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