1235 lines
45 KiB
Java
1235 lines
45 KiB
Java
/*
|
|
* Copyright (C) 2012 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package android.location;
|
|
|
|
import static android.Manifest.permission.LOCATION_BYPASS;
|
|
|
|
import static java.lang.Math.max;
|
|
import static java.lang.Math.min;
|
|
|
|
import android.Manifest;
|
|
import android.annotation.FloatRange;
|
|
import android.annotation.IntDef;
|
|
import android.annotation.IntRange;
|
|
import android.annotation.NonNull;
|
|
import android.annotation.Nullable;
|
|
import android.annotation.RequiresFeature;
|
|
import android.annotation.RequiresPermission;
|
|
import android.annotation.SystemApi;
|
|
import android.compat.annotation.ChangeId;
|
|
import android.compat.annotation.EnabledAfter;
|
|
import android.content.pm.PackageManager;
|
|
import android.os.Build;
|
|
import android.os.Parcel;
|
|
import android.os.Parcelable;
|
|
import android.os.WorkSource;
|
|
import android.util.TimeUtils;
|
|
|
|
import com.android.internal.util.Preconditions;
|
|
|
|
import java.lang.annotation.Retention;
|
|
import java.lang.annotation.RetentionPolicy;
|
|
import java.util.Objects;
|
|
|
|
|
|
/**
|
|
* An encapsulation of various parameters for requesting location via {@link LocationManager}.
|
|
*/
|
|
public final class LocationRequest implements Parcelable {
|
|
|
|
/**
|
|
* For apps targeting Android S and above, all LocationRequest objects marked as low power will
|
|
* throw exceptions if the caller does not have the LOCATION_HARDWARE permission, instead of
|
|
* silently dropping the low power part of the request.
|
|
*
|
|
* @hide
|
|
*/
|
|
@ChangeId
|
|
@EnabledAfter(targetSdkVersion = Build.VERSION_CODES.R)
|
|
public static final long LOW_POWER_EXCEPTIONS = 168936375L;
|
|
|
|
/**
|
|
* Represents a passive only request. Such a request will not trigger any active locations or
|
|
* power usage itself, but may receive locations generated in response to other requests.
|
|
*
|
|
* @see LocationRequest#getIntervalMillis()
|
|
*/
|
|
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. Each
|
|
* location provider may interpret this field differently, but as an example, the network
|
|
* provider may choose to return only wifi based locations rather than cell based locations in
|
|
* order to have greater accuracy when this flag is present.
|
|
*/
|
|
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. Each location provider may interpret this
|
|
* field differently, but location providers will generally use their default behavior when this
|
|
* flag is present.
|
|
*/
|
|
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. Each location provider may
|
|
* interpret this field differently, but as an example, the network provider may choose to
|
|
* return cell based locations rather than wifi based locations in order to save power when this
|
|
* flag is present.
|
|
*/
|
|
public static final int QUALITY_LOW_POWER = 104;
|
|
|
|
/**
|
|
* 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.
|
|
*
|
|
* @hide
|
|
* @deprecated Use {@link #QUALITY_HIGH_ACCURACY} instead.
|
|
*/
|
|
@Deprecated
|
|
@SystemApi
|
|
public static final int ACCURACY_FINE = QUALITY_HIGH_ACCURACY;
|
|
|
|
/**
|
|
* Used with {@link #setQuality} to request "block" level accuracy.
|
|
*
|
|
* <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.
|
|
*
|
|
* @hide
|
|
* @deprecated Use {@link #QUALITY_BALANCED_POWER_ACCURACY} instead.
|
|
*/
|
|
@Deprecated
|
|
@SystemApi
|
|
public static final int ACCURACY_BLOCK = QUALITY_BALANCED_POWER_ACCURACY;
|
|
|
|
/**
|
|
* Used with {@link #setQuality} to request "city" level accuracy.
|
|
*
|
|
* <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.
|
|
*
|
|
* @hide
|
|
* @deprecated Use {@link #QUALITY_LOW_POWER} instead.
|
|
*/
|
|
@Deprecated
|
|
@SystemApi
|
|
public static final int ACCURACY_CITY = QUALITY_LOW_POWER;
|
|
|
|
/**
|
|
* Used with {@link #setQuality} to require no direct power impact (passive locations).
|
|
*
|
|
* <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.
|
|
*
|
|
* @hide
|
|
* @deprecated Use {@link #PASSIVE_INTERVAL} instead.
|
|
*/
|
|
@SystemApi
|
|
@Deprecated
|
|
public static final int POWER_NONE = 200;
|
|
|
|
/**
|
|
* Used with {@link #setQuality} to request low power impact.
|
|
*
|
|
* <p>This location request will avoid high power location work where
|
|
* possible.
|
|
*
|
|
* @hide
|
|
* @deprecated Use {@link #QUALITY_LOW_POWER} instead.
|
|
*/
|
|
@Deprecated
|
|
@SystemApi
|
|
public static final int POWER_LOW = 201;
|
|
|
|
/**
|
|
* Used with {@link #setQuality} to allow high power consumption for location.
|
|
*
|
|
* <p>This location request will allow high power location work.
|
|
*
|
|
* @hide
|
|
* @deprecated Use {@link #QUALITY_HIGH_ACCURACY} instead.
|
|
*/
|
|
@Deprecated
|
|
@SystemApi
|
|
public static final int POWER_HIGH = 203;
|
|
|
|
private static final long IMPLICIT_MIN_UPDATE_INTERVAL = -1;
|
|
private static final double IMPLICIT_MIN_UPDATE_INTERVAL_FACTOR = 1D / 6D;
|
|
|
|
private @Nullable String mProvider;
|
|
private @Quality int mQuality;
|
|
private long mIntervalMillis;
|
|
private long mMinUpdateIntervalMillis;
|
|
private long mExpireAtRealtimeMillis;
|
|
private long mDurationMillis;
|
|
private int mMaxUpdates;
|
|
private float mMinUpdateDistanceMeters;
|
|
private final long mMaxUpdateDelayMillis;
|
|
private boolean mHideFromAppOps;
|
|
private final boolean mAdasGnssBypass;
|
|
private boolean mBypass;
|
|
private boolean mLowPower;
|
|
private @Nullable WorkSource mWorkSource;
|
|
|
|
/**
|
|
* @hide
|
|
* @deprecated Use the Builder to construct new LocationRequests.
|
|
*/
|
|
@SystemApi
|
|
@Deprecated
|
|
@NonNull
|
|
public static LocationRequest create() {
|
|
// 60 minutes is the default legacy interval
|
|
return new LocationRequest.Builder(60 * 60 * 1000).build();
|
|
}
|
|
|
|
/**
|
|
* @hide
|
|
* @deprecated Use the Builder to construct new LocationRequests.
|
|
*/
|
|
@SystemApi
|
|
@Deprecated
|
|
@NonNull
|
|
public static LocationRequest createFromDeprecatedProvider(@NonNull String provider,
|
|
long intervalMillis, float minUpdateDistanceMeters, boolean singleShot) {
|
|
Preconditions.checkArgument(provider != null, "invalid null provider");
|
|
|
|
if (intervalMillis < 0) {
|
|
intervalMillis = 0;
|
|
} else if (intervalMillis == PASSIVE_INTERVAL) {
|
|
intervalMillis = Long.MAX_VALUE - 1;
|
|
}
|
|
if (minUpdateDistanceMeters < 0) {
|
|
minUpdateDistanceMeters = 0;
|
|
}
|
|
|
|
int quality;
|
|
if (LocationManager.PASSIVE_PROVIDER.equals(provider)) {
|
|
quality = POWER_NONE;
|
|
} else if (LocationManager.GPS_PROVIDER.equals(provider)) {
|
|
quality = QUALITY_HIGH_ACCURACY;
|
|
} else {
|
|
quality = QUALITY_BALANCED_POWER_ACCURACY;
|
|
}
|
|
|
|
return new LocationRequest.Builder(intervalMillis)
|
|
.setMinUpdateIntervalMillis(intervalMillis)
|
|
.setMinUpdateDistanceMeters(minUpdateDistanceMeters)
|
|
.setMaxUpdates(singleShot ? 1 : Integer.MAX_VALUE)
|
|
.build()
|
|
.setProvider(provider)
|
|
.setQuality(quality);
|
|
}
|
|
|
|
/**
|
|
* @hide
|
|
* @deprecated Use the Builder to construct new LocationRequests.
|
|
*/
|
|
@SystemApi
|
|
@Deprecated
|
|
@NonNull
|
|
public static LocationRequest createFromDeprecatedCriteria(@NonNull Criteria criteria,
|
|
long intervalMillis, float minUpdateDistanceMeters, boolean singleShot) {
|
|
Preconditions.checkArgument(criteria != null, "invalid null criteria");
|
|
|
|
if (intervalMillis < 0) {
|
|
intervalMillis = 0;
|
|
} else if (intervalMillis == PASSIVE_INTERVAL) {
|
|
intervalMillis = Long.MAX_VALUE - 1;
|
|
}
|
|
if (minUpdateDistanceMeters < 0) {
|
|
minUpdateDistanceMeters = 0;
|
|
}
|
|
|
|
return new LocationRequest.Builder(intervalMillis)
|
|
.setQuality(criteria)
|
|
.setMinUpdateIntervalMillis(intervalMillis)
|
|
.setMinUpdateDistanceMeters(minUpdateDistanceMeters)
|
|
.setMaxUpdates(singleShot ? 1 : Integer.MAX_VALUE)
|
|
.build();
|
|
}
|
|
|
|
private LocationRequest(
|
|
@Nullable String provider,
|
|
long intervalMillis,
|
|
@Quality int quality,
|
|
long expireAtRealtimeMillis,
|
|
long durationMillis,
|
|
int maxUpdates,
|
|
long minUpdateIntervalMillis,
|
|
float minUpdateDistanceMeters,
|
|
long maxUpdateDelayMillis,
|
|
boolean hiddenFromAppOps,
|
|
boolean adasGnssBypass,
|
|
boolean bypass,
|
|
boolean lowPower,
|
|
WorkSource workSource) {
|
|
mProvider = provider;
|
|
mIntervalMillis = intervalMillis;
|
|
mQuality = quality;
|
|
mMinUpdateIntervalMillis = minUpdateIntervalMillis;
|
|
mExpireAtRealtimeMillis = expireAtRealtimeMillis;
|
|
mDurationMillis = durationMillis;
|
|
mMaxUpdates = maxUpdates;
|
|
mMinUpdateDistanceMeters = minUpdateDistanceMeters;
|
|
mMaxUpdateDelayMillis = maxUpdateDelayMillis;
|
|
mHideFromAppOps = hiddenFromAppOps;
|
|
mAdasGnssBypass = adasGnssBypass;
|
|
mBypass = bypass;
|
|
mLowPower = lowPower;
|
|
mWorkSource = Objects.requireNonNull(workSource);
|
|
}
|
|
|
|
/**
|
|
* @hide
|
|
* @deprecated LocationRequests should be treated as immutable.
|
|
*/
|
|
@SystemApi
|
|
@Deprecated
|
|
public @NonNull LocationRequest setProvider(@NonNull String provider) {
|
|
Preconditions.checkArgument(provider != null);
|
|
mProvider = provider;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* @hide
|
|
* @deprecated Providers are no longer an explicit part of a location request.
|
|
*/
|
|
@SystemApi
|
|
@Deprecated
|
|
public @NonNull String getProvider() {
|
|
return mProvider != null ? mProvider : LocationManager.FUSED_PROVIDER;
|
|
}
|
|
|
|
/**
|
|
* @hide
|
|
* @deprecated LocationRequests should be treated as immutable.
|
|
*/
|
|
@SystemApi
|
|
@Deprecated
|
|
public @NonNull LocationRequest setQuality(int quality) {
|
|
switch (quality) {
|
|
case POWER_HIGH:
|
|
// fall through
|
|
case QUALITY_HIGH_ACCURACY:
|
|
mQuality = QUALITY_HIGH_ACCURACY;
|
|
break;
|
|
case QUALITY_BALANCED_POWER_ACCURACY:
|
|
mQuality = QUALITY_BALANCED_POWER_ACCURACY;
|
|
break;
|
|
case POWER_LOW:
|
|
// fall through
|
|
case QUALITY_LOW_POWER:
|
|
mQuality = QUALITY_LOW_POWER;
|
|
break;
|
|
case POWER_NONE:
|
|
mIntervalMillis = PASSIVE_INTERVAL;
|
|
break;
|
|
default:
|
|
throw new IllegalArgumentException("invalid quality: " + quality);
|
|
}
|
|
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* 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 desired quality tradeoffs between accuracy and power
|
|
*/
|
|
public @Quality int getQuality() {
|
|
return mQuality;
|
|
}
|
|
|
|
/**
|
|
* @hide
|
|
* @deprecated LocationRequests should be treated as immutable.
|
|
*/
|
|
@SystemApi
|
|
@Deprecated
|
|
public @NonNull LocationRequest setInterval(long millis) {
|
|
Preconditions.checkArgument(millis >= 0);
|
|
|
|
// legacy clients don't know about the passive interval
|
|
if (millis == PASSIVE_INTERVAL) {
|
|
millis = Long.MAX_VALUE - 1;
|
|
}
|
|
|
|
mIntervalMillis = millis;
|
|
if (mMinUpdateIntervalMillis > mIntervalMillis) {
|
|
mMinUpdateIntervalMillis = mIntervalMillis;
|
|
}
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* @hide
|
|
* @deprecated Use {@link #getIntervalMillis()} instead.
|
|
*/
|
|
@SystemApi
|
|
@Deprecated
|
|
public long getInterval() {
|
|
return getIntervalMillis();
|
|
}
|
|
|
|
/**
|
|
* Returns the desired interval of location updates, or {@link #PASSIVE_INTERVAL} if this is a
|
|
* passive, no power request. A passive request will not actively generate location updates
|
|
* (and thus will not be power blamed for location), but may receive location updates generated
|
|
* as a result of other location requests. A passive request must always have an explicit
|
|
* minimum update interval set.
|
|
*
|
|
* <p>Locations may be available at a faster interval than specified here, see
|
|
* {@link #getMinUpdateIntervalMillis()} for the behavior in that case.
|
|
*
|
|
* @return the desired interval of location updates
|
|
*/
|
|
public @IntRange(from = 0) long getIntervalMillis() {
|
|
return mIntervalMillis;
|
|
}
|
|
|
|
/**
|
|
* @hide
|
|
* @deprecated LocationRequests should be treated as immutable.
|
|
*/
|
|
@SystemApi
|
|
@Deprecated
|
|
public @NonNull LocationRequest setFastestInterval(long millis) {
|
|
Preconditions.checkArgument(millis >= 0);
|
|
mMinUpdateIntervalMillis = millis;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* @hide
|
|
* @deprecated Use {@link #getMinUpdateIntervalMillis()} instead.
|
|
*/
|
|
@SystemApi
|
|
@Deprecated
|
|
public long getFastestInterval() {
|
|
return getMinUpdateIntervalMillis();
|
|
}
|
|
|
|
/**
|
|
* @hide
|
|
* @deprecated LocationRequests should be treated as immutable.
|
|
*/
|
|
@SystemApi
|
|
@Deprecated
|
|
public @NonNull LocationRequest setExpireAt(long millis) {
|
|
mExpireAtRealtimeMillis = max(millis, 0);
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* @hide
|
|
* @deprecated Prefer {@link #getDurationMillis()} where possible.
|
|
*/
|
|
@SystemApi
|
|
@Deprecated
|
|
public long getExpireAt() {
|
|
return mExpireAtRealtimeMillis;
|
|
}
|
|
|
|
/**
|
|
* @hide
|
|
* @deprecated LocationRequests should be treated as immutable.
|
|
*/
|
|
@SystemApi
|
|
@Deprecated
|
|
public @NonNull LocationRequest setExpireIn(long millis) {
|
|
mDurationMillis = millis;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* @hide
|
|
* @deprecated Use {@link #getDurationMillis()} instead.
|
|
*/
|
|
@SystemApi
|
|
@Deprecated
|
|
public long getExpireIn() {
|
|
return getDurationMillis();
|
|
}
|
|
|
|
/**
|
|
* Returns the duration for which location will be provided before the request is automatically
|
|
* removed. A duration of <code>Long.MAX_VALUE</code> represents an unlimited duration.
|
|
*
|
|
* @return the duration for which location will be provided
|
|
*/
|
|
public @IntRange(from = 1) long getDurationMillis() {
|
|
return mDurationMillis;
|
|
}
|
|
|
|
/**
|
|
* @hide
|
|
*/
|
|
public long getExpirationRealtimeMs(long startRealtimeMs) {
|
|
long expirationRealtimeMs;
|
|
// Check for > Long.MAX_VALUE overflow (elapsedRealtime > 0):
|
|
if (mDurationMillis > Long.MAX_VALUE - startRealtimeMs) {
|
|
expirationRealtimeMs = Long.MAX_VALUE;
|
|
} else {
|
|
expirationRealtimeMs = startRealtimeMs + mDurationMillis;
|
|
}
|
|
return min(expirationRealtimeMs, mExpireAtRealtimeMillis);
|
|
}
|
|
|
|
/**
|
|
* @hide
|
|
* @deprecated LocationRequests should be treated as immutable.
|
|
*/
|
|
@SystemApi
|
|
@Deprecated
|
|
public @NonNull LocationRequest setNumUpdates(int numUpdates) {
|
|
if (numUpdates <= 0) {
|
|
throw new IllegalArgumentException(
|
|
"invalid numUpdates: " + numUpdates);
|
|
}
|
|
mMaxUpdates = numUpdates;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* @hide
|
|
* @deprecated Use {@link #getMaxUpdates()} instead.
|
|
*/
|
|
@SystemApi
|
|
@Deprecated
|
|
public int getNumUpdates() {
|
|
return getMaxUpdates();
|
|
}
|
|
|
|
/**
|
|
* Returns the maximum number of location updates for this request before the request is
|
|
* automatically removed. A max updates value of <code>Integer.MAX_VALUE</code> represents an
|
|
* unlimited number of updates.
|
|
*/
|
|
public @IntRange(from = 1, to = Integer.MAX_VALUE) int getMaxUpdates() {
|
|
return mMaxUpdates;
|
|
}
|
|
|
|
/**
|
|
* Returns the minimum update interval. If location updates are available faster than the
|
|
* request interval then locations will only be updated if the minimum update interval has
|
|
* expired since the last location update.
|
|
*
|
|
* <p class=note><strong>Note:</strong> Some allowance for jitter is already built into the
|
|
* minimum update interval, so you need not worry about updates blocked simply because they
|
|
* arrived a fraction of a second earlier than expected.
|
|
*
|
|
* @return the minimum update interval
|
|
*/
|
|
public @IntRange(from = 0) long getMinUpdateIntervalMillis() {
|
|
if (mMinUpdateIntervalMillis == IMPLICIT_MIN_UPDATE_INTERVAL) {
|
|
return (long) (mIntervalMillis * IMPLICIT_MIN_UPDATE_INTERVAL_FACTOR);
|
|
} else {
|
|
// the min is only necessary in case someone use a deprecated function to mess with the
|
|
// interval or min update interval
|
|
return min(mMinUpdateIntervalMillis, mIntervalMillis);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @hide
|
|
* @deprecated LocationRequests should be treated as immutable.
|
|
*/
|
|
@SystemApi
|
|
@Deprecated
|
|
public @NonNull LocationRequest setSmallestDisplacement(float minDisplacementMeters) {
|
|
mMinUpdateDistanceMeters = Preconditions.checkArgumentInRange(minDisplacementMeters, 0,
|
|
Float.MAX_VALUE, "minDisplacementMeters");
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* @hide
|
|
* @deprecated Use {@link #getMinUpdateDistanceMeters()} instead.
|
|
*/
|
|
@SystemApi
|
|
@Deprecated
|
|
public float getSmallestDisplacement() {
|
|
return getMinUpdateDistanceMeters();
|
|
}
|
|
|
|
/**
|
|
* Returns the minimum distance between location updates. If a potential location update is
|
|
* closer to the last location update than the minimum update distance, then the potential
|
|
* location update will not occur. A value of 0 meters implies that no location update will ever
|
|
* be rejected due to failing this constraint.
|
|
*
|
|
* @return the minimum distance between location updates
|
|
*/
|
|
public @FloatRange(from = 0, to = Float.MAX_VALUE) float getMinUpdateDistanceMeters() {
|
|
return mMinUpdateDistanceMeters;
|
|
}
|
|
|
|
/**
|
|
* Returns the maximum time any location update may be delayed, and thus grouped with following
|
|
* updates to enable location batching. If the maximum update delay is equal to or greater than
|
|
* twice the interval, then location providers may provide batched results. The maximum batch
|
|
* size is the maximum update delay divided by the interval. Not all devices or location
|
|
* providers support batching, and use of this parameter does not guarantee that the client will
|
|
* see batched results, or that batched results will always be of the maximum size.
|
|
*
|
|
* 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(java.util.List)
|
|
* @return the maximum time by which a location update may be delayed
|
|
*/
|
|
public @IntRange(from = 0) long getMaxUpdateDelayMillis() {
|
|
return mMaxUpdateDelayMillis;
|
|
}
|
|
|
|
/**
|
|
* @hide
|
|
* @deprecated LocationRequests should be treated as immutable.
|
|
*/
|
|
@SystemApi
|
|
@Deprecated
|
|
public void setHideFromAppOps(boolean hiddenFromAppOps) {
|
|
mHideFromAppOps = hiddenFromAppOps;
|
|
}
|
|
|
|
/**
|
|
* @hide
|
|
* @deprecated Use {@link #isHiddenFromAppOps()} instead.
|
|
*/
|
|
@SystemApi
|
|
@Deprecated
|
|
public boolean getHideFromAppOps() {
|
|
return isHiddenFromAppOps();
|
|
}
|
|
|
|
/**
|
|
* Returns true if this request should be ignored while updating app ops with location usage.
|
|
* This implies that someone else (usually the creator of the location request) is responsible
|
|
* for updating app ops.
|
|
*
|
|
* @return true if this request should be ignored while updating app ops with location usage
|
|
*
|
|
* @hide
|
|
*/
|
|
@SystemApi
|
|
public boolean isHiddenFromAppOps() {
|
|
return mHideFromAppOps;
|
|
}
|
|
|
|
/**
|
|
* Returns true if this request may access GNSS even if location settings would normally deny
|
|
* this, in order to enable automotive safety features. This field is only respected on
|
|
* automotive devices, and only if the client is recognized as a legitimate ADAS (Advanced
|
|
* Driving Assistance Systems) application.
|
|
*
|
|
* @return true if all limiting factors will be ignored to satisfy GNSS request
|
|
*
|
|
* @hide
|
|
*/
|
|
@SystemApi
|
|
public boolean isAdasGnssBypass() {
|
|
return mAdasGnssBypass;
|
|
}
|
|
|
|
/**
|
|
* @hide
|
|
* @deprecated LocationRequests should be treated as immutable.
|
|
*/
|
|
@SystemApi
|
|
@Deprecated
|
|
@RequiresPermission(LOCATION_BYPASS)
|
|
public @NonNull LocationRequest setLocationSettingsIgnored(boolean locationSettingsIgnored) {
|
|
mBypass = locationSettingsIgnored;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Returns true if location settings, throttling, background location limits, and any other
|
|
* possible limiting factors will be ignored in order to satisfy this request.
|
|
*
|
|
* @return true if all limiting factors will be ignored to satisfy this request
|
|
*
|
|
* @hide
|
|
*/
|
|
@SystemApi
|
|
public boolean isLocationSettingsIgnored() {
|
|
return mBypass;
|
|
}
|
|
|
|
/**
|
|
* Returns true if any bypass flag is set on this request. For internal use only.
|
|
*
|
|
* @hide
|
|
*/
|
|
public boolean isBypass() {
|
|
return mAdasGnssBypass || mBypass;
|
|
}
|
|
|
|
/**
|
|
* @hide
|
|
* @deprecated LocationRequests should be treated as immutable.
|
|
*/
|
|
@SystemApi
|
|
@Deprecated
|
|
public @NonNull LocationRequest setLowPowerMode(boolean enabled) {
|
|
mLowPower = enabled;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* @hide
|
|
* @deprecated Use {@link #isLowPower()} instead.
|
|
*/
|
|
@Deprecated
|
|
@SystemApi
|
|
public boolean isLowPowerMode() {
|
|
return isLowPower();
|
|
}
|
|
|
|
/**
|
|
* Returns true if extreme trade-offs should be made to save power for this request. This
|
|
* usually involves specialized hardware modes which can greatly affect the quality of
|
|
* locations.
|
|
*
|
|
* @return true if extreme trade-offs should be made to save power for this request
|
|
*
|
|
* @hide
|
|
*/
|
|
@SystemApi
|
|
public boolean isLowPower() {
|
|
return mLowPower;
|
|
}
|
|
|
|
/**
|
|
* @hide
|
|
* @deprecated LocationRequests should be treated as immutable.
|
|
*/
|
|
@SystemApi
|
|
@Deprecated
|
|
public void setWorkSource(@Nullable WorkSource workSource) {
|
|
if (workSource == null) {
|
|
workSource = new WorkSource();
|
|
}
|
|
mWorkSource = workSource;
|
|
}
|
|
|
|
/**
|
|
* Returns the work source used for power blame for this request. If empty, the system is free
|
|
* to assign power blame as it deems most appropriate.
|
|
*
|
|
* @return the work source used for power blame for this request
|
|
*
|
|
* @hide
|
|
*/
|
|
@SystemApi
|
|
public @NonNull WorkSource getWorkSource() {
|
|
return mWorkSource;
|
|
}
|
|
|
|
|
|
public static final @NonNull Parcelable.Creator<LocationRequest> CREATOR =
|
|
new Parcelable.Creator<LocationRequest>() {
|
|
@Override
|
|
public LocationRequest createFromParcel(Parcel in) {
|
|
return new LocationRequest(
|
|
/* provider= */ in.readString(),
|
|
/* intervalMillis= */ in.readLong(),
|
|
/* quality= */ in.readInt(),
|
|
/* expireAtRealtimeMillis= */ in.readLong(),
|
|
/* durationMillis= */ in.readLong(),
|
|
/* maxUpdates= */ in.readInt(),
|
|
/* minUpdateIntervalMillis= */ in.readLong(),
|
|
/* minUpdateDistanceMeters= */ in.readFloat(),
|
|
/* maxUpdateDelayMillis= */ in.readLong(),
|
|
/* hiddenFromAppOps= */ in.readBoolean(),
|
|
/* adasGnssBypass= */ in.readBoolean(),
|
|
/* locationSettingsIgnored= */ in.readBoolean(),
|
|
/* lowPower= */ in.readBoolean(),
|
|
/* workSource= */ in.readTypedObject(WorkSource.CREATOR));
|
|
}
|
|
|
|
@Override
|
|
public LocationRequest[] newArray(int size) {
|
|
return new LocationRequest[size];
|
|
}
|
|
};
|
|
|
|
@Override
|
|
public int describeContents() {
|
|
return 0;
|
|
}
|
|
|
|
@Override
|
|
public void writeToParcel(@NonNull Parcel parcel, int flags) {
|
|
parcel.writeString(mProvider);
|
|
parcel.writeLong(mIntervalMillis);
|
|
parcel.writeInt(mQuality);
|
|
parcel.writeLong(mExpireAtRealtimeMillis);
|
|
parcel.writeLong(mDurationMillis);
|
|
parcel.writeInt(mMaxUpdates);
|
|
parcel.writeLong(mMinUpdateIntervalMillis);
|
|
parcel.writeFloat(mMinUpdateDistanceMeters);
|
|
parcel.writeLong(mMaxUpdateDelayMillis);
|
|
parcel.writeBoolean(mHideFromAppOps);
|
|
parcel.writeBoolean(mAdasGnssBypass);
|
|
parcel.writeBoolean(mBypass);
|
|
parcel.writeBoolean(mLowPower);
|
|
parcel.writeTypedObject(mWorkSource, 0);
|
|
}
|
|
|
|
@Override
|
|
public boolean equals(Object o) {
|
|
if (this == o) {
|
|
return true;
|
|
}
|
|
if (o == null || getClass() != o.getClass()) {
|
|
return false;
|
|
}
|
|
|
|
LocationRequest that = (LocationRequest) o;
|
|
return mIntervalMillis == that.mIntervalMillis
|
|
&& mQuality == that.mQuality
|
|
&& mExpireAtRealtimeMillis == that.mExpireAtRealtimeMillis
|
|
&& mDurationMillis == that.mDurationMillis
|
|
&& mMaxUpdates == that.mMaxUpdates
|
|
&& mMinUpdateIntervalMillis == that.mMinUpdateIntervalMillis
|
|
&& Float.compare(that.mMinUpdateDistanceMeters, mMinUpdateDistanceMeters) == 0
|
|
&& mMaxUpdateDelayMillis == that.mMaxUpdateDelayMillis
|
|
&& mHideFromAppOps == that.mHideFromAppOps
|
|
&& mAdasGnssBypass == that.mAdasGnssBypass
|
|
&& mBypass == that.mBypass
|
|
&& mLowPower == that.mLowPower
|
|
&& Objects.equals(mProvider, that.mProvider)
|
|
&& Objects.equals(mWorkSource, that.mWorkSource);
|
|
}
|
|
|
|
@Override
|
|
public int hashCode() {
|
|
return Objects.hash(mProvider, mIntervalMillis, mWorkSource);
|
|
}
|
|
|
|
@NonNull
|
|
@Override
|
|
public String toString() {
|
|
StringBuilder s = new StringBuilder();
|
|
s.append("Request[");
|
|
if (mProvider != null) {
|
|
s.append(mProvider).append(" ");
|
|
}
|
|
if (mIntervalMillis != PASSIVE_INTERVAL) {
|
|
s.append("@");
|
|
TimeUtils.formatDuration(mIntervalMillis, 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 {
|
|
s.append("PASSIVE");
|
|
}
|
|
if (mExpireAtRealtimeMillis != Long.MAX_VALUE) {
|
|
s.append(", expireAt=").append(TimeUtils.formatRealtime(mExpireAtRealtimeMillis));
|
|
}
|
|
if (mDurationMillis != Long.MAX_VALUE) {
|
|
s.append(", duration=");
|
|
TimeUtils.formatDuration(mDurationMillis, s);
|
|
}
|
|
if (mMaxUpdates != Integer.MAX_VALUE) {
|
|
s.append(", maxUpdates=").append(mMaxUpdates);
|
|
}
|
|
if (mMinUpdateIntervalMillis != IMPLICIT_MIN_UPDATE_INTERVAL
|
|
&& mMinUpdateIntervalMillis < mIntervalMillis) {
|
|
s.append(", minUpdateInterval=");
|
|
TimeUtils.formatDuration(mMinUpdateIntervalMillis, s);
|
|
}
|
|
if (mMinUpdateDistanceMeters > 0.0) {
|
|
s.append(", minUpdateDistance=").append(mMinUpdateDistanceMeters);
|
|
}
|
|
if (mMaxUpdateDelayMillis / 2 > mIntervalMillis) {
|
|
s.append(", maxUpdateDelay=");
|
|
TimeUtils.formatDuration(mMaxUpdateDelayMillis, s);
|
|
}
|
|
if (mLowPower) {
|
|
s.append(", lowPower");
|
|
}
|
|
if (mHideFromAppOps) {
|
|
s.append(", hiddenFromAppOps");
|
|
}
|
|
if (mAdasGnssBypass) {
|
|
s.append(", adasGnssBypass");
|
|
}
|
|
if (mBypass) {
|
|
s.append(", bypass");
|
|
}
|
|
if (mWorkSource != null && !mWorkSource.isEmpty()) {
|
|
s.append(", ").append(mWorkSource);
|
|
}
|
|
s.append(']');
|
|
return s.toString();
|
|
}
|
|
|
|
/**
|
|
* A builder class for {@link LocationRequest}.
|
|
*/
|
|
public static final class Builder {
|
|
|
|
private long mIntervalMillis;
|
|
private @Quality int mQuality;
|
|
private long mDurationMillis;
|
|
private int mMaxUpdates;
|
|
private long mMinUpdateIntervalMillis;
|
|
private float mMinUpdateDistanceMeters;
|
|
private long mMaxUpdateDelayMillis;
|
|
private boolean mHiddenFromAppOps;
|
|
private boolean mAdasGnssBypass;
|
|
private boolean mBypass;
|
|
private boolean mLowPower;
|
|
@Nullable private WorkSource mWorkSource;
|
|
|
|
/**
|
|
* Creates a new Builder with the given interval. See {@link #setIntervalMillis(long)} for
|
|
* more information on the interval.
|
|
*/
|
|
public Builder(long intervalMillis) {
|
|
// gives us a range check
|
|
setIntervalMillis(intervalMillis);
|
|
|
|
mQuality = QUALITY_BALANCED_POWER_ACCURACY;
|
|
mDurationMillis = Long.MAX_VALUE;
|
|
mMaxUpdates = Integer.MAX_VALUE;
|
|
mMinUpdateIntervalMillis = IMPLICIT_MIN_UPDATE_INTERVAL;
|
|
mMinUpdateDistanceMeters = 0;
|
|
mMaxUpdateDelayMillis = 0;
|
|
mHiddenFromAppOps = false;
|
|
mAdasGnssBypass = false;
|
|
mBypass = false;
|
|
mLowPower = false;
|
|
mWorkSource = null;
|
|
}
|
|
|
|
/**
|
|
* Creates a new Builder with all parameters copied from the given location request.
|
|
*/
|
|
public Builder(@NonNull LocationRequest locationRequest) {
|
|
mIntervalMillis = locationRequest.mIntervalMillis;
|
|
mQuality = locationRequest.mQuality;
|
|
mDurationMillis = locationRequest.mDurationMillis;
|
|
mMaxUpdates = locationRequest.mMaxUpdates;
|
|
mMinUpdateIntervalMillis = locationRequest.mMinUpdateIntervalMillis;
|
|
mMinUpdateDistanceMeters = locationRequest.mMinUpdateDistanceMeters;
|
|
mMaxUpdateDelayMillis = locationRequest.mMaxUpdateDelayMillis;
|
|
mHiddenFromAppOps = locationRequest.mHideFromAppOps;
|
|
mAdasGnssBypass = locationRequest.mAdasGnssBypass;
|
|
mBypass = locationRequest.mBypass;
|
|
mLowPower = locationRequest.mLowPower;
|
|
mWorkSource = locationRequest.mWorkSource;
|
|
|
|
// handle edge cases that can only happen with location request that has been modified
|
|
// by deprecated SystemApi methods
|
|
if (mIntervalMillis == PASSIVE_INTERVAL
|
|
&& mMinUpdateIntervalMillis == IMPLICIT_MIN_UPDATE_INTERVAL) {
|
|
// this is the legacy default minimum update interval, so if we're forced to
|
|
// change the value, at least this should be unsuprising to legacy clients (which
|
|
// should be the only clients capable of getting in this weird state).
|
|
mMinUpdateIntervalMillis = 10 * 60 * 1000;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sets the request interval. The request interval may be set to {@link #PASSIVE_INTERVAL}
|
|
* which indicates this request will not actively generate location updates (and thus will
|
|
* not be power blamed for location), but may receive location updates generated as a result
|
|
* of other location requests. A passive request must always have an explicit minimum
|
|
* update interval set.
|
|
*
|
|
* <p>Locations may be available at a faster interval than specified here, see
|
|
* {@link #setMinUpdateIntervalMillis(long)} for the behavior in that case.
|
|
*/
|
|
public @NonNull Builder setIntervalMillis(@IntRange(from = 0) long intervalMillis) {
|
|
mIntervalMillis = Preconditions.checkArgumentInRange(intervalMillis, 0, Long.MAX_VALUE,
|
|
"intervalMillis");
|
|
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 #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,
|
|
"quality must be a defined QUALITY constant, not %d", quality);
|
|
mQuality = quality;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* @hide
|
|
*/
|
|
public @NonNull Builder setQuality(@NonNull Criteria criteria) {
|
|
switch (criteria.getAccuracy()) {
|
|
case Criteria.ACCURACY_COARSE:
|
|
mQuality = QUALITY_BALANCED_POWER_ACCURACY;
|
|
break;
|
|
case Criteria.ACCURACY_FINE:
|
|
mQuality = QUALITY_HIGH_ACCURACY;
|
|
break;
|
|
default: {
|
|
if (criteria.getPowerRequirement() == Criteria.POWER_HIGH) {
|
|
mQuality = POWER_HIGH;
|
|
} else {
|
|
mQuality = POWER_LOW;
|
|
}
|
|
}
|
|
}
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Sets the duration this request will continue before being automatically removed. Defaults
|
|
* to <code>Long.MAX_VALUE</code>, which represents an unlimited duration.
|
|
*/
|
|
public @NonNull Builder setDurationMillis(@IntRange(from = 1) long durationMillis) {
|
|
mDurationMillis = Preconditions.checkArgumentInRange(durationMillis, 1, Long.MAX_VALUE,
|
|
"durationMillis");
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Sets the maximum number of location updates for this request before this request is
|
|
* automatically removed. Defaults to <code>Integer.MAX_VALUE</code>, which represents an
|
|
* unlimited number of updates.
|
|
*/
|
|
public @NonNull Builder setMaxUpdates(
|
|
@IntRange(from = 1, to = Integer.MAX_VALUE) int maxUpdates) {
|
|
mMaxUpdates = Preconditions.checkArgumentInRange(maxUpdates, 1, Integer.MAX_VALUE,
|
|
"maxUpdates");
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Sets an explicit minimum update interval. If location updates are available faster than
|
|
* the request interval then an update will only occur if the minimum update interval has
|
|
* expired since the last location update. Defaults to no explicit minimum update interval
|
|
* set, which means some sensible default between 0 and the interval will be chosen. The
|
|
* exact value is not specified at the moment. If an exact known value is required, clients
|
|
* should set an explicit value themselves.
|
|
*
|
|
* <p class=note><strong>Note:</strong> Some allowance for jitter is already built into the
|
|
* minimum update interval, so you need not worry about updates blocked simply because they
|
|
* arrived a fraction of a second earlier than expected.
|
|
*
|
|
* <p class="note"><strong>Note:</strong> When {@link #build()} is invoked, the minimum of
|
|
* the interval and the minimum update interval will be used as the minimum update interval
|
|
* of the built request.
|
|
*/
|
|
public @NonNull Builder setMinUpdateIntervalMillis(
|
|
@IntRange(from = 0) long minUpdateIntervalMillis) {
|
|
mMinUpdateIntervalMillis = Preconditions.checkArgumentInRange(minUpdateIntervalMillis,
|
|
0, Long.MAX_VALUE, "minUpdateIntervalMillis");
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Clears an explicitly set minimum update interval and reverts to an implicit minimum
|
|
* update interval (ie, the minimum update interval is some sensible default between 0 and
|
|
* the interval).
|
|
*/
|
|
public @NonNull Builder clearMinUpdateIntervalMillis() {
|
|
mMinUpdateIntervalMillis = IMPLICIT_MIN_UPDATE_INTERVAL;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Sets the minimum update distance between location updates. If a potential location
|
|
* update is closer to the last location update than the minimum update distance, then
|
|
* the potential location update will not occur. Defaults to 0, which represents no minimum
|
|
* update distance.
|
|
*/
|
|
public @NonNull Builder setMinUpdateDistanceMeters(
|
|
@FloatRange(from = 0, to = Float.MAX_VALUE) float minUpdateDistanceMeters) {
|
|
mMinUpdateDistanceMeters = Preconditions.checkArgumentInRange(minUpdateDistanceMeters,
|
|
0, Float.MAX_VALUE, "minUpdateDistanceMeters");
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Sets the maximum time any location update may be delayed, and thus grouped with following
|
|
* updates to enable location batching. If the maximum update delay is equal to or greater
|
|
* than twice the interval, then location providers may provide batched results. Defaults to
|
|
* 0, which represents no batching allowed.
|
|
*/
|
|
public @NonNull Builder setMaxUpdateDelayMillis(
|
|
@IntRange(from = 0) long maxUpdateDelayMillis) {
|
|
mMaxUpdateDelayMillis = Preconditions.checkArgumentInRange(maxUpdateDelayMillis, 0,
|
|
Long.MAX_VALUE, "maxUpdateDelayMillis");
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* If set to true, indicates that app ops should not be updated with location usage due to
|
|
* this request. This implies that someone else (usually the creator of the location
|
|
* request) is responsible for updating app ops as appropriate. Defaults to false.
|
|
*
|
|
* <p>Permissions enforcement occurs when resulting location request is actually used, not
|
|
* when this method is invoked.
|
|
*
|
|
* @hide
|
|
*/
|
|
@SystemApi
|
|
@RequiresPermission(Manifest.permission.UPDATE_APP_OPS_STATS)
|
|
public @NonNull Builder setHiddenFromAppOps(boolean hiddenFromAppOps) {
|
|
mHiddenFromAppOps = hiddenFromAppOps;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* If set to true, indicates that the client is an ADAS (Advanced Driving Assistance
|
|
* Systems) client, which requires access to GNSS even if location settings would normally
|
|
* deny this, in order to enable auto safety features. This field is only respected on
|
|
* automotive devices, and only if the client is recognized as a legitimate ADAS
|
|
* application. Defaults to false.
|
|
*
|
|
* <p>Permissions enforcement occurs when resulting location request is actually used, not
|
|
* when this method is invoked.
|
|
*
|
|
* @hide
|
|
*/
|
|
@SystemApi
|
|
@RequiresPermission(LOCATION_BYPASS)
|
|
@RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE)
|
|
public @NonNull Builder setAdasGnssBypass(boolean adasGnssBypass) {
|
|
mAdasGnssBypass = adasGnssBypass;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* If set to true, indicates that location settings, throttling, background location limits,
|
|
* and any other possible limiting factors should be ignored in order to satisfy this
|
|
* request. This is only intended for use in user initiated emergency situations, and
|
|
* should be used extremely cautiously. Defaults to false.
|
|
*
|
|
* <p>Permissions enforcement occurs when resulting location request is actually used, not
|
|
* when this method is invoked.
|
|
*
|
|
* @hide
|
|
*/
|
|
@SystemApi
|
|
@RequiresPermission(LOCATION_BYPASS)
|
|
public @NonNull Builder setLocationSettingsIgnored(boolean locationSettingsIgnored) {
|
|
mBypass = locationSettingsIgnored;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* It set to true, indicates that extreme trade-offs should be made if possible to save
|
|
* power for this request. This usually involves specialized hardware modes which can
|
|
* greatly affect the quality of locations. Not all devices may support this. Defaults to
|
|
* false.
|
|
*
|
|
* <p>Permissions enforcement occurs when resulting location request is actually used, not
|
|
* when this method is invoked.
|
|
*
|
|
* @hide
|
|
*/
|
|
@SystemApi
|
|
@RequiresPermission(Manifest.permission.LOCATION_HARDWARE)
|
|
public @NonNull Builder setLowPower(boolean lowPower) {
|
|
mLowPower = lowPower;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Sets the work source to use for power blame for this location request. Defaults to an
|
|
* empty WorkSource, which implies the system is free to assign power blame as it determines
|
|
* best for this request (which usually means blaming the owner of the location listener).
|
|
*
|
|
* <p>Permissions enforcement occurs when resulting location request is actually used, not
|
|
* when this method is invoked.
|
|
*
|
|
* @hide
|
|
*/
|
|
@SystemApi
|
|
@RequiresPermission(Manifest.permission.UPDATE_DEVICE_STATS)
|
|
public @NonNull Builder setWorkSource(@Nullable WorkSource workSource) {
|
|
mWorkSource = workSource;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Builds a location request from this builder. If an explicit minimum update interval is
|
|
* set, the minimum update interval of the location request will be the minimum of the
|
|
* interval and minimum update interval.
|
|
*
|
|
* <p>If building a passive request then you must have set an explicit minimum update
|
|
* interval.
|
|
*
|
|
* @throws IllegalStateException if building a passive request with no explicit minimum
|
|
* update interval set
|
|
* @return a new location request
|
|
*/
|
|
public @NonNull LocationRequest build() {
|
|
Preconditions.checkState(mIntervalMillis != PASSIVE_INTERVAL
|
|
|| mMinUpdateIntervalMillis != IMPLICIT_MIN_UPDATE_INTERVAL,
|
|
"passive location requests must have an explicit minimum update interval");
|
|
|
|
return new LocationRequest(
|
|
null,
|
|
mIntervalMillis,
|
|
mQuality,
|
|
Long.MAX_VALUE,
|
|
mDurationMillis,
|
|
mMaxUpdates,
|
|
min(mMinUpdateIntervalMillis, mIntervalMillis),
|
|
mMinUpdateDistanceMeters,
|
|
mMaxUpdateDelayMillis,
|
|
mHiddenFromAppOps,
|
|
mAdasGnssBypass,
|
|
mBypass,
|
|
mLowPower,
|
|
new WorkSource(mWorkSource));
|
|
}
|
|
}
|
|
}
|