diff --git a/api/system-current.txt b/api/system-current.txt index c6b6fff76a52c..4a9a19bcf4881 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -3478,7 +3478,8 @@ package android.location { method @NonNull public static android.location.LocationRequest createFromDeprecatedCriteria(@NonNull android.location.Criteria, long, float, boolean); method @NonNull public static android.location.LocationRequest createFromDeprecatedProvider(@NonNull String, long, float, boolean); method public int describeContents(); - method public long getExpireAt(); + method @Deprecated public long getExpireAt(); + method public long getExpireIn(); method public long getFastestInterval(); method public boolean getHideFromAppOps(); method public long getInterval(); @@ -3489,7 +3490,7 @@ package android.location { method @Nullable public android.os.WorkSource getWorkSource(); method public boolean isLocationSettingsIgnored(); method public boolean isLowPowerMode(); - method @NonNull public android.location.LocationRequest setExpireAt(long); + method @Deprecated @NonNull public android.location.LocationRequest setExpireAt(long); method @NonNull public android.location.LocationRequest setExpireIn(long); method @NonNull public android.location.LocationRequest setFastestInterval(long); method public void setHideFromAppOps(boolean); diff --git a/api/test-current.txt b/api/test-current.txt index e376c471a595e..5624082cecb3c 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -1136,17 +1136,20 @@ package android.location { public final class LocationRequest implements android.os.Parcelable { method @NonNull public static android.location.LocationRequest create(); method public int describeContents(); - method public long getExpireAt(); + method @Deprecated public long getExpireAt(); + method public long getExpireIn(); method public long getFastestInterval(); method public long getInterval(); method public int getNumUpdates(); method public int getQuality(); method public boolean isLocationSettingsIgnored(); - method @NonNull public android.location.LocationRequest setExpireAt(long); + method public boolean isLowPowerMode(); + method @Deprecated @NonNull public android.location.LocationRequest setExpireAt(long); method @NonNull public android.location.LocationRequest setExpireIn(long); method @NonNull public android.location.LocationRequest setFastestInterval(long); method @NonNull public android.location.LocationRequest setInterval(long); method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) @NonNull public android.location.LocationRequest setLocationSettingsIgnored(boolean); + method @NonNull public android.location.LocationRequest setLowPowerMode(boolean); method @NonNull public android.location.LocationRequest setNumUpdates(int); method @NonNull public android.location.LocationRequest setProvider(@NonNull String); method @NonNull public android.location.LocationRequest setQuality(int); diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java index 9e17e9541e5c6..f764ccea9599d 100644 --- a/location/java/android/location/LocationManager.java +++ b/location/java/android/location/LocationManager.java @@ -230,7 +230,7 @@ public class LocationManager { public static final String METADATA_SETTINGS_FOOTER_STRING = "com.android.settings.location.FOOTER_STRING"; - private static final long GET_CURRENT_LOCATION_TIMEOUT_MS = 30 * 1000; + private static final long GET_CURRENT_LOCATION_MAX_TIMEOUT_MS = 30 * 1000; private final Context mContext; @@ -628,7 +628,10 @@ public class LocationManager { @Nullable CancellationSignal cancellationSignal, @NonNull @CallbackExecutor Executor executor, @NonNull Consumer consumer) { LocationRequest currentLocationRequest = new LocationRequest(locationRequest) - .setNumUpdates(1).setExpireIn(GET_CURRENT_LOCATION_TIMEOUT_MS); + .setNumUpdates(1); + if (currentLocationRequest.getExpireIn() > GET_CURRENT_LOCATION_MAX_TIMEOUT_MS) { + currentLocationRequest.setExpireIn(GET_CURRENT_LOCATION_MAX_TIMEOUT_MS); + } GetCurrentLocationTransport listenerTransport = new GetCurrentLocationTransport(executor, consumer); @@ -682,6 +685,7 @@ public class LocationManager { LocationRequest request = LocationRequest.createFromDeprecatedProvider( provider, 0, 0, true); + request.setExpireIn(GET_CURRENT_LOCATION_MAX_TIMEOUT_MS); requestLocationUpdates(request, listener, looper); } @@ -712,6 +716,7 @@ public class LocationManager { LocationRequest request = LocationRequest.createFromDeprecatedCriteria( criteria, 0, 0, true); + request.setExpireIn(GET_CURRENT_LOCATION_MAX_TIMEOUT_MS); requestLocationUpdates(request, listener, looper); } @@ -738,6 +743,7 @@ public class LocationManager { LocationRequest request = LocationRequest.createFromDeprecatedProvider( provider, 0, 0, true); + request.setExpireIn(GET_CURRENT_LOCATION_MAX_TIMEOUT_MS); requestLocationUpdates(request, pendingIntent); } @@ -765,6 +771,7 @@ public class LocationManager { LocationRequest request = LocationRequest.createFromDeprecatedCriteria( criteria, 0, 0, true); + request.setExpireIn(GET_CURRENT_LOCATION_MAX_TIMEOUT_MS); requestLocationUpdates(request, pendingIntent); } @@ -2418,7 +2425,7 @@ public class LocationManager { mAlarmManager = alarmManager; mAlarmManager.set( ELAPSED_REALTIME, - SystemClock.elapsedRealtime() + GET_CURRENT_LOCATION_TIMEOUT_MS, + SystemClock.elapsedRealtime() + GET_CURRENT_LOCATION_MAX_TIMEOUT_MS, "GetCurrentLocation", this, null); diff --git a/location/java/android/location/LocationRequest.java b/location/java/android/location/LocationRequest.java index 0902acf176d4a..2d7fede6ec89d 100644 --- a/location/java/android/location/LocationRequest.java +++ b/location/java/android/location/LocationRequest.java @@ -30,6 +30,8 @@ import android.os.SystemClock; import android.os.WorkSource; import android.util.TimeUtils; +import com.android.internal.util.Preconditions; + /** * A data object that contains quality of service parameters for requests @@ -159,6 +161,7 @@ public final class LocationRequest implements Parcelable { private boolean mExplicitFastestInterval = false; @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) private long mExpireAt = Long.MAX_VALUE; // no expiry + private long mExpireIn = Long.MAX_VALUE; // no expiry @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) private int mNumUpdates = Integer.MAX_VALUE; // no expiry @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) @@ -262,6 +265,7 @@ public final class LocationRequest implements Parcelable { mFastestInterval = src.mFastestInterval; mExplicitFastestInterval = src.mExplicitFastestInterval; mExpireAt = src.mExpireAt; + mExpireIn = src.mExpireIn; mNumUpdates = src.mNumUpdates; mSmallestDisplacement = src.mSmallestDisplacement; mProvider = src.mProvider; @@ -336,7 +340,7 @@ public final class LocationRequest implements Parcelable { * @throws IllegalArgumentException if the interval is less than zero */ public @NonNull LocationRequest setInterval(long millis) { - checkInterval(millis); + Preconditions.checkArgument(millis >= 0, "invalid interval: + millis"); mInterval = millis; if (!mExplicitFastestInterval) { mFastestInterval = (long) (mInterval / FASTEST_INTERVAL_FACTOR); @@ -364,9 +368,7 @@ public final class LocationRequest implements Parcelable { * * @param enabled Enable or disable low power mode * @return the same object, so that setters can be chained - * @hide */ - @SystemApi public @NonNull LocationRequest setLowPowerMode(boolean enabled) { mLowPowerMode = enabled; return this; @@ -374,10 +376,7 @@ public final class LocationRequest implements Parcelable { /** * Returns true if low power mode is enabled. - * - * @hide */ - @SystemApi public boolean isLowPowerMode() { return mLowPowerMode; } @@ -425,93 +424,80 @@ public final class LocationRequest implements Parcelable { *

An interval of 0 is allowed, but not recommended, since * location updates may be extremely fast on future implementations. * - *

If {@link #setFastestInterval} is set slower than {@link #setInterval}, + *

If the fastest interval set is slower than {@link #setInterval}, * then your effective fastest interval is {@link #setInterval}. * - * @param millis fastest interval for updates in milliseconds, exact + * @param millis fastest interval for updates in milliseconds * @return the same object, so that setters can be chained * @throws IllegalArgumentException if the interval is less than zero */ public @NonNull LocationRequest setFastestInterval(long millis) { - checkInterval(millis); + Preconditions.checkArgument(millis >= 0, "invalid interval: + millis"); mExplicitFastestInterval = true; mFastestInterval = millis; return this; } /** - * Get the fastest interval of this request, in milliseconds. + * Get the fastest interval of this request in milliseconds. The system will never provide + * location updates faster than the minimum of the fastest interval and {@link #getInterval}. * - *

The system will never provide location updates faster - * than the minimum of {@link #getFastestInterval} and - * {@link #getInterval}. - * - * @return fastest interval in milliseconds, exact + * @return fastest interval in milliseconds */ public long getFastestInterval() { return mFastestInterval; } /** - * Set the duration of this request, in milliseconds. + * Set the expiration time of this request in milliseconds of realtime since boot. Values in the + * past are allowed, but indicate that the request has already expired. The location manager + * will automatically stop updates after the request expires. * - *

The duration begins immediately (and not when the request - * is passed to the location manager), so call this method again - * if the request is re-used at a later time. + * @param millis expiration time of request in milliseconds since boot + * @return the same object, so that setters can be chained + * @see SystemClock#elapsedRealtime() + * @deprecated Prefer {@link #setExpireIn(long)}. + */ + @Deprecated + public @NonNull LocationRequest setExpireAt(long millis) { + mExpireAt = Math.max(millis, 0); + return this; + } + + /** + * Get the request expiration time in milliseconds of realtime since boot. * - *

The location manager will automatically stop updates after - * the request expires. - * - *

The duration includes suspend time. Values less than 0 - * are allowed, but indicate that the request has already expired. + * @return request expiration time in milliseconds since boot + * @see SystemClock#elapsedRealtime() + * @deprecated Prefer {@link #getExpireIn()}. + */ + @Deprecated + public long getExpireAt() { + return mExpireAt; + } + + /** + * Set the duration of this request in milliseconds of realtime. Values less than 0 are allowed, + * but indicate that the request has already expired. The location manager will automatically + * stop updates after the request expires. * * @param millis duration of request in milliseconds * @return the same object, so that setters can be chained + * @see SystemClock#elapsedRealtime() */ public @NonNull LocationRequest setExpireIn(long millis) { - long elapsedRealtime = SystemClock.elapsedRealtime(); - - // Check for > Long.MAX_VALUE overflow (elapsedRealtime > 0): - if (millis > Long.MAX_VALUE - elapsedRealtime) { - mExpireAt = Long.MAX_VALUE; - } else { - mExpireAt = millis + elapsedRealtime; - } - - if (mExpireAt < 0) mExpireAt = 0; + mExpireIn = millis; return this; } /** - * Set the request expiration time, in millisecond since boot. + * Get the request expiration duration in milliseconds of realtime. * - *

This expiration time uses the same time base as {@link SystemClock#elapsedRealtime}. - * - *

The location manager will automatically stop updates after - * the request expires. - * - *

The duration includes suspend time. Values before {@link SystemClock#elapsedRealtime} - * are allowed, but indicate that the request has already expired. - * - * @param millis expiration time of request, in milliseconds since boot including suspend - * @return the same object, so that setters can be chained + * @return request expiration duration in milliseconds + * @see SystemClock#elapsedRealtime() */ - public @NonNull LocationRequest setExpireAt(long millis) { - mExpireAt = millis; - if (mExpireAt < 0) mExpireAt = 0; - return this; - } - - /** - * Get the request expiration time, in milliseconds since boot. - * - *

This value can be compared to {@link SystemClock#elapsedRealtime} to determine - * the time until expiration. - * - * @return expiration time of request, in milliseconds since boot including suspend - */ - public long getExpireAt() { - return mExpireAt; + public long getExpireIn() { + return mExpireIn; } /** @@ -631,13 +617,6 @@ public final class LocationRequest implements Parcelable { return mHideFromAppOps; } - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) - private static void checkInterval(long millis) { - if (millis < 0) { - throw new IllegalArgumentException("invalid interval: " + millis); - } - } - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) private static void checkQuality(int quality) { switch (quality) { @@ -676,6 +655,7 @@ public final class LocationRequest implements Parcelable { request.setFastestInterval(in.readLong()); request.setInterval(in.readLong()); request.setExpireAt(in.readLong()); + request.setExpireIn(in.readLong()); request.setNumUpdates(in.readInt()); request.setSmallestDisplacement(in.readFloat()); request.setHideFromAppOps(in.readInt() != 0); @@ -705,6 +685,7 @@ public final class LocationRequest implements Parcelable { parcel.writeLong(mFastestInterval); parcel.writeLong(mInterval); parcel.writeLong(mExpireAt); + parcel.writeLong(mExpireIn); parcel.writeInt(mNumUpdates); parcel.writeFloat(mSmallestDisplacement); parcel.writeInt(mHideFromAppOps ? 1 : 0); @@ -747,9 +728,11 @@ public final class LocationRequest implements Parcelable { s.append(" fastest="); TimeUtils.formatDuration(mFastestInterval, s); if (mExpireAt != Long.MAX_VALUE) { - long expireIn = mExpireAt - SystemClock.elapsedRealtime(); + s.append(" expireAt=").append(TimeUtils.formatUptime(mExpireAt)); + } + if (mExpireIn != Long.MAX_VALUE) { s.append(" expireIn="); - TimeUtils.formatDuration(expireIn, s); + TimeUtils.formatDuration(mExpireIn, s); } if (mNumUpdates != Integer.MAX_VALUE) { s.append(" num=").append(mNumUpdates); diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java index 1d22b824aff99..fee41da9971dd 100644 --- a/services/core/java/com/android/server/LocationManagerService.java +++ b/services/core/java/com/android/server/LocationManagerService.java @@ -2044,6 +2044,18 @@ public class LocationManagerService extends ILocationManager.Stub { * Note: must be constructed with lock held. */ private UpdateRecord(String provider, LocationRequest request, Receiver receiver) { + // translate expireIn value into expireAt + long elapsedRealtime = SystemClock.elapsedRealtime(); + long expireAt; + // Check for > Long.MAX_VALUE overflow (elapsedRealtime > 0): + if (request.getExpireIn() > Long.MAX_VALUE - elapsedRealtime) { + expireAt = Long.MAX_VALUE; + } else { + expireAt = Math.max(request.getExpireIn() + elapsedRealtime, 0); + } + request.setExpireAt(Math.min(request.getExpireAt(), expireAt)); + request.setExpireIn(Long.MAX_VALUE); + mProvider = provider; mRealRequest = request; mRequest = request;