1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.location; 18 19 import static java.lang.Math.max; 20 import static java.lang.Math.min; 21 22 import android.Manifest; 23 import android.annotation.FloatRange; 24 import android.annotation.IntDef; 25 import android.annotation.IntRange; 26 import android.annotation.NonNull; 27 import android.annotation.Nullable; 28 import android.annotation.RequiresPermission; 29 import android.annotation.SystemApi; 30 import android.compat.annotation.ChangeId; 31 import android.compat.annotation.EnabledAfter; 32 import android.compat.annotation.UnsupportedAppUsage; 33 import android.os.Build; 34 import android.os.Parcel; 35 import android.os.Parcelable; 36 import android.os.WorkSource; 37 import android.util.TimeUtils; 38 39 import com.android.internal.util.Preconditions; 40 41 import java.lang.annotation.Retention; 42 import java.lang.annotation.RetentionPolicy; 43 import java.util.Objects; 44 45 46 /** 47 * An encapsulation of various parameters for requesting location via {@link LocationManager}. 48 */ 49 public final class LocationRequest implements Parcelable { 50 51 /** 52 * For apps targeting Android S and above, all LocationRequest objects marked as low power will 53 * throw exceptions if the caller does not have the LOCATION_HARDWARE permission, instead of 54 * silently dropping the low power part of the request. 55 * 56 * @hide 57 */ 58 @ChangeId 59 @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.R) 60 public static final long LOW_POWER_EXCEPTIONS = 168936375L; 61 62 /** 63 * Represents a passive only request. Such a request will not trigger any active locations or 64 * power usage itself, but may receive locations generated in response to other requests. 65 * 66 * @see LocationRequest#getIntervalMillis() 67 */ 68 public static final long PASSIVE_INTERVAL = Long.MAX_VALUE; 69 70 /** @hide */ 71 @Retention(RetentionPolicy.SOURCE) 72 @IntDef({QUALITY_LOW_POWER, QUALITY_BALANCED_POWER_ACCURACY, QUALITY_HIGH_ACCURACY}) 73 public @interface Quality {} 74 75 /** 76 * A quality constant indicating a location provider may choose to satisfy this request by 77 * providing very accurate locations at the expense of potentially increased power usage. Each 78 * location provider may interpret this field differently, but as an example, the network 79 * provider may choose to return only wifi based locations rather than cell based locations in 80 * order to have greater accuracy when this flag is present. 81 */ 82 public static final int QUALITY_HIGH_ACCURACY = 100; 83 84 /** 85 * A quality constant indicating a location provider may choose to satisfy this request by 86 * equally balancing power and accuracy constraints. Each location provider may interpret this 87 * field differently, but location providers will generally use their default behavior when this 88 * flag is present. 89 */ 90 public static final int QUALITY_BALANCED_POWER_ACCURACY = 102; 91 92 /** 93 * A quality constant indicating a location provider may choose to satisfy this request by 94 * providing less accurate locations in order to save power. Each location provider may 95 * interpret this field differently, but as an example, the network provider may choose to 96 * return cell based locations rather than wifi based locations in order to save power when this 97 * flag is present. 98 */ 99 public static final int QUALITY_LOW_POWER = 104; 100 101 /** 102 * Used with {@link #setQuality} to request the most accurate locations available. 103 * 104 * <p>This may be up to 1 meter accuracy, although this is implementation dependent. 105 * 106 * @hide 107 * @deprecated Use {@link #QUALITY_HIGH_ACCURACY} instead. 108 */ 109 @Deprecated 110 @SystemApi 111 public static final int ACCURACY_FINE = QUALITY_HIGH_ACCURACY; 112 113 /** 114 * Used with {@link #setQuality} to request "block" level accuracy. 115 * 116 * <p>Block level accuracy is considered to be about 100 meter accuracy, 117 * although this is implementation dependent. Using a coarse accuracy 118 * such as this often consumes less power. 119 * 120 * @hide 121 * @deprecated Use {@link #QUALITY_BALANCED_POWER_ACCURACY} instead. 122 */ 123 @Deprecated 124 @SystemApi 125 public static final int ACCURACY_BLOCK = QUALITY_BALANCED_POWER_ACCURACY; 126 127 /** 128 * Used with {@link #setQuality} to request "city" level accuracy. 129 * 130 * <p>City level accuracy is considered to be about 10km accuracy, 131 * although this is implementation dependent. Using a coarse accuracy 132 * such as this often consumes less power. 133 * 134 * @hide 135 * @deprecated Use {@link #QUALITY_LOW_POWER} instead. 136 */ 137 @Deprecated 138 @SystemApi 139 public static final int ACCURACY_CITY = QUALITY_LOW_POWER; 140 141 /** 142 * Used with {@link #setQuality} to require no direct power impact (passive locations). 143 * 144 * <p>This location request will not trigger any active location requests, 145 * but will receive locations triggered by other applications. Your application 146 * will not receive any direct power blame for location work. 147 * 148 * @hide 149 * @deprecated Use {@link #PASSIVE_INTERVAL} instead. 150 */ 151 @SystemApi 152 @Deprecated 153 public static final int POWER_NONE = 200; 154 155 /** 156 * Used with {@link #setQuality} to request low power impact. 157 * 158 * <p>This location request will avoid high power location work where 159 * possible. 160 * 161 * @hide 162 * @deprecated Use {@link #QUALITY_LOW_POWER} instead. 163 */ 164 @Deprecated 165 @SystemApi 166 public static final int POWER_LOW = 201; 167 168 /** 169 * Used with {@link #setQuality} to allow high power consumption for location. 170 * 171 * <p>This location request will allow high power location work. 172 * 173 * @hide 174 * @deprecated Use {@link #QUALITY_HIGH_ACCURACY} instead. 175 */ 176 @Deprecated 177 @SystemApi 178 public static final int POWER_HIGH = 203; 179 180 private static final long IMPLICIT_MIN_UPDATE_INTERVAL = -1; 181 private static final double IMPLICIT_MIN_UPDATE_INTERVAL_FACTOR = 1D / 6D; 182 183 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, publicAlternatives = "Use {@link " 184 + "LocationManager} methods to provide the provider explicitly.") 185 @Nullable private String mProvider; 186 private @Quality int mQuality; 187 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, publicAlternatives = "Use {@link " 188 + "LocationRequest} instead.") 189 private long mInterval; 190 private long mMinUpdateIntervalMillis; 191 private long mExpireAtRealtimeMillis; 192 private long mDurationMillis; 193 private int mMaxUpdates; 194 private float mMinUpdateDistanceMeters; 195 private final long mMaxUpdateDelayMillis; 196 private boolean mHideFromAppOps; 197 private final boolean mAdasGnssBypass; 198 private boolean mLocationSettingsIgnored; 199 private boolean mLowPower; 200 private @Nullable WorkSource mWorkSource; 201 202 /** 203 * @hide 204 * @deprecated Use the Builder to construct new LocationRequests. 205 */ 206 @SystemApi 207 @Deprecated 208 @NonNull create()209 public static LocationRequest create() { 210 // 60 minutes is the default legacy interval 211 return new LocationRequest.Builder(60 * 60 * 1000) 212 .setQuality(QUALITY_LOW_POWER) 213 .build(); 214 } 215 216 /** 217 * @hide 218 * @deprecated Use the Builder to construct new LocationRequests. 219 */ 220 @SystemApi 221 @Deprecated 222 @NonNull createFromDeprecatedProvider(@onNull String provider, long intervalMillis, float minUpdateDistanceMeters, boolean singleShot)223 public static LocationRequest createFromDeprecatedProvider(@NonNull String provider, 224 long intervalMillis, float minUpdateDistanceMeters, boolean singleShot) { 225 Preconditions.checkArgument(provider != null, "invalid null provider"); 226 227 if (intervalMillis < 0) { 228 intervalMillis = 0; 229 } else if (intervalMillis == PASSIVE_INTERVAL) { 230 intervalMillis = Long.MAX_VALUE - 1; 231 } 232 if (minUpdateDistanceMeters < 0) { 233 minUpdateDistanceMeters = 0; 234 } 235 236 int quality; 237 if (LocationManager.PASSIVE_PROVIDER.equals(provider)) { 238 quality = POWER_NONE; 239 } else if (LocationManager.GPS_PROVIDER.equals(provider)) { 240 quality = QUALITY_HIGH_ACCURACY; 241 } else { 242 quality = POWER_LOW; 243 } 244 245 return new LocationRequest.Builder(intervalMillis) 246 .setMinUpdateIntervalMillis(intervalMillis) 247 .setMinUpdateDistanceMeters(minUpdateDistanceMeters) 248 .setMaxUpdates(singleShot ? 1 : Integer.MAX_VALUE) 249 .build() 250 .setProvider(provider) 251 .setQuality(quality); 252 } 253 254 /** 255 * @hide 256 * @deprecated Use the Builder to construct new LocationRequests. 257 */ 258 @SystemApi 259 @Deprecated 260 @NonNull createFromDeprecatedCriteria(@onNull Criteria criteria, long intervalMillis, float minUpdateDistanceMeters, boolean singleShot)261 public static LocationRequest createFromDeprecatedCriteria(@NonNull Criteria criteria, 262 long intervalMillis, float minUpdateDistanceMeters, boolean singleShot) { 263 Preconditions.checkArgument(criteria != null, "invalid null criteria"); 264 265 if (intervalMillis < 0) { 266 intervalMillis = 0; 267 } else if (intervalMillis == PASSIVE_INTERVAL) { 268 intervalMillis = Long.MAX_VALUE - 1; 269 } 270 if (minUpdateDistanceMeters < 0) { 271 minUpdateDistanceMeters = 0; 272 } 273 274 return new LocationRequest.Builder(intervalMillis) 275 .setQuality(criteria) 276 .setMinUpdateIntervalMillis(intervalMillis) 277 .setMinUpdateDistanceMeters(minUpdateDistanceMeters) 278 .setMaxUpdates(singleShot ? 1 : Integer.MAX_VALUE) 279 .build(); 280 } 281 LocationRequest( @ullable String provider, long intervalMillis, @Quality int quality, long expireAtRealtimeMillis, long durationMillis, int maxUpdates, long minUpdateIntervalMillis, float minUpdateDistanceMeters, long maxUpdateDelayMillis, boolean hiddenFromAppOps, boolean adasGnssBypass, boolean locationSettingsIgnored, boolean lowPower, WorkSource workSource)282 private LocationRequest( 283 @Nullable String provider, 284 long intervalMillis, 285 @Quality int quality, 286 long expireAtRealtimeMillis, 287 long durationMillis, 288 int maxUpdates, 289 long minUpdateIntervalMillis, 290 float minUpdateDistanceMeters, 291 long maxUpdateDelayMillis, 292 boolean hiddenFromAppOps, 293 boolean adasGnssBypass, 294 boolean locationSettingsIgnored, 295 boolean lowPower, 296 WorkSource workSource) { 297 mProvider = provider; 298 mInterval = intervalMillis; 299 mQuality = quality; 300 mMinUpdateIntervalMillis = minUpdateIntervalMillis; 301 mExpireAtRealtimeMillis = expireAtRealtimeMillis; 302 mDurationMillis = durationMillis; 303 mMaxUpdates = maxUpdates; 304 mMinUpdateDistanceMeters = minUpdateDistanceMeters; 305 mMaxUpdateDelayMillis = maxUpdateDelayMillis; 306 mHideFromAppOps = hiddenFromAppOps; 307 mAdasGnssBypass = adasGnssBypass; 308 mLocationSettingsIgnored = locationSettingsIgnored; 309 mLowPower = lowPower; 310 mWorkSource = Objects.requireNonNull(workSource); 311 } 312 313 /** 314 * @hide 315 * @deprecated LocationRequests should be treated as immutable. 316 */ 317 @SystemApi 318 @Deprecated setProvider(@onNull String provider)319 public @NonNull LocationRequest setProvider(@NonNull String provider) { 320 Preconditions.checkArgument(provider != null); 321 mProvider = provider; 322 return this; 323 } 324 325 /** 326 * @hide 327 * @deprecated Providers are no longer an explicit part of a location request. 328 */ 329 @SystemApi 330 @Deprecated getProvider()331 public @NonNull String getProvider() { 332 return mProvider != null ? mProvider : LocationManager.FUSED_PROVIDER; 333 } 334 335 /** 336 * @hide 337 * @deprecated LocationRequests should be treated as immutable. 338 */ 339 @SystemApi 340 @Deprecated setQuality(int quality)341 public @NonNull LocationRequest setQuality(int quality) { 342 switch (quality) { 343 case POWER_HIGH: 344 // fall through 345 case QUALITY_HIGH_ACCURACY: 346 mQuality = QUALITY_HIGH_ACCURACY; 347 break; 348 case QUALITY_BALANCED_POWER_ACCURACY: 349 mQuality = QUALITY_BALANCED_POWER_ACCURACY; 350 break; 351 case POWER_LOW: 352 // fall through 353 case QUALITY_LOW_POWER: 354 mQuality = QUALITY_LOW_POWER; 355 break; 356 case POWER_NONE: 357 mInterval = PASSIVE_INTERVAL; 358 break; 359 default: 360 throw new IllegalArgumentException("invalid quality: " + quality); 361 } 362 363 return this; 364 } 365 366 /** 367 * Returns the quality hint for this location request. The quality hint informs the provider how 368 * it should attempt to manage any accuracy vs power tradeoffs while attempting to satisfy this 369 * location request. 370 * 371 * @return the desired quality tradeoffs between accuracy and power 372 */ getQuality()373 public @Quality int getQuality() { 374 return mQuality; 375 } 376 377 /** 378 * @hide 379 * @deprecated LocationRequests should be treated as immutable. 380 */ 381 @SystemApi 382 @Deprecated setInterval(long millis)383 public @NonNull LocationRequest setInterval(long millis) { 384 Preconditions.checkArgument(millis >= 0); 385 386 // legacy clients don't know about the passive interval 387 if (millis == PASSIVE_INTERVAL) { 388 millis = Long.MAX_VALUE - 1; 389 } 390 391 mInterval = millis; 392 if (mMinUpdateIntervalMillis > mInterval) { 393 mMinUpdateIntervalMillis = mInterval; 394 } 395 return this; 396 } 397 398 /** 399 * @hide 400 * @deprecated Use {@link #getIntervalMillis()} instead. 401 */ 402 @SystemApi 403 @Deprecated getInterval()404 public long getInterval() { 405 return getIntervalMillis(); 406 } 407 408 /** 409 * Returns the desired interval of location updates, or {@link #PASSIVE_INTERVAL} if this is a 410 * passive, no power request. A passive request will not actively generate location updates 411 * (and thus will not be power blamed for location), but may receive location updates generated 412 * as a result of other location requests. A passive request must always have an explicit 413 * minimum update interval set. 414 * 415 * <p>Locations may be available at a faster interval than specified here, see 416 * {@link #getMinUpdateIntervalMillis()} for the behavior in that case. 417 * 418 * @return the desired interval of location updates 419 */ getIntervalMillis()420 public @IntRange(from = 0) long getIntervalMillis() { 421 return mInterval; 422 } 423 424 /** 425 * @hide 426 * @deprecated LocationRequests should be treated as immutable. 427 */ 428 @SystemApi 429 @Deprecated setFastestInterval(long millis)430 public @NonNull LocationRequest setFastestInterval(long millis) { 431 Preconditions.checkArgument(millis >= 0); 432 mMinUpdateIntervalMillis = millis; 433 return this; 434 } 435 436 /** 437 * @hide 438 * @deprecated Use {@link #getMinUpdateIntervalMillis()} instead. 439 */ 440 @SystemApi 441 @Deprecated getFastestInterval()442 public long getFastestInterval() { 443 return getMinUpdateIntervalMillis(); 444 } 445 446 /** 447 * @hide 448 * @deprecated LocationRequests should be treated as immutable. 449 */ 450 @SystemApi 451 @Deprecated setExpireAt(long millis)452 public @NonNull LocationRequest setExpireAt(long millis) { 453 mExpireAtRealtimeMillis = max(millis, 0); 454 return this; 455 } 456 457 /** 458 * @hide 459 * @deprecated Prefer {@link #getDurationMillis()} where possible. 460 */ 461 @SystemApi 462 @Deprecated getExpireAt()463 public long getExpireAt() { 464 return mExpireAtRealtimeMillis; 465 } 466 467 /** 468 * @hide 469 * @deprecated LocationRequests should be treated as immutable. 470 */ 471 @SystemApi 472 @Deprecated setExpireIn(long millis)473 public @NonNull LocationRequest setExpireIn(long millis) { 474 mDurationMillis = millis; 475 return this; 476 } 477 478 /** 479 * @hide 480 * @deprecated Use {@link #getDurationMillis()} instead. 481 */ 482 @SystemApi 483 @Deprecated getExpireIn()484 public long getExpireIn() { 485 return getDurationMillis(); 486 } 487 488 /** 489 * Returns the duration for which location will be provided before the request is automatically 490 * removed. A duration of <code>Long.MAX_VALUE</code> represents an unlimited duration. 491 * 492 * @return the duration for which location will be provided 493 */ getDurationMillis()494 public @IntRange(from = 1) long getDurationMillis() { 495 return mDurationMillis; 496 } 497 498 /** 499 * @hide 500 */ getExpirationRealtimeMs(long startRealtimeMs)501 public long getExpirationRealtimeMs(long startRealtimeMs) { 502 long expirationRealtimeMs; 503 // Check for > Long.MAX_VALUE overflow (elapsedRealtime > 0): 504 if (mDurationMillis > Long.MAX_VALUE - startRealtimeMs) { 505 expirationRealtimeMs = Long.MAX_VALUE; 506 } else { 507 expirationRealtimeMs = startRealtimeMs + mDurationMillis; 508 } 509 return min(expirationRealtimeMs, mExpireAtRealtimeMillis); 510 } 511 512 /** 513 * @hide 514 * @deprecated LocationRequests should be treated as immutable. 515 */ 516 @SystemApi 517 @Deprecated setNumUpdates(int numUpdates)518 public @NonNull LocationRequest setNumUpdates(int numUpdates) { 519 if (numUpdates <= 0) { 520 throw new IllegalArgumentException( 521 "invalid numUpdates: " + numUpdates); 522 } 523 mMaxUpdates = numUpdates; 524 return this; 525 } 526 527 /** 528 * @hide 529 * @deprecated Use {@link #getMaxUpdates()} instead. 530 */ 531 @SystemApi 532 @Deprecated getNumUpdates()533 public int getNumUpdates() { 534 return getMaxUpdates(); 535 } 536 537 /** 538 * Returns the maximum number of location updates for this request before the request is 539 * automatically removed. A max updates value of <code>Integer.MAX_VALUE</code> represents an 540 * unlimited number of updates. 541 */ getMaxUpdates()542 public @IntRange(from = 1, to = Integer.MAX_VALUE) int getMaxUpdates() { 543 return mMaxUpdates; 544 } 545 546 /** 547 * Returns the minimum update interval. If location updates are available faster than the 548 * request interval then locations will only be updated if the minimum update interval has 549 * expired since the last location update. 550 * 551 * <p class=note><strong>Note:</strong> Some allowance for jitter is already built into the 552 * minimum update interval, so you need not worry about updates blocked simply because they 553 * arrived a fraction of a second earlier than expected. 554 * 555 * @return the minimum update interval 556 */ getMinUpdateIntervalMillis()557 public @IntRange(from = 0) long getMinUpdateIntervalMillis() { 558 if (mMinUpdateIntervalMillis == IMPLICIT_MIN_UPDATE_INTERVAL) { 559 return (long) (mInterval * IMPLICIT_MIN_UPDATE_INTERVAL_FACTOR); 560 } else { 561 // the min is only necessary in case someone use a deprecated function to mess with the 562 // interval or min update interval 563 return min(mMinUpdateIntervalMillis, mInterval); 564 } 565 } 566 567 /** 568 * @hide 569 * @deprecated LocationRequests should be treated as immutable. 570 */ 571 @SystemApi 572 @Deprecated setSmallestDisplacement(float minDisplacementMeters)573 public @NonNull LocationRequest setSmallestDisplacement(float minDisplacementMeters) { 574 mMinUpdateDistanceMeters = Preconditions.checkArgumentInRange(minDisplacementMeters, 0, 575 Float.MAX_VALUE, "minDisplacementMeters"); 576 return this; 577 } 578 579 /** 580 * @hide 581 * @deprecated Use {@link #getMinUpdateDistanceMeters()} instead. 582 */ 583 @SystemApi 584 @Deprecated getSmallestDisplacement()585 public float getSmallestDisplacement() { 586 return getMinUpdateDistanceMeters(); 587 } 588 589 /** 590 * Returns the minimum distance between location updates. If a potential location update is 591 * closer to the last location update than the minimum update distance, then the potential 592 * location update will not occur. A value of 0 meters implies that no location update will ever 593 * be rejected due to failing this constraint. 594 * 595 * @return the minimum distance between location updates 596 */ getMinUpdateDistanceMeters()597 public @FloatRange(from = 0, to = Float.MAX_VALUE) float getMinUpdateDistanceMeters() { 598 return mMinUpdateDistanceMeters; 599 } 600 601 /** 602 * Returns the maximum time any location update may be delayed, and thus grouped with following 603 * updates to enable location batching. If the maximum update delay is equal to or greater than 604 * twice the interval, then location providers may provide batched results. The maximum batch 605 * size is the maximum update delay divided by the interval. Not all devices or location 606 * providers support batching, and use of this parameter does not guarantee that the client will 607 * see batched results, or that batched results will always be of the maximum size. 608 * 609 * When available, batching can provide substantial power savings to the device, and clients are 610 * encouraged to take advantage where appropriate for the use case. 611 * 612 * @see LocationListener#onLocationChanged(java.util.List) 613 * @return the maximum time by which a location update may be delayed 614 */ getMaxUpdateDelayMillis()615 public @IntRange(from = 0) long getMaxUpdateDelayMillis() { 616 return mMaxUpdateDelayMillis; 617 } 618 619 /** 620 * @hide 621 * @deprecated LocationRequests should be treated as immutable. 622 */ 623 @SystemApi 624 @Deprecated setHideFromAppOps(boolean hiddenFromAppOps)625 public void setHideFromAppOps(boolean hiddenFromAppOps) { 626 mHideFromAppOps = hiddenFromAppOps; 627 } 628 629 /** 630 * @hide 631 * @deprecated Use {@link #isHiddenFromAppOps()} instead. 632 */ 633 @SystemApi 634 @Deprecated getHideFromAppOps()635 public boolean getHideFromAppOps() { 636 return isHiddenFromAppOps(); 637 } 638 639 /** 640 * Returns true if this request should be ignored while updating app ops with location usage. 641 * This implies that someone else (usually the creator of the location request) is responsible 642 * for updating app ops. 643 * 644 * @return true if this request should be ignored while updating app ops with location usage 645 * 646 * @hide 647 */ 648 @SystemApi isHiddenFromAppOps()649 public boolean isHiddenFromAppOps() { 650 return mHideFromAppOps; 651 } 652 653 /** 654 * Returns true if this request may access GNSS even if location settings would normally deny 655 * this, in order to enable automotive safety features. This field is only respected on 656 * automotive devices, and only if the client is recognized as a legitimate ADAS (Advanced 657 * Driving Assistance Systems) application. 658 * 659 * @return true if all limiting factors will be ignored to satisfy GNSS request 660 * 661 * @hide 662 */ 663 // TODO: @SystemApi isAdasGnssBypass()664 public boolean isAdasGnssBypass() { 665 return mAdasGnssBypass; 666 } 667 668 /** 669 * @hide 670 * @deprecated LocationRequests should be treated as immutable. 671 */ 672 @SystemApi 673 @Deprecated 674 @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS) setLocationSettingsIgnored(boolean locationSettingsIgnored)675 public @NonNull LocationRequest setLocationSettingsIgnored(boolean locationSettingsIgnored) { 676 mLocationSettingsIgnored = locationSettingsIgnored; 677 return this; 678 } 679 680 /** 681 * Returns true if location settings, throttling, background location limits, and any other 682 * possible limiting factors will be ignored in order to satisfy this request. 683 * 684 * @return true if all limiting factors will be ignored to satisfy this request 685 * 686 * @hide 687 */ 688 @SystemApi isLocationSettingsIgnored()689 public boolean isLocationSettingsIgnored() { 690 return mLocationSettingsIgnored; 691 } 692 693 /** 694 * Returns true if any bypass flag is set on this request. For internal use only. 695 * 696 * @hide 697 */ isBypass()698 public boolean isBypass() { 699 return mAdasGnssBypass || mLocationSettingsIgnored; 700 } 701 702 /** 703 * @hide 704 * @deprecated LocationRequests should be treated as immutable. 705 */ 706 @SystemApi 707 @Deprecated setLowPowerMode(boolean enabled)708 public @NonNull LocationRequest setLowPowerMode(boolean enabled) { 709 mLowPower = enabled; 710 return this; 711 } 712 713 /** 714 * @hide 715 * @deprecated Use {@link #isLowPower()} instead. 716 */ 717 @Deprecated 718 @SystemApi isLowPowerMode()719 public boolean isLowPowerMode() { 720 return isLowPower(); 721 } 722 723 /** 724 * Returns true if extreme trade-offs should be made to save power for this request. This 725 * usually involves specialized hardware modes which can greatly affect the quality of 726 * locations. 727 * 728 * @return true if extreme trade-offs should be made to save power for this request 729 * 730 * @hide 731 */ 732 @SystemApi isLowPower()733 public boolean isLowPower() { 734 return mLowPower; 735 } 736 737 /** 738 * @hide 739 * @deprecated LocationRequests should be treated as immutable. 740 */ 741 @SystemApi 742 @Deprecated setWorkSource(@ullable WorkSource workSource)743 public void setWorkSource(@Nullable WorkSource workSource) { 744 if (workSource == null) { 745 workSource = new WorkSource(); 746 } 747 mWorkSource = workSource; 748 } 749 750 /** 751 * Returns the work source used for power blame for this request. If empty, the system is free 752 * to assign power blame as it deems most appropriate. 753 * 754 * @return the work source used for power blame for this request 755 * 756 * @hide 757 */ 758 @SystemApi getWorkSource()759 public @NonNull WorkSource getWorkSource() { 760 return mWorkSource; 761 } 762 763 764 public static final @NonNull Parcelable.Creator<LocationRequest> CREATOR = 765 new Parcelable.Creator<LocationRequest>() { 766 @Override 767 public LocationRequest createFromParcel(Parcel in) { 768 return new LocationRequest( 769 /* provider= */ in.readString(), 770 /* intervalMillis= */ in.readLong(), 771 /* quality= */ in.readInt(), 772 /* expireAtRealtimeMillis= */ in.readLong(), 773 /* durationMillis= */ in.readLong(), 774 /* maxUpdates= */ in.readInt(), 775 /* minUpdateIntervalMillis= */ in.readLong(), 776 /* minUpdateDistanceMeters= */ in.readFloat(), 777 /* maxUpdateDelayMillis= */ in.readLong(), 778 /* hiddenFromAppOps= */ in.readBoolean(), 779 /* adasGnssBypass= */ in.readBoolean(), 780 /* locationSettingsIgnored= */ in.readBoolean(), 781 /* lowPower= */ in.readBoolean(), 782 /* workSource= */ in.readTypedObject(WorkSource.CREATOR)); 783 } 784 785 @Override 786 public LocationRequest[] newArray(int size) { 787 return new LocationRequest[size]; 788 } 789 }; 790 791 @Override describeContents()792 public int describeContents() { 793 return 0; 794 } 795 796 @Override writeToParcel(@onNull Parcel parcel, int flags)797 public void writeToParcel(@NonNull Parcel parcel, int flags) { 798 parcel.writeString(mProvider); 799 parcel.writeLong(mInterval); 800 parcel.writeInt(mQuality); 801 parcel.writeLong(mExpireAtRealtimeMillis); 802 parcel.writeLong(mDurationMillis); 803 parcel.writeInt(mMaxUpdates); 804 parcel.writeLong(mMinUpdateIntervalMillis); 805 parcel.writeFloat(mMinUpdateDistanceMeters); 806 parcel.writeLong(mMaxUpdateDelayMillis); 807 parcel.writeBoolean(mHideFromAppOps); 808 parcel.writeBoolean(mAdasGnssBypass); 809 parcel.writeBoolean(mLocationSettingsIgnored); 810 parcel.writeBoolean(mLowPower); 811 parcel.writeTypedObject(mWorkSource, 0); 812 } 813 814 @Override equals(Object o)815 public boolean equals(Object o) { 816 if (this == o) { 817 return true; 818 } 819 if (o == null || getClass() != o.getClass()) { 820 return false; 821 } 822 823 LocationRequest that = (LocationRequest) o; 824 return mInterval == that.mInterval 825 && mQuality == that.mQuality 826 && mExpireAtRealtimeMillis == that.mExpireAtRealtimeMillis 827 && mDurationMillis == that.mDurationMillis 828 && mMaxUpdates == that.mMaxUpdates 829 && mMinUpdateIntervalMillis == that.mMinUpdateIntervalMillis 830 && Float.compare(that.mMinUpdateDistanceMeters, mMinUpdateDistanceMeters) == 0 831 && mMaxUpdateDelayMillis == that.mMaxUpdateDelayMillis 832 && mHideFromAppOps == that.mHideFromAppOps 833 && mAdasGnssBypass == that.mAdasGnssBypass 834 && mLocationSettingsIgnored == that.mLocationSettingsIgnored 835 && mLowPower == that.mLowPower 836 && Objects.equals(mProvider, that.mProvider) 837 && Objects.equals(mWorkSource, that.mWorkSource); 838 } 839 840 @Override hashCode()841 public int hashCode() { 842 return Objects.hash(mProvider, mInterval, mWorkSource); 843 } 844 845 @NonNull 846 @Override toString()847 public String toString() { 848 StringBuilder s = new StringBuilder(); 849 s.append("Request["); 850 if (mProvider != null) { 851 s.append(mProvider).append(" "); 852 } 853 if (mInterval != PASSIVE_INTERVAL) { 854 s.append("@"); 855 TimeUtils.formatDuration(mInterval, s); 856 857 switch (mQuality) { 858 case QUALITY_HIGH_ACCURACY: 859 s.append(" HIGH_ACCURACY"); 860 break; 861 case QUALITY_BALANCED_POWER_ACCURACY: 862 s.append(" BALANCED"); 863 break; 864 case QUALITY_LOW_POWER: 865 s.append(" LOW_POWER"); 866 break; 867 } 868 } else { 869 s.append("PASSIVE"); 870 } 871 if (mExpireAtRealtimeMillis != Long.MAX_VALUE) { 872 s.append(", expireAt=").append(TimeUtils.formatRealtime(mExpireAtRealtimeMillis)); 873 } 874 if (mDurationMillis != Long.MAX_VALUE) { 875 s.append(", duration="); 876 TimeUtils.formatDuration(mDurationMillis, s); 877 } 878 if (mMaxUpdates != Integer.MAX_VALUE) { 879 s.append(", maxUpdates=").append(mMaxUpdates); 880 } 881 if (mMinUpdateIntervalMillis != IMPLICIT_MIN_UPDATE_INTERVAL 882 && mMinUpdateIntervalMillis < mInterval) { 883 s.append(", minUpdateInterval="); 884 TimeUtils.formatDuration(mMinUpdateIntervalMillis, s); 885 } 886 if (mMinUpdateDistanceMeters > 0.0) { 887 s.append(", minUpdateDistance=").append(mMinUpdateDistanceMeters); 888 } 889 if (mMaxUpdateDelayMillis / 2 > mInterval) { 890 s.append(", maxUpdateDelay="); 891 TimeUtils.formatDuration(mMaxUpdateDelayMillis, s); 892 } 893 if (mLowPower) { 894 s.append(", lowPower"); 895 } 896 if (mHideFromAppOps) { 897 s.append(", hiddenFromAppOps"); 898 } 899 if (mAdasGnssBypass) { 900 s.append(", adasGnssBypass"); 901 } 902 if (mLocationSettingsIgnored) { 903 s.append(", settingsBypass"); 904 } 905 if (mWorkSource != null && !mWorkSource.isEmpty()) { 906 s.append(", ").append(mWorkSource); 907 } 908 s.append(']'); 909 return s.toString(); 910 } 911 912 /** 913 * A builder class for {@link LocationRequest}. 914 */ 915 public static final class Builder { 916 917 private long mIntervalMillis; 918 private @Quality int mQuality; 919 private long mDurationMillis; 920 private int mMaxUpdates; 921 private long mMinUpdateIntervalMillis; 922 private float mMinUpdateDistanceMeters; 923 private long mMaxUpdateDelayMillis; 924 private boolean mHiddenFromAppOps; 925 private boolean mAdasGnssBypass; 926 private boolean mLocationSettingsIgnored; 927 private boolean mLowPower; 928 @Nullable private WorkSource mWorkSource; 929 930 /** 931 * Creates a new Builder with the given interval. See {@link #setIntervalMillis(long)} for 932 * more information on the interval. 933 */ Builder(long intervalMillis)934 public Builder(long intervalMillis) { 935 // gives us a range check 936 setIntervalMillis(intervalMillis); 937 938 mQuality = QUALITY_BALANCED_POWER_ACCURACY; 939 mDurationMillis = Long.MAX_VALUE; 940 mMaxUpdates = Integer.MAX_VALUE; 941 mMinUpdateIntervalMillis = IMPLICIT_MIN_UPDATE_INTERVAL; 942 mMinUpdateDistanceMeters = 0; 943 mMaxUpdateDelayMillis = 0; 944 mHiddenFromAppOps = false; 945 mAdasGnssBypass = false; 946 mLocationSettingsIgnored = false; 947 mLowPower = false; 948 mWorkSource = null; 949 } 950 951 /** 952 * Creates a new Builder with all parameters copied from the given location request. 953 */ Builder(@onNull LocationRequest locationRequest)954 public Builder(@NonNull LocationRequest locationRequest) { 955 mIntervalMillis = locationRequest.mInterval; 956 mQuality = locationRequest.mQuality; 957 mDurationMillis = locationRequest.mDurationMillis; 958 mMaxUpdates = locationRequest.mMaxUpdates; 959 mMinUpdateIntervalMillis = locationRequest.mMinUpdateIntervalMillis; 960 mMinUpdateDistanceMeters = locationRequest.mMinUpdateDistanceMeters; 961 mMaxUpdateDelayMillis = locationRequest.mMaxUpdateDelayMillis; 962 mHiddenFromAppOps = locationRequest.mHideFromAppOps; 963 mAdasGnssBypass = locationRequest.mAdasGnssBypass; 964 mLocationSettingsIgnored = locationRequest.mLocationSettingsIgnored; 965 mLowPower = locationRequest.mLowPower; 966 mWorkSource = locationRequest.mWorkSource; 967 968 // handle edge cases that can only happen with location request that has been modified 969 // by deprecated SystemApi methods 970 if (mIntervalMillis == PASSIVE_INTERVAL 971 && mMinUpdateIntervalMillis == IMPLICIT_MIN_UPDATE_INTERVAL) { 972 // this is the legacy default minimum update interval, so if we're forced to 973 // change the value, at least this should be unsuprising to legacy clients (which 974 // should be the only clients capable of getting in this weird state). 975 mMinUpdateIntervalMillis = 10 * 60 * 1000; 976 } 977 } 978 979 /** 980 * Sets the request interval. The request interval may be set to {@link #PASSIVE_INTERVAL} 981 * which indicates this request will not actively generate location updates (and thus will 982 * not be power blamed for location), but may receive location updates generated as a result 983 * of other location requests. A passive request must always have an explicit minimum 984 * update interval set. 985 * 986 * <p>Locations may be available at a faster interval than specified here, see 987 * {@link #setMinUpdateIntervalMillis(long)} for the behavior in that case. 988 */ setIntervalMillis(@ntRangefrom = 0) long intervalMillis)989 public @NonNull Builder setIntervalMillis(@IntRange(from = 0) long intervalMillis) { 990 mIntervalMillis = Preconditions.checkArgumentInRange(intervalMillis, 0, Long.MAX_VALUE, 991 "intervalMillis"); 992 return this; 993 } 994 995 /** 996 * Sets the request quality. The quality is a hint to providers on how they should weigh 997 * power vs accuracy tradeoffs. High accuracy locations may cost more power to produce, and 998 * lower accuracy locations may cost less power to produce. Defaults to 999 * {@link #QUALITY_BALANCED_POWER_ACCURACY}. 1000 */ setQuality(@uality int quality)1001 public @NonNull Builder setQuality(@Quality int quality) { 1002 Preconditions.checkArgument( 1003 quality == QUALITY_LOW_POWER || quality == QUALITY_BALANCED_POWER_ACCURACY 1004 || quality == QUALITY_HIGH_ACCURACY, 1005 "quality must be a defined QUALITY constant, not %d", quality); 1006 mQuality = quality; 1007 return this; 1008 } 1009 1010 /** 1011 * @hide 1012 */ setQuality(@onNull Criteria criteria)1013 public @NonNull Builder setQuality(@NonNull Criteria criteria) { 1014 switch (criteria.getAccuracy()) { 1015 case Criteria.ACCURACY_COARSE: 1016 mQuality = QUALITY_BALANCED_POWER_ACCURACY; 1017 break; 1018 case Criteria.ACCURACY_FINE: 1019 mQuality = QUALITY_HIGH_ACCURACY; 1020 break; 1021 default: { 1022 if (criteria.getPowerRequirement() == Criteria.POWER_HIGH) { 1023 mQuality = POWER_HIGH; 1024 } else { 1025 mQuality = POWER_LOW; 1026 } 1027 } 1028 } 1029 return this; 1030 } 1031 1032 /** 1033 * Sets the duration this request will continue before being automatically removed. Defaults 1034 * to <code>Long.MAX_VALUE</code>, which represents an unlimited duration. 1035 */ setDurationMillis(@ntRangefrom = 1) long durationMillis)1036 public @NonNull Builder setDurationMillis(@IntRange(from = 1) long durationMillis) { 1037 mDurationMillis = Preconditions.checkArgumentInRange(durationMillis, 1, Long.MAX_VALUE, 1038 "durationMillis"); 1039 return this; 1040 } 1041 1042 /** 1043 * Sets the maximum number of location updates for this request before this request is 1044 * automatically removed. Defaults to <code>Integer.MAX_VALUE</code>, which represents an 1045 * unlimited number of updates. 1046 */ setMaxUpdates( @ntRangefrom = 1, to = Integer.MAX_VALUE) int maxUpdates)1047 public @NonNull Builder setMaxUpdates( 1048 @IntRange(from = 1, to = Integer.MAX_VALUE) int maxUpdates) { 1049 mMaxUpdates = Preconditions.checkArgumentInRange(maxUpdates, 1, Integer.MAX_VALUE, 1050 "maxUpdates"); 1051 return this; 1052 } 1053 1054 /** 1055 * Sets an explicit minimum update interval. If location updates are available faster than 1056 * the request interval then an update will only occur if the minimum update interval has 1057 * expired since the last location update. Defaults to no explicit minimum update interval 1058 * set, which means some sensible default between 0 and the interval will be chosen. The 1059 * exact value is not specified at the moment. If an exact known value is required, clients 1060 * should set an explicit value themselves. 1061 * 1062 * <p class=note><strong>Note:</strong> Some allowance for jitter is already built into the 1063 * minimum update interval, so you need not worry about updates blocked simply because they 1064 * arrived a fraction of a second earlier than expected. 1065 * 1066 * <p class="note"><strong>Note:</strong> When {@link #build()} is invoked, the minimum of 1067 * the interval and the minimum update interval will be used as the minimum update interval 1068 * of the built request. 1069 */ setMinUpdateIntervalMillis( @ntRangefrom = 0) long minUpdateIntervalMillis)1070 public @NonNull Builder setMinUpdateIntervalMillis( 1071 @IntRange(from = 0) long minUpdateIntervalMillis) { 1072 mMinUpdateIntervalMillis = Preconditions.checkArgumentInRange(minUpdateIntervalMillis, 1073 0, Long.MAX_VALUE, "minUpdateIntervalMillis"); 1074 return this; 1075 } 1076 1077 /** 1078 * Clears an explicitly set minimum update interval and reverts to an implicit minimum 1079 * update interval (ie, the minimum update interval is some sensible default between 0 and 1080 * the interval). 1081 */ clearMinUpdateIntervalMillis()1082 public @NonNull Builder clearMinUpdateIntervalMillis() { 1083 mMinUpdateIntervalMillis = IMPLICIT_MIN_UPDATE_INTERVAL; 1084 return this; 1085 } 1086 1087 /** 1088 * Sets the minimum update distance between location updates. If a potential location 1089 * update is closer to the last location update than the minimum update distance, then 1090 * the potential location update will not occur. Defaults to 0, which represents no minimum 1091 * update distance. 1092 */ setMinUpdateDistanceMeters( @loatRangefrom = 0, to = Float.MAX_VALUE) float minUpdateDistanceMeters)1093 public @NonNull Builder setMinUpdateDistanceMeters( 1094 @FloatRange(from = 0, to = Float.MAX_VALUE) float minUpdateDistanceMeters) { 1095 mMinUpdateDistanceMeters = Preconditions.checkArgumentInRange(minUpdateDistanceMeters, 1096 0, Float.MAX_VALUE, "minUpdateDistanceMeters"); 1097 return this; 1098 } 1099 1100 /** 1101 * Sets the maximum time any location update may be delayed, and thus grouped with following 1102 * updates to enable location batching. If the maximum update delay is equal to or greater 1103 * than twice the interval, then location providers may provide batched results. Defaults to 1104 * 0, which represents no batching allowed. 1105 */ setMaxUpdateDelayMillis( @ntRangefrom = 0) long maxUpdateDelayMillis)1106 public @NonNull Builder setMaxUpdateDelayMillis( 1107 @IntRange(from = 0) long maxUpdateDelayMillis) { 1108 mMaxUpdateDelayMillis = Preconditions.checkArgumentInRange(maxUpdateDelayMillis, 0, 1109 Long.MAX_VALUE, "maxUpdateDelayMillis"); 1110 return this; 1111 } 1112 1113 /** 1114 * If set to true, indicates that app ops should not be updated with location usage due to 1115 * this request. This implies that someone else (usually the creator of the location 1116 * request) is responsible for updating app ops as appropriate. Defaults to false. 1117 * 1118 * <p>Permissions enforcement occurs when resulting location request is actually used, not 1119 * when this method is invoked. 1120 * 1121 * @hide 1122 */ 1123 @SystemApi 1124 @RequiresPermission(Manifest.permission.UPDATE_APP_OPS_STATS) setHiddenFromAppOps(boolean hiddenFromAppOps)1125 public @NonNull Builder setHiddenFromAppOps(boolean hiddenFromAppOps) { 1126 mHiddenFromAppOps = hiddenFromAppOps; 1127 return this; 1128 } 1129 1130 /** 1131 * If set to true, indicates that the client is an ADAS (Advanced Driving Assistance 1132 * Systems) client, which requires access to GNSS even if location settings would normally 1133 * deny this, in order to enable auto safety features. This field is only respected on 1134 * automotive devices, and only if the client is recognized as a legitimate ADAS 1135 * application. Defaults to false. 1136 * 1137 * <p>Permissions enforcement occurs when resulting location request is actually used, not 1138 * when this method is invoked. 1139 * 1140 * @hide 1141 */ 1142 // TODO: @SystemApi 1143 @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS) setAdasGnssBypass(boolean adasGnssBypass)1144 public @NonNull Builder setAdasGnssBypass(boolean adasGnssBypass) { 1145 mAdasGnssBypass = adasGnssBypass; 1146 return this; 1147 } 1148 1149 /** 1150 * If set to true, indicates that location settings, throttling, background location limits, 1151 * and any other possible limiting factors should be ignored in order to satisfy this 1152 * request. This is only intended for use in user initiated emergency situations, and 1153 * should be used extremely cautiously. Defaults to false. 1154 * 1155 * <p>Permissions enforcement occurs when resulting location request is actually used, not 1156 * when this method is invoked. 1157 * 1158 * @hide 1159 */ 1160 @SystemApi 1161 @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS) setLocationSettingsIgnored(boolean locationSettingsIgnored)1162 public @NonNull Builder setLocationSettingsIgnored(boolean locationSettingsIgnored) { 1163 mLocationSettingsIgnored = locationSettingsIgnored; 1164 return this; 1165 } 1166 1167 /** 1168 * It set to true, indicates that extreme trade-offs should be made if possible to save 1169 * power for this request. This usually involves specialized hardware modes which can 1170 * greatly affect the quality of locations. Defaults to false. 1171 * 1172 * <p>Permissions enforcement occurs when resulting location request is actually used, not 1173 * when this method is invoked. 1174 * 1175 * @hide 1176 */ 1177 @SystemApi 1178 @RequiresPermission(Manifest.permission.LOCATION_HARDWARE) setLowPower(boolean lowPower)1179 public @NonNull Builder setLowPower(boolean lowPower) { 1180 mLowPower = lowPower; 1181 return this; 1182 } 1183 1184 /** 1185 * Sets the work source to use for power blame for this location request. Defaults to an 1186 * empty WorkSource, which implies the system is free to assign power blame as it determines 1187 * best for this request (which usually means blaming the owner of the location listener). 1188 * 1189 * <p>Permissions enforcement occurs when resulting location request is actually used, not 1190 * when this method is invoked. 1191 * 1192 * @hide 1193 */ 1194 @SystemApi 1195 @RequiresPermission(Manifest.permission.UPDATE_DEVICE_STATS) setWorkSource(@ullable WorkSource workSource)1196 public @NonNull Builder setWorkSource(@Nullable WorkSource workSource) { 1197 mWorkSource = workSource; 1198 return this; 1199 } 1200 1201 /** 1202 * Builds a location request from this builder. If an explicit minimum update interval is 1203 * set, the minimum update interval of the location request will be the minimum of the 1204 * interval and minimum update interval. 1205 * 1206 * <p>If building a passive request then you must have set an explicit minimum update 1207 * interval. 1208 * 1209 * @throws IllegalStateException if building a passive request with no explicit minimum 1210 * update interval set 1211 * @return a new location request 1212 */ build()1213 public @NonNull LocationRequest build() { 1214 Preconditions.checkState(mIntervalMillis != PASSIVE_INTERVAL 1215 || mMinUpdateIntervalMillis != IMPLICIT_MIN_UPDATE_INTERVAL, 1216 "passive location requests must have an explicit minimum update interval"); 1217 1218 return new LocationRequest( 1219 null, 1220 mIntervalMillis, 1221 mQuality, 1222 Long.MAX_VALUE, 1223 mDurationMillis, 1224 mMaxUpdates, 1225 min(mMinUpdateIntervalMillis, mIntervalMillis), 1226 mMinUpdateDistanceMeters, 1227 mMaxUpdateDelayMillis, 1228 mHiddenFromAppOps, 1229 mAdasGnssBypass, 1230 mLocationSettingsIgnored, 1231 mLowPower, 1232 new WorkSource(mWorkSource)); 1233 } 1234 } 1235 } 1236