Merge "Add quality to LocationRequest/ProviderRequest"

This commit is contained in:
TreeHugger Robot
2020-10-15 02:14:41 +00:00
committed by Android (Google) Code Review
18 changed files with 305 additions and 277 deletions

View File

@@ -2179,7 +2179,7 @@ public class DeviceIdleController extends SystemService
if (getContext().getResources().getBoolean( if (getContext().getResources().getBoolean(
com.android.internal.R.bool.config_autoPowerModePrefetchLocation)) { com.android.internal.R.bool.config_autoPowerModePrefetchLocation)) {
mLocationRequest = new LocationRequest.Builder(/*intervalMillis=*/ 0) mLocationRequest = new LocationRequest.Builder(/*intervalMillis=*/ 0)
.setQuality(LocationRequest.ACCURACY_FINE) .setQuality(LocationRequest.QUALITY_HIGH_ACCURACY)
.setMaxUpdates(1) .setMaxUpdates(1)
.build(); .build();
} }

View File

@@ -24099,9 +24099,13 @@ package android.location {
method @IntRange(from=1, to=java.lang.Integer.MAX_VALUE) public int getMaxUpdates(); method @IntRange(from=1, to=java.lang.Integer.MAX_VALUE) public int getMaxUpdates();
method @FloatRange(from=0, to=java.lang.Float.MAX_VALUE) public float getMinUpdateDistanceMeters(); method @FloatRange(from=0, to=java.lang.Float.MAX_VALUE) public float getMinUpdateDistanceMeters();
method @IntRange(from=0) public long getMinUpdateIntervalMillis(); method @IntRange(from=0) public long getMinUpdateIntervalMillis();
method public int getQuality();
method public void writeToParcel(@NonNull android.os.Parcel, int); method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.location.LocationRequest> CREATOR; field @NonNull public static final android.os.Parcelable.Creator<android.location.LocationRequest> CREATOR;
field public static final long PASSIVE_INTERVAL = 9223372036854775807L; // 0x7fffffffffffffffL field public static final long PASSIVE_INTERVAL = 9223372036854775807L; // 0x7fffffffffffffffL
field public static final int QUALITY_BALANCED_POWER_ACCURACY = 102; // 0x66
field public static final int QUALITY_HIGH_ACCURACY = 100; // 0x64
field public static final int QUALITY_LOW_POWER = 104; // 0x68
} }
public static final class LocationRequest.Builder { public static final class LocationRequest.Builder {
@@ -24114,6 +24118,7 @@ package android.location {
method @NonNull public android.location.LocationRequest.Builder setMaxUpdates(@IntRange(from=1, to=java.lang.Integer.MAX_VALUE) int); method @NonNull public android.location.LocationRequest.Builder setMaxUpdates(@IntRange(from=1, to=java.lang.Integer.MAX_VALUE) int);
method @NonNull public android.location.LocationRequest.Builder setMinUpdateDistanceMeters(@FloatRange(from=0, to=java.lang.Float.MAX_VALUE) float); method @NonNull public android.location.LocationRequest.Builder setMinUpdateDistanceMeters(@FloatRange(from=0, to=java.lang.Float.MAX_VALUE) float);
method @NonNull public android.location.LocationRequest.Builder setMinUpdateIntervalMillis(@IntRange(from=0) long); method @NonNull public android.location.LocationRequest.Builder setMinUpdateIntervalMillis(@IntRange(from=0) long);
method @NonNull public android.location.LocationRequest.Builder setQuality(int);
} }
public interface OnNmeaMessageListener { public interface OnNmeaMessageListener {

View File

@@ -4174,7 +4174,6 @@ package android.location {
method @Deprecated public long getInterval(); method @Deprecated public long getInterval();
method @Deprecated public int getNumUpdates(); method @Deprecated public int getNumUpdates();
method @Deprecated @NonNull public String getProvider(); method @Deprecated @NonNull public String getProvider();
method public int getQuality();
method @Deprecated public float getSmallestDisplacement(); method @Deprecated public float getSmallestDisplacement();
method @NonNull public android.os.WorkSource getWorkSource(); method @NonNull public android.os.WorkSource getWorkSource();
method public boolean isHiddenFromAppOps(); method public boolean isHiddenFromAppOps();
@@ -4193,11 +4192,11 @@ package android.location {
method @Deprecated @NonNull public android.location.LocationRequest setQuality(int); method @Deprecated @NonNull public android.location.LocationRequest setQuality(int);
method @Deprecated @NonNull public android.location.LocationRequest setSmallestDisplacement(float); method @Deprecated @NonNull public android.location.LocationRequest setSmallestDisplacement(float);
method @Deprecated public void setWorkSource(@Nullable android.os.WorkSource); method @Deprecated public void setWorkSource(@Nullable android.os.WorkSource);
field public static final int ACCURACY_BLOCK = 102; // 0x66 field @Deprecated public static final int ACCURACY_BLOCK = 102; // 0x66
field public static final int ACCURACY_CITY = 104; // 0x68 field @Deprecated public static final int ACCURACY_CITY = 104; // 0x68
field public static final int ACCURACY_FINE = 100; // 0x64 field @Deprecated public static final int ACCURACY_FINE = 100; // 0x64
field public static final int POWER_HIGH = 203; // 0xcb field @Deprecated public static final int POWER_HIGH = 203; // 0xcb
field public static final int POWER_LOW = 201; // 0xc9 field @Deprecated public static final int POWER_LOW = 201; // 0xc9
field @Deprecated public static final int POWER_NONE = 200; // 0xc8 field @Deprecated public static final int POWER_NONE = 200; // 0xc8
} }
@@ -4205,7 +4204,6 @@ package android.location {
method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_APP_OPS_STATS) public android.location.LocationRequest.Builder setHiddenFromAppOps(boolean); method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_APP_OPS_STATS) public android.location.LocationRequest.Builder setHiddenFromAppOps(boolean);
method @NonNull @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public android.location.LocationRequest.Builder setLocationSettingsIgnored(boolean); method @NonNull @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public android.location.LocationRequest.Builder setLocationSettingsIgnored(boolean);
method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.location.LocationRequest.Builder setLowPower(boolean); method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.location.LocationRequest.Builder setLowPower(boolean);
method @NonNull public android.location.LocationRequest.Builder setQuality(int);
method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public android.location.LocationRequest.Builder setWorkSource(@Nullable android.os.WorkSource); method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public android.location.LocationRequest.Builder setWorkSource(@Nullable android.os.WorkSource);
} }

View File

@@ -1777,11 +1777,11 @@ package android.location {
method public boolean isHiddenFromAppOps(); method public boolean isHiddenFromAppOps();
method public boolean isLocationSettingsIgnored(); method public boolean isLocationSettingsIgnored();
method public boolean isLowPower(); method public boolean isLowPower();
field public static final int ACCURACY_BLOCK = 102; // 0x66 field @Deprecated public static final int ACCURACY_BLOCK = 102; // 0x66
field public static final int ACCURACY_CITY = 104; // 0x68 field @Deprecated public static final int ACCURACY_CITY = 104; // 0x68
field public static final int ACCURACY_FINE = 100; // 0x64 field @Deprecated public static final int ACCURACY_FINE = 100; // 0x64
field public static final int POWER_HIGH = 203; // 0xcb field @Deprecated public static final int POWER_HIGH = 203; // 0xcb
field public static final int POWER_LOW = 201; // 0xc9 field @Deprecated public static final int POWER_LOW = 201; // 0xc9
} }
public static final class LocationRequest.Builder { public static final class LocationRequest.Builder {

View File

@@ -21,6 +21,7 @@ import static java.lang.Math.min;
import android.Manifest; import android.Manifest;
import android.annotation.FloatRange; import android.annotation.FloatRange;
import android.annotation.IntDef;
import android.annotation.IntRange; import android.annotation.IntRange;
import android.annotation.NonNull; import android.annotation.NonNull;
import android.annotation.Nullable; import android.annotation.Nullable;
@@ -38,6 +39,8 @@ import android.util.TimeUtils;
import com.android.internal.util.Preconditions; import com.android.internal.util.Preconditions;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Objects; import java.util.Objects;
@@ -65,16 +68,41 @@ public final class LocationRequest implements Parcelable {
*/ */
public static final long PASSIVE_INTERVAL = Long.MAX_VALUE; public static final long PASSIVE_INTERVAL = Long.MAX_VALUE;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef({QUALITY_LOW_POWER, QUALITY_BALANCED_POWER_ACCURACY, QUALITY_HIGH_ACCURACY})
public @interface Quality {}
/**
* A quality constant indicating a location provider may choose to satisfy this request by
* providing very accurate locations at the expense of potentially increased power usage.
*/
public static final int QUALITY_HIGH_ACCURACY = 100;
/**
* A quality constant indicating a location provider may choose to satisfy this request by
* equally balancing power and accuracy constraints.
*/
public static final int QUALITY_BALANCED_POWER_ACCURACY = 102;
/**
* A quality constant indicating a location provider may choose to satisfy this request by
* providing less accurate locations in order to save power.
*/
public static final int QUALITY_LOW_POWER = 104;
/** /**
* Used with {@link #setQuality} to request the most accurate locations available. * Used with {@link #setQuality} to request the most accurate locations available.
* *
* <p>This may be up to 1 meter accuracy, although this is implementation dependent. * <p>This may be up to 1 meter accuracy, although this is implementation dependent.
* *
* @hide * @hide
* @deprecated Use {@link #QUALITY_HIGH_ACCURACY} instead.
*/ */
@Deprecated
@SystemApi @SystemApi
@TestApi @TestApi
public static final int ACCURACY_FINE = 100; public static final int ACCURACY_FINE = QUALITY_HIGH_ACCURACY;
/** /**
* Used with {@link #setQuality} to request "block" level accuracy. * Used with {@link #setQuality} to request "block" level accuracy.
@@ -84,10 +112,12 @@ public final class LocationRequest implements Parcelable {
* such as this often consumes less power. * such as this often consumes less power.
* *
* @hide * @hide
* @deprecated Use {@link #QUALITY_BALANCED_POWER_ACCURACY} instead.
*/ */
@Deprecated
@SystemApi @SystemApi
@TestApi @TestApi
public static final int ACCURACY_BLOCK = 102; public static final int ACCURACY_BLOCK = QUALITY_BALANCED_POWER_ACCURACY;
/** /**
* Used with {@link #setQuality} to request "city" level accuracy. * Used with {@link #setQuality} to request "city" level accuracy.
@@ -97,10 +127,12 @@ public final class LocationRequest implements Parcelable {
* such as this often consumes less power. * such as this often consumes less power.
* *
* @hide * @hide
* @deprecated Use {@link #QUALITY_LOW_POWER} instead.
*/ */
@Deprecated
@SystemApi @SystemApi
@TestApi @TestApi
public static final int ACCURACY_CITY = 104; public static final int ACCURACY_CITY = QUALITY_LOW_POWER;
/** /**
* Used with {@link #setQuality} to require no direct power impact (passive locations). * Used with {@link #setQuality} to require no direct power impact (passive locations).
@@ -123,7 +155,9 @@ public final class LocationRequest implements Parcelable {
* possible. * possible.
* *
* @hide * @hide
* @deprecated Use {@link #QUALITY_LOW_POWER} instead.
*/ */
@Deprecated
@SystemApi @SystemApi
@TestApi @TestApi
public static final int POWER_LOW = 201; public static final int POWER_LOW = 201;
@@ -134,7 +168,9 @@ public final class LocationRequest implements Parcelable {
* <p>This location request will allow high power location work. * <p>This location request will allow high power location work.
* *
* @hide * @hide
* @deprecated Use {@link #QUALITY_HIGH_ACCURACY} instead.
*/ */
@Deprecated
@SystemApi @SystemApi
@TestApi @TestApi
public static final int POWER_HIGH = 203; public static final int POWER_HIGH = 203;
@@ -144,7 +180,7 @@ public final class LocationRequest implements Parcelable {
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, publicAlternatives = "Use {@link " @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, publicAlternatives = "Use {@link "
+ "LocationManager} methods to provide the provider explicitly.") + "LocationManager} methods to provide the provider explicitly.")
@Nullable private String mProvider; @Nullable private String mProvider;
private int mQuality; private @Quality int mQuality;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, publicAlternatives = "Use {@link " @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, publicAlternatives = "Use {@link "
+ "LocationRequest} instead.") + "LocationRequest} instead.")
private long mInterval; private long mInterval;
@@ -168,7 +204,7 @@ public final class LocationRequest implements Parcelable {
public static LocationRequest create() { public static LocationRequest create() {
// 60 minutes is the default legacy interval // 60 minutes is the default legacy interval
return new LocationRequest.Builder(60 * 60 * 1000) return new LocationRequest.Builder(60 * 60 * 1000)
.setQuality(POWER_LOW) .setQuality(QUALITY_LOW_POWER)
.build(); .build();
} }
@@ -241,7 +277,7 @@ public final class LocationRequest implements Parcelable {
private LocationRequest( private LocationRequest(
@Nullable String provider, @Nullable String provider,
long intervalMillis, long intervalMillis,
int quality, @Quality int quality,
long expireAtRealtimeMillis, long expireAtRealtimeMillis,
long durationMillis, long durationMillis,
int maxUpdates, int maxUpdates,
@@ -251,9 +287,6 @@ public final class LocationRequest implements Parcelable {
boolean locationSettingsIgnored, boolean locationSettingsIgnored,
boolean lowPower, boolean lowPower,
WorkSource workSource) { WorkSource workSource) {
Preconditions.checkArgument(intervalMillis != PASSIVE_INTERVAL || quality == POWER_NONE);
Preconditions.checkArgument(minUpdateIntervalMillis <= intervalMillis);
mProvider = provider; mProvider = provider;
mInterval = intervalMillis; mInterval = intervalMillis;
mQuality = quality; mQuality = quality;
@@ -297,24 +330,39 @@ public final class LocationRequest implements Parcelable {
@SystemApi @SystemApi
@Deprecated @Deprecated
public @NonNull LocationRequest setQuality(int quality) { public @NonNull LocationRequest setQuality(int quality) {
mQuality = Builder.checkQuality(quality, true); switch (quality) {
case POWER_HIGH:
// fall through
case ACCURACY_FINE:
mQuality = QUALITY_HIGH_ACCURACY;
break;
case ACCURACY_BLOCK:
mQuality = QUALITY_BALANCED_POWER_ACCURACY;
break;
case POWER_LOW:
// fall through
case ACCURACY_CITY:
mQuality = QUALITY_LOW_POWER;
break;
case POWER_NONE:
mInterval = PASSIVE_INTERVAL;
break;
default:
throw new IllegalArgumentException("invalid quality: " + quality);
}
return this; return this;
} }
/** /**
* Returns the quality of the location request. * Returns the quality hint for this location request. The quality hint informs the provider how
* it should attempt to manage any accuracy vs power tradeoffs while attempting to satisfy this
* location request.
* *
* @return the quality of the location request * @return the desired quality tradeoffs between accuracy and power
*
* @hide
*/ */
@SystemApi public @Quality int getQuality() {
public int getQuality() { return mQuality;
if (mInterval == PASSIVE_INTERVAL) {
return POWER_NONE;
} else {
return mQuality;
}
} }
/** /**
@@ -749,97 +797,65 @@ public final class LocationRequest implements Parcelable {
if (mProvider != null) { if (mProvider != null) {
s.append(mProvider).append(" "); s.append(mProvider).append(" ");
} }
if (mQuality != POWER_NONE && mQuality != ACCURACY_BLOCK) {
s.append(qualityToString(mQuality)).append(" ");
}
if (mInterval != PASSIVE_INTERVAL) { if (mInterval != PASSIVE_INTERVAL) {
s.append("@"); s.append("@");
TimeUtils.formatDuration(mInterval, s); TimeUtils.formatDuration(mInterval, s);
switch (mQuality) {
case QUALITY_HIGH_ACCURACY:
s.append(" HIGH_ACCURACY");
break;
case QUALITY_BALANCED_POWER_ACCURACY:
s.append(" BALANCED");
break;
case QUALITY_LOW_POWER:
s.append(" LOW_POWER");
break;
}
} else { } else {
s.append("PASSIVE"); s.append("PASSIVE");
} }
if (mExpireAtRealtimeMillis != Long.MAX_VALUE) { if (mExpireAtRealtimeMillis != Long.MAX_VALUE) {
s.append(" expireAt=").append(TimeUtils.formatRealtime(mExpireAtRealtimeMillis)); s.append(", expireAt=").append(TimeUtils.formatRealtime(mExpireAtRealtimeMillis));
} }
if (mDurationMillis != Long.MAX_VALUE) { if (mDurationMillis != Long.MAX_VALUE) {
s.append(" duration="); s.append(", duration=");
TimeUtils.formatDuration(mDurationMillis, s); TimeUtils.formatDuration(mDurationMillis, s);
} }
if (mMaxUpdates != Integer.MAX_VALUE) { if (mMaxUpdates != Integer.MAX_VALUE) {
s.append(" maxUpdates=").append(mMaxUpdates); s.append(", maxUpdates=").append(mMaxUpdates);
} }
if (mMinUpdateIntervalMillis != IMPLICIT_MIN_UPDATE_INTERVAL if (mMinUpdateIntervalMillis != IMPLICIT_MIN_UPDATE_INTERVAL
&& mMinUpdateIntervalMillis < mInterval) { && mMinUpdateIntervalMillis < mInterval) {
s.append(" minUpdateInterval="); s.append(", minUpdateInterval=");
TimeUtils.formatDuration(mMinUpdateIntervalMillis, s); TimeUtils.formatDuration(mMinUpdateIntervalMillis, s);
} }
if (mMinUpdateDistanceMeters > 0.0) { if (mMinUpdateDistanceMeters > 0.0) {
s.append(" minUpdateDistance=").append(mMinUpdateDistanceMeters); s.append(", minUpdateDistance=").append(mMinUpdateDistanceMeters);
} }
if (mLowPower) { if (mLowPower) {
s.append(" lowPower"); s.append(", lowPower");
} }
if (mHideFromAppOps) { if (mHideFromAppOps) {
s.append(" hiddenFromAppOps"); s.append(", hiddenFromAppOps");
} }
if (mLocationSettingsIgnored) { if (mLocationSettingsIgnored) {
s.append(" locationSettingsIgnored"); s.append(", locationSettingsIgnored");
} }
if (mWorkSource != null) { if (mWorkSource != null && !mWorkSource.isEmpty()) {
s.append(" ").append(mWorkSource); s.append(", ").append(mWorkSource);
} }
s.append(']'); s.append(']');
return s.toString(); return s.toString();
} }
private static String qualityToString(int quality) {
switch (quality) {
case ACCURACY_FINE:
return "ACCURACY_FINE";
case ACCURACY_BLOCK:
return "ACCURACY_BLOCK";
case ACCURACY_CITY:
return "ACCURACY_CITY";
case POWER_NONE:
return "POWER_NONE";
case POWER_LOW:
return "POWER_LOW";
case POWER_HIGH:
return "POWER_HIGH";
default:
return "???";
}
}
/** /**
* A builder class for {@link LocationRequest}. * A builder class for {@link LocationRequest}.
*/ */
public static final class Builder { public static final class Builder {
private static int checkQuality(int quality, boolean allowDeprecated) {
switch (quality) {
case ACCURACY_FINE:
// fall through
case ACCURACY_BLOCK:
// fall through
case ACCURACY_CITY:
// fall through
case POWER_LOW:
// fall through
case POWER_HIGH:
return quality;
case POWER_NONE:
if (allowDeprecated) {
return quality;
}
// fall through
default:
throw new IllegalArgumentException("invalid quality: " + quality);
}
}
private long mIntervalMillis; private long mIntervalMillis;
private int mQuality; private @Quality int mQuality;
private long mDurationMillis; private long mDurationMillis;
private int mMaxUpdates; private int mMaxUpdates;
private long mMinUpdateIntervalMillis; private long mMinUpdateIntervalMillis;
@@ -857,7 +873,7 @@ public final class LocationRequest implements Parcelable {
// gives us a range check // gives us a range check
setIntervalMillis(intervalMillis); setIntervalMillis(intervalMillis);
mQuality = ACCURACY_BLOCK; mQuality = QUALITY_BALANCED_POWER_ACCURACY;
mDurationMillis = Long.MAX_VALUE; mDurationMillis = Long.MAX_VALUE;
mMaxUpdates = Integer.MAX_VALUE; mMaxUpdates = Integer.MAX_VALUE;
mMinUpdateIntervalMillis = IMPLICIT_MIN_UPDATE_INTERVAL; mMinUpdateIntervalMillis = IMPLICIT_MIN_UPDATE_INTERVAL;
@@ -885,9 +901,6 @@ public final class LocationRequest implements Parcelable {
// handle edge cases that can only happen with location request that has been modified // handle edge cases that can only happen with location request that has been modified
// by deprecated SystemApi methods // by deprecated SystemApi methods
if (mQuality == POWER_NONE) {
mIntervalMillis = PASSIVE_INTERVAL;
}
if (mIntervalMillis == PASSIVE_INTERVAL if (mIntervalMillis == PASSIVE_INTERVAL
&& mMinUpdateIntervalMillis == IMPLICIT_MIN_UPDATE_INTERVAL) { && mMinUpdateIntervalMillis == IMPLICIT_MIN_UPDATE_INTERVAL) {
// this is the legacy default minimum update interval, so if we're forced to // this is the legacy default minimum update interval, so if we're forced to
@@ -914,11 +927,17 @@ public final class LocationRequest implements Parcelable {
} }
/** /**
* @hide * Sets the request quality. The quality is a hint to providers on how they should weigh
* power vs accuracy tradeoffs. High accuracy locations may cost more power to produce, and
* lower accuracy locations may cost less power to produce. Defaults to
* {@link #QUALITY_BALANCED_POWER_ACCURACY}.
*/ */
@SystemApi public @NonNull Builder setQuality(@Quality int quality) {
public @NonNull Builder setQuality(int quality) { Preconditions.checkArgument(
mQuality = checkQuality(quality, false); quality == QUALITY_LOW_POWER || quality == QUALITY_BALANCED_POWER_ACCURACY
|| quality == QUALITY_HIGH_ACCURACY,
"quality must be a defined QUALITY constant, not " + quality);
mQuality = quality;
return this; return this;
} }
@@ -1102,7 +1121,7 @@ public final class LocationRequest implements Parcelable {
return new LocationRequest( return new LocationRequest(
null, null,
mIntervalMillis, mIntervalMillis,
mIntervalMillis != PASSIVE_INTERVAL ? mQuality : POWER_NONE, mQuality,
Long.MAX_VALUE, Long.MAX_VALUE,
mDurationMillis, mDurationMillis,
mMaxUpdates, mMaxUpdates,

View File

@@ -16,10 +16,15 @@
package com.android.internal.location; package com.android.internal.location;
import static android.location.LocationRequest.QUALITY_BALANCED_POWER_ACCURACY;
import static android.location.LocationRequest.QUALITY_HIGH_ACCURACY;
import static android.location.LocationRequest.QUALITY_LOW_POWER;
import android.annotation.IntRange; import android.annotation.IntRange;
import android.annotation.NonNull; import android.annotation.NonNull;
import android.compat.annotation.UnsupportedAppUsage; import android.compat.annotation.UnsupportedAppUsage;
import android.location.LocationRequest; import android.location.LocationRequest;
import android.location.LocationRequest.Quality;
import android.os.Build; import android.os.Build;
import android.os.Parcel; import android.os.Parcel;
import android.os.Parcelable; import android.os.Parcelable;
@@ -41,7 +46,7 @@ public final class ProviderRequest implements Parcelable {
public static final long INTERVAL_DISABLED = Long.MAX_VALUE; public static final long INTERVAL_DISABLED = Long.MAX_VALUE;
public static final ProviderRequest EMPTY_REQUEST = new ProviderRequest( public static final ProviderRequest EMPTY_REQUEST = new ProviderRequest(
INTERVAL_DISABLED, false, false, Collections.emptyList(), new WorkSource()); INTERVAL_DISABLED, QUALITY_BALANCED_POWER_ACCURACY, false, false, new WorkSource());
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, publicAlternatives = "{@link " @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, publicAlternatives = "{@link "
+ "ProviderRequest}") + "ProviderRequest}")
@@ -49,6 +54,7 @@ public final class ProviderRequest implements Parcelable {
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, publicAlternatives = "{@link " @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, publicAlternatives = "{@link "
+ "ProviderRequest}") + "ProviderRequest}")
public final long interval; public final long interval;
private final @Quality int mQuality;
private final boolean mLowPower; private final boolean mLowPower;
private final boolean mLocationSettingsIgnored; private final boolean mLocationSettingsIgnored;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, publicAlternatives = "{@link " @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, publicAlternatives = "{@link "
@@ -56,15 +62,24 @@ public final class ProviderRequest implements Parcelable {
public final List<LocationRequest> locationRequests; public final List<LocationRequest> locationRequests;
private final WorkSource mWorkSource; private final WorkSource mWorkSource;
private ProviderRequest(long intervalMillis, boolean lowPower, private ProviderRequest(long intervalMillis, @Quality int quality, boolean lowPower,
boolean locationSettingsIgnored, @NonNull List<LocationRequest> locationRequests, boolean locationSettingsIgnored, @NonNull WorkSource workSource) {
@NonNull WorkSource workSource) {
reportLocation = intervalMillis != INTERVAL_DISABLED; reportLocation = intervalMillis != INTERVAL_DISABLED;
interval = intervalMillis; interval = intervalMillis;
mQuality = quality;
mLowPower = lowPower; mLowPower = lowPower;
mLocationSettingsIgnored = locationSettingsIgnored; mLocationSettingsIgnored = locationSettingsIgnored;
this.locationRequests = locationRequests; if (intervalMillis != INTERVAL_DISABLED) {
mWorkSource = workSource; locationRequests = Collections.singletonList(new LocationRequest.Builder(intervalMillis)
.setQuality(quality)
.setLowPower(lowPower)
.setLocationSettingsIgnored(locationSettingsIgnored)
.setWorkSource(workSource)
.build());
} else {
locationRequests = Collections.emptyList();
}
mWorkSource = Objects.requireNonNull(workSource);
} }
/** /**
@@ -83,6 +98,15 @@ public final class ProviderRequest implements Parcelable {
return interval; return interval;
} }
/**
* The quality hint for this location request. The quality hint informs the provider how it
* should attempt to manage any accuracy vs power tradeoffs while attempting to satisfy this
* provider request.
*/
public @Quality int getQuality() {
return mQuality;
}
/** /**
* Whether any applicable hardware low power modes should be used to satisfy this request. * Whether any applicable hardware low power modes should be used to satisfy this request.
*/ */
@@ -99,13 +123,6 @@ public final class ProviderRequest implements Parcelable {
return mLocationSettingsIgnored; return mLocationSettingsIgnored;
} }
/**
* The full list of location requests contributing to this provider request.
*/
public @NonNull List<LocationRequest> getLocationRequests() {
return locationRequests;
}
/** /**
* The power blame for this provider request. * The power blame for this provider request.
*/ */
@@ -117,13 +134,17 @@ public final class ProviderRequest implements Parcelable {
new Parcelable.Creator<ProviderRequest>() { new Parcelable.Creator<ProviderRequest>() {
@Override @Override
public ProviderRequest createFromParcel(Parcel in) { public ProviderRequest createFromParcel(Parcel in) {
return new ProviderRequest( long intervalMillis = in.readLong();
/* intervalMillis= */ in.readLong(), if (intervalMillis == INTERVAL_DISABLED) {
/* lowPower= */ in.readBoolean(), return EMPTY_REQUEST;
/* locationSettingsIgnored= */ in.readBoolean(), } else {
/* locationRequests= */ return new ProviderRequest(
in.createTypedArrayList(LocationRequest.CREATOR), intervalMillis,
/* workSource= */ in.readTypedObject(WorkSource.CREATOR)); /* quality= */ in.readInt(),
/* lowPower= */ in.readBoolean(),
/* locationSettingsIgnored= */ in.readBoolean(),
/* workSource= */ in.readTypedObject(WorkSource.CREATOR));
}
} }
@Override @Override
@@ -140,10 +161,12 @@ public final class ProviderRequest implements Parcelable {
@Override @Override
public void writeToParcel(Parcel parcel, int flags) { public void writeToParcel(Parcel parcel, int flags) {
parcel.writeLong(interval); parcel.writeLong(interval);
parcel.writeBoolean(mLowPower); if (interval != INTERVAL_DISABLED) {
parcel.writeBoolean(mLocationSettingsIgnored); parcel.writeInt(mQuality);
parcel.writeTypedList(locationRequests); parcel.writeBoolean(mLowPower);
parcel.writeTypedObject(mWorkSource, flags); parcel.writeBoolean(mLocationSettingsIgnored);
parcel.writeTypedObject(mWorkSource, flags);
}
} }
@Override @Override
@@ -160,16 +183,16 @@ public final class ProviderRequest implements Parcelable {
return that.interval == INTERVAL_DISABLED; return that.interval == INTERVAL_DISABLED;
} else { } else {
return interval == that.interval return interval == that.interval
&& mQuality == that.mQuality
&& mLowPower == that.mLowPower && mLowPower == that.mLowPower
&& mLocationSettingsIgnored == that.mLocationSettingsIgnored && mLocationSettingsIgnored == that.mLocationSettingsIgnored
&& locationRequests.equals(that.locationRequests)
&& mWorkSource.equals(that.mWorkSource); && mWorkSource.equals(that.mWorkSource);
} }
} }
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(interval, mWorkSource); return Objects.hash(interval, mQuality, mWorkSource);
} }
@Override @Override
@@ -179,6 +202,13 @@ public final class ProviderRequest implements Parcelable {
if (interval != INTERVAL_DISABLED) { if (interval != INTERVAL_DISABLED) {
s.append("@"); s.append("@");
TimeUtils.formatDuration(interval, s); TimeUtils.formatDuration(interval, s);
if (mQuality != QUALITY_BALANCED_POWER_ACCURACY) {
if (mQuality == QUALITY_HIGH_ACCURACY) {
s.append(", HIGH_ACCURACY");
} else if (mQuality == QUALITY_LOW_POWER) {
s.append(", LOW_POWER");
}
}
if (mLowPower) { if (mLowPower) {
s.append(", lowPower"); s.append(", lowPower");
} }
@@ -200,9 +230,9 @@ public final class ProviderRequest implements Parcelable {
*/ */
public static class Builder { public static class Builder {
private long mIntervalMillis = INTERVAL_DISABLED; private long mIntervalMillis = INTERVAL_DISABLED;
private int mQuality = QUALITY_BALANCED_POWER_ACCURACY;
private boolean mLowPower; private boolean mLowPower;
private boolean mLocationSettingsIgnored; private boolean mLocationSettingsIgnored;
private List<LocationRequest> mLocationRequests = Collections.emptyList();
private WorkSource mWorkSource = new WorkSource(); private WorkSource mWorkSource = new WorkSource();
/** /**
@@ -215,6 +245,20 @@ public final class ProviderRequest implements Parcelable {
return this; return this;
} }
/**
* Sets the request quality. The quality is a hint to providers on how they should weigh
* power vs accuracy tradeoffs. High accuracy locations may cost more power to produce, and
* lower accuracy locations may cost less power to produce. Defaults to
* {@link LocationRequest#QUALITY_BALANCED_POWER_ACCURACY}.
*/
public @NonNull Builder setQuality(@Quality int quality) {
Preconditions.checkArgument(
quality == QUALITY_LOW_POWER || quality == QUALITY_BALANCED_POWER_ACCURACY
|| quality == QUALITY_HIGH_ACCURACY);
mQuality = quality;
return this;
}
/** /**
* Sets whether hardware low power mode should be used. False by default. * Sets whether hardware low power mode should be used. False by default.
*/ */
@@ -231,15 +275,6 @@ public final class ProviderRequest implements Parcelable {
return this; return this;
} }
/**
* Sets the {@link LocationRequest}s associated with this request. Empty by default.
*/
public @NonNull Builder setLocationRequests(
@NonNull List<LocationRequest> locationRequests) {
this.mLocationRequests = Objects.requireNonNull(locationRequests);
return this;
}
/** /**
* Sets the work source for power blame. Empty by default. * Sets the work source for power blame. Empty by default.
*/ */
@@ -255,8 +290,8 @@ public final class ProviderRequest implements Parcelable {
if (mIntervalMillis == INTERVAL_DISABLED) { if (mIntervalMillis == INTERVAL_DISABLED) {
return EMPTY_REQUEST; return EMPTY_REQUEST;
} else { } else {
return new ProviderRequest(mIntervalMillis, mLowPower, mLocationSettingsIgnored, return new ProviderRequest(mIntervalMillis, mQuality, mLowPower,
mLocationRequests, mWorkSource); mLocationSettingsIgnored, mWorkSource);
} }
} }
} }

View File

@@ -29,18 +29,18 @@ package com.android.location.provider {
field public static final String FUSED_PROVIDER = "fused"; field public static final String FUSED_PROVIDER = "fused";
} }
public final class LocationRequestUnbundled { @Deprecated public final class LocationRequestUnbundled {
method public long getFastestInterval(); method @Deprecated public long getFastestInterval();
method public long getInterval(); method @Deprecated public long getInterval();
method public int getQuality(); method @Deprecated @android.location.LocationRequest.Quality public int getQuality();
method public float getSmallestDisplacement(); method @Deprecated public float getSmallestDisplacement();
method public boolean isLocationSettingsIgnored(); method @Deprecated public boolean isLocationSettingsIgnored();
field public static final int ACCURACY_BLOCK = 102; // 0x66 field @Deprecated public static final int ACCURACY_BLOCK = 102; // 0x66
field public static final int ACCURACY_CITY = 104; // 0x68 field @Deprecated public static final int ACCURACY_CITY = 104; // 0x68
field public static final int ACCURACY_FINE = 100; // 0x64 field @Deprecated public static final int ACCURACY_FINE = 100; // 0x64
field public static final int POWER_HIGH = 203; // 0xcb field @Deprecated public static final int POWER_HIGH = 203; // 0xcb
field public static final int POWER_LOW = 201; // 0xc9 field @Deprecated public static final int POWER_LOW = 201; // 0xc9
field public static final int POWER_NONE = 200; // 0xc8 field @Deprecated public static final int POWER_NONE = 200; // 0xc8
} }
public final class ProviderPropertiesUnbundled { public final class ProviderPropertiesUnbundled {
@@ -49,7 +49,8 @@ package com.android.location.provider {
public final class ProviderRequestUnbundled { public final class ProviderRequestUnbundled {
method public long getInterval(); method public long getInterval();
method @NonNull public java.util.List<com.android.location.provider.LocationRequestUnbundled> getLocationRequests(); method @Deprecated @NonNull public java.util.List<com.android.location.provider.LocationRequestUnbundled> getLocationRequests();
method @android.location.LocationRequest.Quality @RequiresApi(android.os.Build.VERSION_CODES.S) public int getQuality();
method public boolean getReportLocation(); method public boolean getReportLocation();
method @NonNull @RequiresApi(android.os.Build.VERSION_CODES.S) public android.os.WorkSource getWorkSource(); method @NonNull @RequiresApi(android.os.Build.VERSION_CODES.S) public android.os.WorkSource getWorkSource();
method @RequiresApi(android.os.Build.VERSION_CODES.Q) public boolean isLocationSettingsIgnored(); method @RequiresApi(android.os.Build.VERSION_CODES.Q) public boolean isLocationSettingsIgnored();

View File

@@ -17,6 +17,7 @@
package com.android.location.provider; package com.android.location.provider;
import android.location.LocationRequest; import android.location.LocationRequest;
import android.location.LocationRequest.Quality;
/** /**
* This class is an interface to LocationRequests for unbundled applications. * This class is an interface to LocationRequests for unbundled applications.
@@ -24,55 +25,50 @@ import android.location.LocationRequest;
* <p>IMPORTANT: This class is effectively a public API for unbundled * <p>IMPORTANT: This class is effectively a public API for unbundled
* applications, and must remain API stable. See README.txt in the root * applications, and must remain API stable. See README.txt in the root
* of this package for more information. * of this package for more information.
*
* @deprecated Do not use.
*/ */
@Deprecated
public final class LocationRequestUnbundled { public final class LocationRequestUnbundled {
/** /**
* Returned by {@link #getQuality} when requesting the most accurate locations available. * @deprecated Use {@link LocationRequest#QUALITY_HIGH_ACCURACY} instead.
*
* <p>This may be up to 1 meter accuracy, although this is implementation dependent.
*/ */
@Deprecated
public static final int ACCURACY_FINE = LocationRequest.ACCURACY_FINE; public static final int ACCURACY_FINE = LocationRequest.ACCURACY_FINE;
/** /**
* Returned by {@link #getQuality} when requesting "block" level accuracy. * @deprecated Use {@link LocationRequest#QUALITY_BALANCED_POWER_ACCURACY} instead.
*
* <p>Block level accuracy is considered to be about 100 meter accuracy,
* although this is implementation dependent. Using a coarse accuracy
* such as this often consumes less power.
*/ */
@Deprecated
public static final int ACCURACY_BLOCK = LocationRequest.ACCURACY_BLOCK; public static final int ACCURACY_BLOCK = LocationRequest.ACCURACY_BLOCK;
/** /**
* Returned by {@link #getQuality} when requesting "city" level accuracy. * @deprecated Use {@link LocationRequest#QUALITY_LOW_POWER} instead.
*
* <p>City level accuracy is considered to be about 10km accuracy,
* although this is implementation dependent. Using a coarse accuracy
* such as this often consumes less power.
*/ */
@Deprecated
public static final int ACCURACY_CITY = LocationRequest.ACCURACY_CITY; public static final int ACCURACY_CITY = LocationRequest.ACCURACY_CITY;
/** /**
* Returned by {@link #getQuality} when requiring no direct power impact (passive locations). * @deprecated Do not use.
*
* <p>This location request will not trigger any active location requests,
* but will receive locations triggered by other applications. Your application
* will not receive any direct power blame for location work.
*/ */
@Deprecated
public static final int POWER_NONE = LocationRequest.POWER_NONE; public static final int POWER_NONE = LocationRequest.POWER_NONE;
/**
* Returned by {@link #getQuality} when requesting low power impact.
*
* <p>This location request will avoid high power location work where
* possible.
*/
public static final int POWER_LOW = LocationRequest.POWER_LOW;
/** /**
* Returned by {@link #getQuality} when allowing high power consumption for location. * @deprecated Use {@link LocationRequest#QUALITY_LOW_POWER} instead.
*
* <p>This location request will allow high power location work.
*/ */
@Deprecated
public static final int POWER_LOW = LocationRequest.POWER_LOW;
/**
* @deprecated Use {@link LocationRequest#QUALITY_BALANCED_POWER_ACCURACY} instead.
*/
@Deprecated
public static final int POWER_HIGH = LocationRequest.POWER_HIGH; public static final int POWER_HIGH = LocationRequest.POWER_HIGH;
private final LocationRequest delegate; private final LocationRequest delegate;
@@ -102,9 +98,9 @@ public final class LocationRequestUnbundled {
/** /**
* Get the quality of the request. * Get the quality of the request.
* *
* @return an accuracy or power constant * @return a {@link LocationRequest} QUALITY_* constant
*/ */
public int getQuality() { public @Quality int getQuality() {
return delegate.getQuality(); return delegate.getQuality();
} }

View File

@@ -25,7 +25,7 @@ import androidx.annotation.RequiresApi;
import com.android.internal.location.ProviderRequest; import com.android.internal.location.ProviderRequest;
import java.util.ArrayList; import java.util.Collections;
import java.util.List; import java.util.List;
/** /**
@@ -56,6 +56,16 @@ public final class ProviderRequestUnbundled {
return mRequest.isActive(); return mRequest.isActive();
} }
/**
* The quality hint for this location request. The quality hint informs the provider how it
* should attempt to manage any accuracy vs power tradeoffs while attempting to satisfy this
* provider request.
*/
@RequiresApi(Build.VERSION_CODES.S)
public @LocationRequest.Quality int getQuality() {
return mRequest.getQuality();
}
/** /**
* The interval at which a provider should report location. Will return * The interval at which a provider should report location. Will return
* {@link #INTERVAL_DISABLED} for an inactive request. * {@link #INTERVAL_DISABLED} for an inactive request.
@@ -84,14 +94,22 @@ public final class ProviderRequestUnbundled {
/** /**
* The full list of location requests contributing to this provider request. * The full list of location requests contributing to this provider request.
*
* @deprecated Do not use.
*/ */
@Deprecated
public @NonNull List<LocationRequestUnbundled> getLocationRequests() { public @NonNull List<LocationRequestUnbundled> getLocationRequests() {
List<LocationRequestUnbundled> result = new ArrayList<>( if (!mRequest.isActive()) {
mRequest.getLocationRequests().size()); return Collections.emptyList();
for (LocationRequest r : mRequest.getLocationRequests()) {
result.add(new LocationRequestUnbundled(r));
} }
return result;
return Collections.singletonList(new LocationRequestUnbundled(
new LocationRequest.Builder(mRequest.getIntervalMillis())
.setQuality(mRequest.getQuality())
.setLowPower(mRequest.isLowPower())
.setLocationSettingsIgnored(mRequest.isLocationSettingsIgnored())
.setWorkSource(mRequest.getWorkSource())
.build()));
} }
/** /**

View File

@@ -24081,9 +24081,13 @@ package android.location {
method @IntRange(from=1, to=java.lang.Integer.MAX_VALUE) public int getMaxUpdates(); method @IntRange(from=1, to=java.lang.Integer.MAX_VALUE) public int getMaxUpdates();
method @FloatRange(from=0, to=java.lang.Float.MAX_VALUE) public float getMinUpdateDistanceMeters(); method @FloatRange(from=0, to=java.lang.Float.MAX_VALUE) public float getMinUpdateDistanceMeters();
method @IntRange(from=0) public long getMinUpdateIntervalMillis(); method @IntRange(from=0) public long getMinUpdateIntervalMillis();
method public int getQuality();
method public void writeToParcel(@NonNull android.os.Parcel, int); method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.location.LocationRequest> CREATOR; field @NonNull public static final android.os.Parcelable.Creator<android.location.LocationRequest> CREATOR;
field public static final long PASSIVE_INTERVAL = 9223372036854775807L; // 0x7fffffffffffffffL field public static final long PASSIVE_INTERVAL = 9223372036854775807L; // 0x7fffffffffffffffL
field public static final int QUALITY_BALANCED_POWER_ACCURACY = 102; // 0x66
field public static final int QUALITY_HIGH_ACCURACY = 100; // 0x64
field public static final int QUALITY_LOW_POWER = 104; // 0x68
} }
public static final class LocationRequest.Builder { public static final class LocationRequest.Builder {
@@ -24096,6 +24100,7 @@ package android.location {
method @NonNull public android.location.LocationRequest.Builder setMaxUpdates(@IntRange(from=1, to=java.lang.Integer.MAX_VALUE) int); method @NonNull public android.location.LocationRequest.Builder setMaxUpdates(@IntRange(from=1, to=java.lang.Integer.MAX_VALUE) int);
method @NonNull public android.location.LocationRequest.Builder setMinUpdateDistanceMeters(@FloatRange(from=0, to=java.lang.Float.MAX_VALUE) float); method @NonNull public android.location.LocationRequest.Builder setMinUpdateDistanceMeters(@FloatRange(from=0, to=java.lang.Float.MAX_VALUE) float);
method @NonNull public android.location.LocationRequest.Builder setMinUpdateIntervalMillis(@IntRange(from=0) long); method @NonNull public android.location.LocationRequest.Builder setMinUpdateIntervalMillis(@IntRange(from=0) long);
method @NonNull public android.location.LocationRequest.Builder setQuality(int);
} }
public interface OnNmeaMessageListener { public interface OnNmeaMessageListener {

View File

@@ -4114,7 +4114,6 @@ package android.location {
method @Deprecated public long getInterval(); method @Deprecated public long getInterval();
method @Deprecated public int getNumUpdates(); method @Deprecated public int getNumUpdates();
method @Deprecated @NonNull public String getProvider(); method @Deprecated @NonNull public String getProvider();
method public int getQuality();
method @Deprecated public float getSmallestDisplacement(); method @Deprecated public float getSmallestDisplacement();
method @NonNull public android.os.WorkSource getWorkSource(); method @NonNull public android.os.WorkSource getWorkSource();
method public boolean isHiddenFromAppOps(); method public boolean isHiddenFromAppOps();
@@ -4133,11 +4132,11 @@ package android.location {
method @Deprecated @NonNull public android.location.LocationRequest setQuality(int); method @Deprecated @NonNull public android.location.LocationRequest setQuality(int);
method @Deprecated @NonNull public android.location.LocationRequest setSmallestDisplacement(float); method @Deprecated @NonNull public android.location.LocationRequest setSmallestDisplacement(float);
method @Deprecated public void setWorkSource(@Nullable android.os.WorkSource); method @Deprecated public void setWorkSource(@Nullable android.os.WorkSource);
field public static final int ACCURACY_BLOCK = 102; // 0x66 field @Deprecated public static final int ACCURACY_BLOCK = 102; // 0x66
field public static final int ACCURACY_CITY = 104; // 0x68 field @Deprecated public static final int ACCURACY_CITY = 104; // 0x68
field public static final int ACCURACY_FINE = 100; // 0x64 field @Deprecated public static final int ACCURACY_FINE = 100; // 0x64
field public static final int POWER_HIGH = 203; // 0xcb field @Deprecated public static final int POWER_HIGH = 203; // 0xcb
field public static final int POWER_LOW = 201; // 0xc9 field @Deprecated public static final int POWER_LOW = 201; // 0xc9
field @Deprecated public static final int POWER_NONE = 200; // 0xc8 field @Deprecated public static final int POWER_NONE = 200; // 0xc8
} }
@@ -4145,7 +4144,6 @@ package android.location {
method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_APP_OPS_STATS) public android.location.LocationRequest.Builder setHiddenFromAppOps(boolean); method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_APP_OPS_STATS) public android.location.LocationRequest.Builder setHiddenFromAppOps(boolean);
method @NonNull @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public android.location.LocationRequest.Builder setLocationSettingsIgnored(boolean); method @NonNull @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public android.location.LocationRequest.Builder setLocationSettingsIgnored(boolean);
method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.location.LocationRequest.Builder setLowPower(boolean); method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.location.LocationRequest.Builder setLowPower(boolean);
method @NonNull public android.location.LocationRequest.Builder setQuality(int);
method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public android.location.LocationRequest.Builder setWorkSource(@Nullable android.os.WorkSource); method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public android.location.LocationRequest.Builder setWorkSource(@Nullable android.os.WorkSource);
} }

View File

@@ -19,6 +19,9 @@ package com.android.location.fused;
import static android.content.Intent.ACTION_USER_SWITCHED; import static android.content.Intent.ACTION_USER_SWITCHED;
import static android.location.LocationManager.GPS_PROVIDER; import static android.location.LocationManager.GPS_PROVIDER;
import static android.location.LocationManager.NETWORK_PROVIDER; import static android.location.LocationManager.NETWORK_PROVIDER;
import static android.location.LocationRequest.QUALITY_LOW_POWER;
import static com.android.location.provider.ProviderRequestUnbundled.INTERVAL_DISABLED;
import android.annotation.Nullable; import android.annotation.Nullable;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
@@ -35,7 +38,6 @@ import android.os.WorkSource;
import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.GuardedBy;
import com.android.internal.location.ProviderRequest; import com.android.internal.location.ProviderRequest;
import com.android.location.provider.LocationProviderBase; import com.android.location.provider.LocationProviderBase;
import com.android.location.provider.LocationRequestUnbundled;
import com.android.location.provider.ProviderPropertiesUnbundled; import com.android.location.provider.ProviderPropertiesUnbundled;
import com.android.location.provider.ProviderRequestUnbundled; import com.android.location.provider.ProviderRequestUnbundled;
@@ -147,8 +149,8 @@ public class FusedLocationProvider extends LocationProviderBase {
mRequest = new ProviderRequestUnbundled(ProviderRequest.EMPTY_REQUEST); mRequest = new ProviderRequestUnbundled(ProviderRequest.EMPTY_REQUEST);
mWorkSource = new WorkSource(); mWorkSource = new WorkSource();
mGpsInterval = Long.MAX_VALUE; mGpsInterval = INTERVAL_DISABLED;
mNetworkInterval = Long.MAX_VALUE; mNetworkInterval = INTERVAL_DISABLED;
} }
void start() { void start() {
@@ -175,30 +177,9 @@ public class FusedLocationProvider extends LocationProviderBase {
@GuardedBy("mLock") @GuardedBy("mLock")
private void updateRequirementsLocked() { private void updateRequirementsLocked() {
long gpsInterval = Long.MAX_VALUE; long gpsInterval = mRequest.getQuality() < QUALITY_LOW_POWER ? mRequest.getInterval()
long networkInterval = Long.MAX_VALUE; : INTERVAL_DISABLED;
if (mRequest.getReportLocation()) { long networkInterval = mRequest.getInterval();
for (LocationRequestUnbundled request : mRequest.getLocationRequests()) {
switch (request.getQuality()) {
case LocationRequestUnbundled.ACCURACY_FINE:
case LocationRequestUnbundled.ACCURACY_BLOCK:
case LocationRequestUnbundled.POWER_HIGH:
if (request.getInterval() < gpsInterval) {
gpsInterval = request.getInterval();
}
if (request.getInterval() < networkInterval) {
networkInterval = request.getInterval();
}
break;
case LocationRequestUnbundled.ACCURACY_CITY:
case LocationRequestUnbundled.POWER_LOW:
if (request.getInterval() < networkInterval) {
networkInterval = request.getInterval();
}
break;
}
}
}
if (gpsInterval != mGpsInterval) { if (gpsInterval != mGpsInterval) {
resetProviderRequestLocked(GPS_PROVIDER, mGpsInterval, gpsInterval, mGpsListener); resetProviderRequestLocked(GPS_PROVIDER, mGpsInterval, gpsInterval, mGpsListener);
@@ -214,11 +195,12 @@ public class FusedLocationProvider extends LocationProviderBase {
@GuardedBy("mLock") @GuardedBy("mLock")
private void resetProviderRequestLocked(String provider, long oldInterval, long newInterval, private void resetProviderRequestLocked(String provider, long oldInterval, long newInterval,
LocationListener listener) { LocationListener listener) {
if (oldInterval != Long.MAX_VALUE) { if (oldInterval != INTERVAL_DISABLED && newInterval == INTERVAL_DISABLED) {
mLocationManager.removeUpdates(listener); mLocationManager.removeUpdates(listener);
} }
if (newInterval != Long.MAX_VALUE) { if (newInterval != INTERVAL_DISABLED) {
LocationRequest request = new LocationRequest.Builder(newInterval) LocationRequest request = new LocationRequest.Builder(newInterval)
.setQuality(mRequest.getQuality())
.setLocationSettingsIgnored(mRequest.isLocationSettingsIgnored()) .setLocationSettingsIgnored(mRequest.isLocationSettingsIgnored())
.setWorkSource(mWorkSource) .setWorkSource(mWorkSource)
.build(); .build();
@@ -254,10 +236,10 @@ public class FusedLocationProvider extends LocationProviderBase {
void dump(PrintWriter writer) { void dump(PrintWriter writer) {
synchronized (mLock) { synchronized (mLock) {
writer.println("request: " + mRequest); writer.println("request: " + mRequest);
if (mGpsInterval != Long.MAX_VALUE) { if (mGpsInterval != INTERVAL_DISABLED) {
writer.println(" gps interval: " + mGpsInterval); writer.println(" gps interval: " + mGpsInterval);
} }
if (mNetworkInterval != Long.MAX_VALUE) { if (mNetworkInterval != INTERVAL_DISABLED) {
writer.println(" network interval: " + mNetworkInterval); writer.println(" network interval: " + mNetworkInterval);
} }
if (mGpsLocation != null) { if (mGpsLocation != null) {

View File

@@ -48,7 +48,6 @@ import org.junit.runner.RunWith;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.util.Collections;
import java.util.Random; import java.util.Random;
import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@@ -60,7 +59,6 @@ public class FusedLocationServiceTest {
private static final long TIMEOUT_MS = 5000; private static final long TIMEOUT_MS = 5000;
private Context mContext;
private Random mRandom; private Random mRandom;
private LocationManager mLocationManager; private LocationManager mLocationManager;
@@ -72,15 +70,15 @@ public class FusedLocationServiceTest {
long seed = System.currentTimeMillis(); long seed = System.currentTimeMillis();
Log.i(TAG, "location seed: " + seed); Log.i(TAG, "location seed: " + seed);
mContext = InstrumentationRegistry.getTargetContext(); Context context = InstrumentationRegistry.getTargetContext();
mRandom = new Random(seed); mRandom = new Random(seed);
mLocationManager = mContext.getSystemService(LocationManager.class); mLocationManager = context.getSystemService(LocationManager.class);
setMockLocation(true); setMockLocation(true);
mManager = new LocationProviderManagerCapture(); mManager = new LocationProviderManagerCapture();
mProvider = ILocationProvider.Stub.asInterface( mProvider = ILocationProvider.Stub.asInterface(
new FusedLocationProvider(mContext).getBinder()); new FusedLocationProvider(context).getBinder());
mProvider.setLocationProviderManager(mManager); mProvider.setLocationProviderManager(mManager);
mLocationManager.addTestProvider(NETWORK_PROVIDER, mLocationManager.addTestProvider(NETWORK_PROVIDER,
@@ -118,12 +116,9 @@ public class FusedLocationServiceTest {
@Test @Test
public void testNetworkRequest() throws Exception { public void testNetworkRequest() throws Exception {
LocationRequest request = new LocationRequest.Builder(1000).build();
mProvider.setRequest( mProvider.setRequest(
new ProviderRequest.Builder() new ProviderRequest.Builder()
.setIntervalMillis(1000) .setIntervalMillis(1000)
.setLocationRequests(Collections.singletonList(request))
.build(), .build(),
new WorkSource()); new WorkSource());
@@ -135,14 +130,10 @@ public class FusedLocationServiceTest {
@Test @Test
public void testGpsRequest() throws Exception { public void testGpsRequest() throws Exception {
LocationRequest request = new LocationRequest.Builder(1000)
.setQuality(LocationRequest.POWER_HIGH)
.build();
mProvider.setRequest( mProvider.setRequest(
new ProviderRequest.Builder() new ProviderRequest.Builder()
.setQuality(LocationRequest.QUALITY_HIGH_ACCURACY)
.setIntervalMillis(1000) .setIntervalMillis(1000)
.setLocationRequests(Collections.singletonList(request))
.build(), .build(),
new WorkSource()); new WorkSource());

View File

@@ -254,7 +254,7 @@ public final class FusedPrintersProvider extends Loader<List<PrinterInfo>>
mLocationManager.requestLocationUpdates( mLocationManager.requestLocationUpdates(
LocationManager.FUSED_PROVIDER, LocationManager.FUSED_PROVIDER,
new LocationRequest.Builder(LOCATION_UPDATE_MS) new LocationRequest.Builder(LOCATION_UPDATE_MS)
.setQuality(LocationRequest.POWER_LOW) .setQuality(LocationRequest.QUALITY_LOW_POWER)
.build(), .build(),
new HandlerExecutor(new Handler(Looper.getMainLooper())), new HandlerExecutor(new Handler(Looper.getMainLooper())),
this); this);

View File

@@ -23,15 +23,12 @@ import static android.location.LocationManager.GPS_PROVIDER;
import static android.location.LocationManager.KEY_LOCATION_CHANGED; import static android.location.LocationManager.KEY_LOCATION_CHANGED;
import static android.location.LocationManager.KEY_PROVIDER_ENABLED; import static android.location.LocationManager.KEY_PROVIDER_ENABLED;
import static android.location.LocationManager.PASSIVE_PROVIDER; import static android.location.LocationManager.PASSIVE_PROVIDER;
import static android.location.LocationRequest.PASSIVE_INTERVAL;
import static android.os.IPowerManager.LOCATION_MODE_NO_CHANGE; import static android.os.IPowerManager.LOCATION_MODE_NO_CHANGE;
import static android.os.PowerManager.LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF; import static android.os.PowerManager.LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF;
import static android.os.PowerManager.LOCATION_MODE_FOREGROUND_ONLY; import static android.os.PowerManager.LOCATION_MODE_FOREGROUND_ONLY;
import static android.os.PowerManager.LOCATION_MODE_GPS_DISABLED_WHEN_SCREEN_OFF; import static android.os.PowerManager.LOCATION_MODE_GPS_DISABLED_WHEN_SCREEN_OFF;
import static android.os.PowerManager.LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF; import static android.os.PowerManager.LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF;
import static com.android.internal.location.ProviderRequest.EMPTY_REQUEST;
import static com.android.internal.location.ProviderRequest.INTERVAL_DISABLED;
import static com.android.server.location.LocationManagerService.D; import static com.android.server.location.LocationManagerService.D;
import static com.android.server.location.LocationManagerService.TAG; import static com.android.server.location.LocationManagerService.TAG;
import static com.android.server.location.LocationPermissions.PERMISSION_COARSE; import static com.android.server.location.LocationPermissions.PERMISSION_COARSE;
@@ -503,14 +500,7 @@ class LocationProviderManager extends
LocationRequest.Builder builder = new LocationRequest.Builder(baseRequest); LocationRequest.Builder builder = new LocationRequest.Builder(baseRequest);
if (mPermissionLevel < PERMISSION_FINE) { if (mPermissionLevel < PERMISSION_FINE) {
switch (baseRequest.getQuality()) { builder.setQuality(LocationRequest.QUALITY_LOW_POWER);
case LocationRequest.ACCURACY_FINE:
builder.setQuality(LocationRequest.ACCURACY_BLOCK);
break;
case LocationRequest.POWER_HIGH:
builder.setQuality(LocationRequest.POWER_LOW);
break;
}
if (baseRequest.getIntervalMillis() < MIN_COARSE_INTERVAL_MS) { if (baseRequest.getIntervalMillis() < MIN_COARSE_INTERVAL_MS) {
builder.setIntervalMillis(MIN_COARSE_INTERVAL_MS); builder.setIntervalMillis(MIN_COARSE_INTERVAL_MS);
} }
@@ -1709,7 +1699,7 @@ class LocationProviderManager extends
@Override @Override
protected boolean registerWithService(ProviderRequest request, protected boolean registerWithService(ProviderRequest request,
Collection<Registration> registrations) { Collection<Registration> registrations) {
return reregisterWithService(EMPTY_REQUEST, request, registrations); return reregisterWithService(ProviderRequest.EMPTY_REQUEST, request, registrations);
} }
@GuardedBy("mLock") @GuardedBy("mLock")
@@ -1778,8 +1768,8 @@ class LocationProviderManager extends
Preconditions.checkState(Thread.holdsLock(mLock)); Preconditions.checkState(Thread.holdsLock(mLock));
} }
mLocationEventLog.logProviderUpdateRequest(mName, EMPTY_REQUEST); mLocationEventLog.logProviderUpdateRequest(mName, ProviderRequest.EMPTY_REQUEST);
mProvider.setRequest(EMPTY_REQUEST); mProvider.setRequest(ProviderRequest.EMPTY_REQUEST);
} }
@GuardedBy("mLock") @GuardedBy("mLock")
@@ -1839,27 +1829,27 @@ class LocationProviderManager extends
Preconditions.checkState(Thread.holdsLock(mLock)); Preconditions.checkState(Thread.holdsLock(mLock));
} }
long intervalMs = INTERVAL_DISABLED; long intervalMs = ProviderRequest.INTERVAL_DISABLED;
int quality = LocationRequest.QUALITY_LOW_POWER;
boolean locationSettingsIgnored = false; boolean locationSettingsIgnored = false;
boolean lowPower = true; boolean lowPower = true;
ArrayList<LocationRequest> locationRequests = new ArrayList<>(registrations.size());
for (Registration registration : registrations) { for (Registration registration : registrations) {
LocationRequest request = registration.getRequest(); LocationRequest request = registration.getRequest();
// passive requests do not contribute to the provider request // passive requests do not contribute to the provider request
if (request.getIntervalMillis() == PASSIVE_INTERVAL) { if (request.getIntervalMillis() == LocationRequest.PASSIVE_INTERVAL) {
continue; continue;
} }
intervalMs = min(request.getIntervalMillis(), intervalMs); intervalMs = min(request.getIntervalMillis(), intervalMs);
quality = min(request.getQuality(), quality);
locationSettingsIgnored |= request.isLocationSettingsIgnored(); locationSettingsIgnored |= request.isLocationSettingsIgnored();
lowPower &= request.isLowPower(); lowPower &= request.isLowPower();
locationRequests.add(request);
} }
if (intervalMs == INTERVAL_DISABLED) { if (intervalMs == ProviderRequest.INTERVAL_DISABLED) {
return EMPTY_REQUEST; return ProviderRequest.EMPTY_REQUEST;
} }
// calculate who to blame for power in a somewhat arbitrary fashion. we pick a threshold // calculate who to blame for power in a somewhat arbitrary fashion. we pick a threshold
@@ -1872,7 +1862,7 @@ class LocationProviderManager extends
} catch (ArithmeticException e) { } catch (ArithmeticException e) {
// check for and handle overflow by setting to one below the passive interval so passive // check for and handle overflow by setting to one below the passive interval so passive
// requests are automatically skipped // requests are automatically skipped
thresholdIntervalMs = PASSIVE_INTERVAL - 1; thresholdIntervalMs = LocationRequest.PASSIVE_INTERVAL - 1;
} }
WorkSource workSource = new WorkSource(); WorkSource workSource = new WorkSource();
@@ -1884,9 +1874,9 @@ class LocationProviderManager extends
return new ProviderRequest.Builder() return new ProviderRequest.Builder()
.setIntervalMillis(intervalMs) .setIntervalMillis(intervalMs)
.setQuality(quality)
.setLocationSettingsIgnored(locationSettingsIgnored) .setLocationSettingsIgnored(locationSettingsIgnored)
.setLowPower(lowPower) .setLowPower(lowPower)
.setLocationRequests(locationRequests)
.setWorkSource(workSource) .setWorkSource(workSource)
.build(); .build();
} }

View File

@@ -63,15 +63,7 @@ class PassiveLocationProviderManager extends LocationProviderManager {
@Override @Override
protected ProviderRequest mergeRegistrations(Collection<Registration> registrations) { protected ProviderRequest mergeRegistrations(Collection<Registration> registrations) {
boolean locationSettingsIgnored = false; return new ProviderRequest.Builder().setIntervalMillis(0).build();
for (Registration registration : registrations) {
locationSettingsIgnored |= registration.getRequest().isLocationSettingsIgnored();
}
return new ProviderRequest.Builder()
.setIntervalMillis(0)
.setLocationSettingsIgnored(locationSettingsIgnored)
.build();
} }
@Override @Override
@@ -79,4 +71,9 @@ class PassiveLocationProviderManager extends LocationProviderManager {
Collection<Registration> registrations) { Collection<Registration> registrations) {
return 0; return 0;
} }
@Override
protected String getServiceState() {
return mProvider.getCurrentRequest().isActive() ? "registered" : "unregistered";
}
} }

View File

@@ -708,12 +708,12 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
// For fast GNSS TTFF // For fast GNSS TTFF
provider = LocationManager.NETWORK_PROVIDER; provider = LocationManager.NETWORK_PROVIDER;
locationListener = mNetworkLocationListener; locationListener = mNetworkLocationListener;
locationRequest.setQuality(LocationRequest.POWER_LOW); locationRequest.setQuality(LocationRequest.QUALITY_LOW_POWER);
} else { } else {
// For Device-Based Hybrid (E911) // For Device-Based Hybrid (E911)
provider = LocationManager.FUSED_PROVIDER; provider = LocationManager.FUSED_PROVIDER;
locationListener = mFusedLocationListener; locationListener = mFusedLocationListener;
locationRequest.setQuality(LocationRequest.ACCURACY_FINE); locationRequest.setQuality(LocationRequest.QUALITY_HIGH_ACCURACY);
} }
// Ignore location settings if in emergency mode. This is only allowed for // Ignore location settings if in emergency mode. This is only allowed for

View File

@@ -710,7 +710,6 @@ public class LocationProviderManagerTest {
@Test @Test
public void testProviderRequest() { public void testProviderRequest() {
assertThat(mProvider.getRequest().isActive()).isFalse(); assertThat(mProvider.getRequest().isActive()).isFalse();
assertThat(mProvider.getRequest().getLocationRequests()).isEmpty();
ILocationListener listener1 = createMockLocationListener(); ILocationListener listener1 = createMockLocationListener();
LocationRequest request1 = new LocationRequest.Builder(5).setWorkSource( LocationRequest request1 = new LocationRequest.Builder(5).setWorkSource(
@@ -718,7 +717,6 @@ public class LocationProviderManagerTest {
mManager.registerLocationRequest(request1, IDENTITY, PERMISSION_FINE, listener1); mManager.registerLocationRequest(request1, IDENTITY, PERMISSION_FINE, listener1);
assertThat(mProvider.getRequest().isActive()).isTrue(); assertThat(mProvider.getRequest().isActive()).isTrue();
assertThat(mProvider.getRequest().getLocationRequests()).containsExactly(request1);
assertThat(mProvider.getRequest().isLocationSettingsIgnored()).isFalse(); assertThat(mProvider.getRequest().isLocationSettingsIgnored()).isFalse();
assertThat(mProvider.getRequest().getIntervalMillis()).isEqualTo(5); assertThat(mProvider.getRequest().getIntervalMillis()).isEqualTo(5);
assertThat(mProvider.getRequest().isLowPower()).isFalse(); assertThat(mProvider.getRequest().isLowPower()).isFalse();
@@ -732,8 +730,6 @@ public class LocationProviderManagerTest {
mManager.registerLocationRequest(request2, IDENTITY, PERMISSION_FINE, listener2); mManager.registerLocationRequest(request2, IDENTITY, PERMISSION_FINE, listener2);
assertThat(mProvider.getRequest().isActive()).isTrue(); assertThat(mProvider.getRequest().isActive()).isTrue();
assertThat(mProvider.getRequest().getLocationRequests()).containsExactly(request1,
request2);
assertThat(mProvider.getRequest().isLocationSettingsIgnored()).isFalse(); assertThat(mProvider.getRequest().isLocationSettingsIgnored()).isFalse();
assertThat(mProvider.getRequest().getIntervalMillis()).isEqualTo(1); assertThat(mProvider.getRequest().getIntervalMillis()).isEqualTo(1);
assertThat(mProvider.getRequest().isLowPower()).isFalse(); assertThat(mProvider.getRequest().isLowPower()).isFalse();
@@ -742,7 +738,6 @@ public class LocationProviderManagerTest {
mManager.unregisterLocationRequest(listener1); mManager.unregisterLocationRequest(listener1);
assertThat(mProvider.getRequest().isActive()).isTrue(); assertThat(mProvider.getRequest().isActive()).isTrue();
assertThat(mProvider.getRequest().getLocationRequests()).containsExactly(request2);
assertThat(mProvider.getRequest().isLocationSettingsIgnored()).isFalse(); assertThat(mProvider.getRequest().isLocationSettingsIgnored()).isFalse();
assertThat(mProvider.getRequest().getIntervalMillis()).isEqualTo(1); assertThat(mProvider.getRequest().getIntervalMillis()).isEqualTo(1);
assertThat(mProvider.getRequest().isLowPower()).isTrue(); assertThat(mProvider.getRequest().isLowPower()).isTrue();
@@ -751,7 +746,6 @@ public class LocationProviderManagerTest {
mManager.unregisterLocationRequest(listener2); mManager.unregisterLocationRequest(listener2);
assertThat(mProvider.getRequest().isActive()).isFalse(); assertThat(mProvider.getRequest().isActive()).isFalse();
assertThat(mProvider.getRequest().getLocationRequests()).isEmpty();
} }
@Test @Test
@@ -855,7 +849,6 @@ public class LocationProviderManagerTest {
mInjector.getSettingsHelper().setLocationEnabled(false, IDENTITY.getUserId()); mInjector.getSettingsHelper().setLocationEnabled(false, IDENTITY.getUserId());
assertThat(mProvider.getRequest().isActive()).isTrue(); assertThat(mProvider.getRequest().isActive()).isTrue();
assertThat(mProvider.getRequest().getLocationRequests()).containsExactly(request2);
assertThat(mProvider.getRequest().getIntervalMillis()).isEqualTo(5); assertThat(mProvider.getRequest().getIntervalMillis()).isEqualTo(5);
assertThat(mProvider.getRequest().isLocationSettingsIgnored()).isTrue(); assertThat(mProvider.getRequest().isLocationSettingsIgnored()).isTrue();
} }