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 android.Manifest; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.annotation.RequiresPermission; 23 import android.annotation.SystemApi; 24 import android.annotation.TestApi; 25 import android.compat.annotation.UnsupportedAppUsage; 26 import android.os.Build; 27 import android.os.Parcel; 28 import android.os.Parcelable; 29 import android.os.SystemClock; 30 import android.os.WorkSource; 31 import android.util.TimeUtils; 32 33 34 /** 35 * A data object that contains quality of service parameters for requests 36 * to the {@link LocationManager}. 37 * 38 * <p>LocationRequest objects are used to request a quality of service 39 * for location updates from the Location Manager. 40 * 41 * <p>For example, if your application wants high accuracy location 42 * it should create a location request with {@link #setQuality} set to 43 * {@link #ACCURACY_FINE} or {@link #POWER_HIGH}, and it should set 44 * {@link #setInterval} to less than one second. This would be 45 * appropriate for mapping applications that are showing your location 46 * in real-time. 47 * 48 * <p>At the other extreme, if you want negligible power 49 * impact, but to still receive location updates when available, then use 50 * {@link #setQuality} with {@link #POWER_NONE}. With this request your 51 * application will not trigger (and therefore will not receive any 52 * power blame) any location updates, but will receive locations 53 * triggered by other applications. This would be appropriate for 54 * applications that have no firm requirement for location, but can 55 * take advantage when available. 56 * 57 * <p>In between these two extremes is a very common use-case, where 58 * applications definitely want to receive 59 * updates at a specified interval, and can receive them faster when 60 * available, but still want a low power impact. These applications 61 * should consider {@link #POWER_LOW} combined with a faster 62 * {@link #setFastestInterval} (such as 1 minute) and a slower 63 * {@link #setInterval} (such as 60 minutes). They will only be assigned 64 * power blame for the interval set by {@link #setInterval}, but can 65 * still receive locations triggered by other applications at a rate up 66 * to {@link #setFastestInterval}. This style of request is appropriate for 67 * many location aware applications, including background usage. Do be 68 * careful to also throttle {@link #setFastestInterval} if you perform 69 * heavy-weight work after receiving an update - such as using the network. 70 * 71 * <p>Activities should strongly consider removing all location 72 * request when entering the background 73 * (for example at {@link android.app.Activity#onPause}), or 74 * at least swap the request to a larger interval and lower quality. 75 * Future version of the location manager may automatically perform background 76 * throttling on behalf of applications. 77 * 78 * <p>Applications cannot specify the exact location sources that are 79 * used by Android's <em>Fusion Engine</em>. In fact, the system 80 * may have multiple location sources (providers) running and may 81 * fuse the results from several sources into a single Location object. 82 * 83 * <p>Location requests from applications with 84 * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION} and not 85 * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} will 86 * be automatically throttled to a slower interval, and the location 87 * object will be obfuscated to only show a coarse level of accuracy. 88 * 89 * <p>All location requests are considered hints, and you may receive 90 * locations that are more accurate, less accurate, and slower 91 * than requested. 92 * 93 * @hide 94 */ 95 @SystemApi 96 @TestApi 97 public final class LocationRequest implements Parcelable { 98 /** 99 * Used with {@link #setQuality} to request the most accurate locations available. 100 * 101 * <p>This may be up to 1 meter accuracy, although this is implementation dependent. 102 */ 103 public static final int ACCURACY_FINE = 100; 104 105 /** 106 * Used with {@link #setQuality} to request "block" level accuracy. 107 * 108 * <p>Block level accuracy is considered to be about 100 meter accuracy, 109 * although this is implementation dependent. Using a coarse accuracy 110 * such as this often consumes less power. 111 */ 112 public static final int ACCURACY_BLOCK = 102; 113 114 /** 115 * Used with {@link #setQuality} to request "city" level accuracy. 116 * 117 * <p>City level accuracy is considered to be about 10km accuracy, 118 * although this is implementation dependent. Using a coarse accuracy 119 * such as this often consumes less power. 120 */ 121 public static final int ACCURACY_CITY = 104; 122 123 /** 124 * Used with {@link #setQuality} to require no direct power impact (passive locations). 125 * 126 * <p>This location request will not trigger any active location requests, 127 * but will receive locations triggered by other applications. Your application 128 * will not receive any direct power blame for location work. 129 */ 130 public static final int POWER_NONE = 200; 131 132 /** 133 * Used with {@link #setQuality} to request low power impact. 134 * 135 * <p>This location request will avoid high power location work where 136 * possible. 137 */ 138 public static final int POWER_LOW = 201; 139 140 /** 141 * Used with {@link #setQuality} to allow high power consumption for location. 142 * 143 * <p>This location request will allow high power location work. 144 */ 145 public static final int POWER_HIGH = 203; 146 147 /** 148 * By default, mFastestInterval = FASTEST_INTERVAL_MULTIPLE * mInterval 149 */ 150 private static final double FASTEST_INTERVAL_FACTOR = 6.0; // 6x 151 152 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 153 private int mQuality = POWER_LOW; 154 @UnsupportedAppUsage 155 private long mInterval = 60 * 60 * 1000; // 60 minutes 156 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 157 private long mFastestInterval = (long) (mInterval / FASTEST_INTERVAL_FACTOR); // 10 minutes 158 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 159 private boolean mExplicitFastestInterval = false; 160 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 161 private long mExpireAt = Long.MAX_VALUE; // no expiry 162 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 163 private int mNumUpdates = Integer.MAX_VALUE; // no expiry 164 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 165 private float mSmallestDisplacement = 0.0f; // meters 166 @UnsupportedAppUsage 167 private WorkSource mWorkSource = null; 168 @UnsupportedAppUsage 169 private boolean mHideFromAppOps = false; // True if this request shouldn't be counted by AppOps 170 private boolean mLocationSettingsIgnored = false; 171 172 @UnsupportedAppUsage 173 private String mProvider = LocationManager.FUSED_PROVIDER; 174 // for deprecated APIs that explicitly request a provider 175 176 /** If true, GNSS chipset will make strong tradeoffs to substantially restrict power use */ 177 private boolean mLowPowerMode = false; 178 179 /** 180 * Create a location request with default parameters. 181 * 182 * <p>Default parameters are for a low power, slowly updated location. 183 * It can then be adjusted as required by the applications before passing 184 * to the {@link LocationManager} 185 * 186 * @return a new location request 187 */ 188 @NonNull create()189 public static LocationRequest create() { 190 return new LocationRequest(); 191 } 192 193 /** @hide */ 194 @SystemApi 195 @NonNull createFromDeprecatedProvider( @onNull String provider, long minTime, float minDistance, boolean singleShot)196 public static LocationRequest createFromDeprecatedProvider( 197 @NonNull String provider, long minTime, float minDistance, boolean singleShot) { 198 if (minTime < 0) minTime = 0; 199 if (minDistance < 0) minDistance = 0; 200 201 int quality; 202 if (LocationManager.PASSIVE_PROVIDER.equals(provider)) { 203 quality = POWER_NONE; 204 } else if (LocationManager.GPS_PROVIDER.equals(provider)) { 205 quality = ACCURACY_FINE; 206 } else { 207 quality = POWER_LOW; 208 } 209 210 LocationRequest request = new LocationRequest() 211 .setProvider(provider) 212 .setQuality(quality) 213 .setInterval(minTime) 214 .setFastestInterval(minTime) 215 .setSmallestDisplacement(minDistance); 216 if (singleShot) request.setNumUpdates(1); 217 return request; 218 } 219 220 /** @hide */ 221 @SystemApi 222 @NonNull createFromDeprecatedCriteria( @onNull Criteria criteria, long minTime, float minDistance, boolean singleShot)223 public static LocationRequest createFromDeprecatedCriteria( 224 @NonNull Criteria criteria, long minTime, float minDistance, boolean singleShot) { 225 if (minTime < 0) minTime = 0; 226 if (minDistance < 0) minDistance = 0; 227 228 int quality; 229 switch (criteria.getAccuracy()) { 230 case Criteria.ACCURACY_COARSE: 231 quality = ACCURACY_BLOCK; 232 break; 233 case Criteria.ACCURACY_FINE: 234 quality = ACCURACY_FINE; 235 break; 236 default: { 237 if (criteria.getPowerRequirement() == Criteria.POWER_HIGH) { 238 quality = POWER_HIGH; 239 } else { 240 quality = POWER_LOW; 241 } 242 } 243 } 244 245 LocationRequest request = new LocationRequest() 246 .setQuality(quality) 247 .setInterval(minTime) 248 .setFastestInterval(minTime) 249 .setSmallestDisplacement(minDistance); 250 if (singleShot) request.setNumUpdates(1); 251 return request; 252 } 253 254 /** @hide */ LocationRequest()255 public LocationRequest() { 256 } 257 258 /** @hide */ LocationRequest(LocationRequest src)259 public LocationRequest(LocationRequest src) { 260 mQuality = src.mQuality; 261 mInterval = src.mInterval; 262 mFastestInterval = src.mFastestInterval; 263 mExplicitFastestInterval = src.mExplicitFastestInterval; 264 mExpireAt = src.mExpireAt; 265 mNumUpdates = src.mNumUpdates; 266 mSmallestDisplacement = src.mSmallestDisplacement; 267 mProvider = src.mProvider; 268 mWorkSource = src.mWorkSource; 269 mHideFromAppOps = src.mHideFromAppOps; 270 mLowPowerMode = src.mLowPowerMode; 271 mLocationSettingsIgnored = src.mLocationSettingsIgnored; 272 } 273 274 /** 275 * Set the quality of the request. 276 * 277 * <p>Use with a accuracy constant such as {@link #ACCURACY_FINE}, or a power 278 * constant such as {@link #POWER_LOW}. You cannot request both accuracy and 279 * power, only one or the other can be specified. The system will then 280 * maximize accuracy or minimize power as appropriate. 281 * 282 * <p>The quality of the request is a strong hint to the system for which 283 * location sources to use. For example, {@link #ACCURACY_FINE} is more likely 284 * to use GPS, and {@link #POWER_LOW} is more likely to use WIFI & Cell tower 285 * positioning, but it also depends on many other factors (such as which sources 286 * are available) and is implementation dependent. 287 * 288 * <p>{@link #setQuality} and {@link #setInterval} are the most important parameters 289 * on a location request. 290 * 291 * @param quality an accuracy or power constant 292 * @return the same object, so that setters can be chained 293 * @throws IllegalArgumentException if the quality constant is not valid 294 */ setQuality(int quality)295 public @NonNull LocationRequest setQuality(int quality) { 296 checkQuality(quality); 297 mQuality = quality; 298 return this; 299 } 300 301 /** 302 * Get the quality of the request. 303 * 304 * @return an accuracy or power constant 305 */ getQuality()306 public int getQuality() { 307 return mQuality; 308 } 309 310 /** 311 * Set the desired interval for active location updates, in milliseconds. 312 * 313 * <p>The location manager will actively try to obtain location updates 314 * for your application at this interval, so it has a 315 * direct influence on the amount of power used by your application. 316 * Choose your interval wisely. 317 * 318 * <p>This interval is inexact. You may not receive updates at all (if 319 * no location sources are available), or you may receive them 320 * slower than requested. You may also receive them faster than 321 * requested (if other applications are requesting location at a 322 * faster interval). The fastest rate that you will receive 323 * updates can be controlled with {@link #setFastestInterval}. 324 * 325 * <p>Applications with only the coarse location permission may have their 326 * interval silently throttled. 327 * 328 * <p>An interval of 0 is allowed, but not recommended, since 329 * location updates may be extremely fast on future implementations. 330 * 331 * <p>{@link #setQuality} and {@link #setInterval} are the most important parameters 332 * on a location request. 333 * 334 * @param millis desired interval in millisecond, inexact 335 * @return the same object, so that setters can be chained 336 * @throws IllegalArgumentException if the interval is less than zero 337 */ setInterval(long millis)338 public @NonNull LocationRequest setInterval(long millis) { 339 checkInterval(millis); 340 mInterval = millis; 341 if (!mExplicitFastestInterval) { 342 mFastestInterval = (long) (mInterval / FASTEST_INTERVAL_FACTOR); 343 } 344 return this; 345 } 346 347 /** 348 * Get the desired interval of this request, in milliseconds. 349 * 350 * @return desired interval in milliseconds, inexact 351 */ getInterval()352 public long getInterval() { 353 return mInterval; 354 } 355 356 357 /** 358 * Requests the GNSS chipset to run in a low power mode and make strong tradeoffs to 359 * substantially restrict power. 360 * 361 * <p>In this mode, the GNSS chipset will not, on average, run power hungry operations like RF & 362 * signal searches for more than one second per interval (specified by 363 * {@link #setInterval(long)}). 364 * 365 * @param enabled Enable or disable low power mode 366 * @return the same object, so that setters can be chained 367 * @hide 368 */ 369 @SystemApi setLowPowerMode(boolean enabled)370 public @NonNull LocationRequest setLowPowerMode(boolean enabled) { 371 mLowPowerMode = enabled; 372 return this; 373 } 374 375 /** 376 * Returns true if low power mode is enabled. 377 * 378 * @hide 379 */ 380 @SystemApi isLowPowerMode()381 public boolean isLowPowerMode() { 382 return mLowPowerMode; 383 } 384 385 /** 386 * Requests that user location settings be ignored in order to satisfy this request. This API 387 * is only for use in extremely rare scenarios where it is appropriate to ignore user location 388 * settings, such as a user initiated emergency (dialing 911 for instance). 389 * 390 * @param locationSettingsIgnored Whether to ignore location settings 391 * @return the same object, so that setters can be chained 392 */ 393 @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS) setLocationSettingsIgnored(boolean locationSettingsIgnored)394 public @NonNull LocationRequest setLocationSettingsIgnored(boolean locationSettingsIgnored) { 395 mLocationSettingsIgnored = locationSettingsIgnored; 396 return this; 397 } 398 399 /** 400 * Returns true if location settings will be ignored in order to satisfy this request. 401 */ isLocationSettingsIgnored()402 public boolean isLocationSettingsIgnored() { 403 return mLocationSettingsIgnored; 404 } 405 406 /** 407 * Explicitly set the fastest interval for location updates, in 408 * milliseconds. 409 * 410 * <p>This controls the fastest rate at which your application will 411 * receive location updates, which might be faster than 412 * {@link #setInterval} in some situations (for example, if other 413 * applications are triggering location updates). 414 * 415 * <p>This allows your application to passively acquire locations 416 * at a rate faster than it actively acquires locations, saving power. 417 * 418 * <p>Unlike {@link #setInterval}, this parameter is exact. Your 419 * application will never receive updates faster than this value. 420 * 421 * <p>If you don't call this method, a fastest interval 422 * will be selected for you. It will be a value faster than your 423 * active interval ({@link #setInterval}). 424 * 425 * <p>An interval of 0 is allowed, but not recommended, since 426 * location updates may be extremely fast on future implementations. 427 * 428 * <p>If {@link #setFastestInterval} is set slower than {@link #setInterval}, 429 * then your effective fastest interval is {@link #setInterval}. 430 * 431 * @param millis fastest interval for updates in milliseconds, exact 432 * @return the same object, so that setters can be chained 433 * @throws IllegalArgumentException if the interval is less than zero 434 */ setFastestInterval(long millis)435 public @NonNull LocationRequest setFastestInterval(long millis) { 436 checkInterval(millis); 437 mExplicitFastestInterval = true; 438 mFastestInterval = millis; 439 return this; 440 } 441 442 /** 443 * Get the fastest interval of this request, in milliseconds. 444 * 445 * <p>The system will never provide location updates faster 446 * than the minimum of {@link #getFastestInterval} and 447 * {@link #getInterval}. 448 * 449 * @return fastest interval in milliseconds, exact 450 */ getFastestInterval()451 public long getFastestInterval() { 452 return mFastestInterval; 453 } 454 455 /** 456 * Set the duration of this request, in milliseconds. 457 * 458 * <p>The duration begins immediately (and not when the request 459 * is passed to the location manager), so call this method again 460 * if the request is re-used at a later time. 461 * 462 * <p>The location manager will automatically stop updates after 463 * the request expires. 464 * 465 * <p>The duration includes suspend time. Values less than 0 466 * are allowed, but indicate that the request has already expired. 467 * 468 * @param millis duration of request in milliseconds 469 * @return the same object, so that setters can be chained 470 */ setExpireIn(long millis)471 public @NonNull LocationRequest setExpireIn(long millis) { 472 long elapsedRealtime = SystemClock.elapsedRealtime(); 473 474 // Check for > Long.MAX_VALUE overflow (elapsedRealtime > 0): 475 if (millis > Long.MAX_VALUE - elapsedRealtime) { 476 mExpireAt = Long.MAX_VALUE; 477 } else { 478 mExpireAt = millis + elapsedRealtime; 479 } 480 481 if (mExpireAt < 0) mExpireAt = 0; 482 return this; 483 } 484 485 /** 486 * Set the request expiration time, in millisecond since boot. 487 * 488 * <p>This expiration time uses the same time base as {@link SystemClock#elapsedRealtime}. 489 * 490 * <p>The location manager will automatically stop updates after 491 * the request expires. 492 * 493 * <p>The duration includes suspend time. Values before {@link SystemClock#elapsedRealtime} 494 * are allowed, but indicate that the request has already expired. 495 * 496 * @param millis expiration time of request, in milliseconds since boot including suspend 497 * @return the same object, so that setters can be chained 498 */ setExpireAt(long millis)499 public @NonNull LocationRequest setExpireAt(long millis) { 500 mExpireAt = millis; 501 if (mExpireAt < 0) mExpireAt = 0; 502 return this; 503 } 504 505 /** 506 * Get the request expiration time, in milliseconds since boot. 507 * 508 * <p>This value can be compared to {@link SystemClock#elapsedRealtime} to determine 509 * the time until expiration. 510 * 511 * @return expiration time of request, in milliseconds since boot including suspend 512 */ getExpireAt()513 public long getExpireAt() { 514 return mExpireAt; 515 } 516 517 /** 518 * Set the number of location updates. 519 * 520 * <p>By default locations are continuously updated until the request is explicitly 521 * removed, however you can optionally request a set number of updates. 522 * For example, if your application only needs a single fresh location, 523 * then call this method with a value of 1 before passing the request 524 * to the location manager. 525 * 526 * @param numUpdates the number of location updates requested 527 * @return the same object, so that setters can be chained 528 * @throws IllegalArgumentException if numUpdates is 0 or less 529 */ setNumUpdates(int numUpdates)530 public @NonNull LocationRequest setNumUpdates(int numUpdates) { 531 if (numUpdates <= 0) { 532 throw new IllegalArgumentException( 533 "invalid numUpdates: " + numUpdates); 534 } 535 mNumUpdates = numUpdates; 536 return this; 537 } 538 539 /** 540 * Get the number of updates requested. 541 * 542 * <p>By default this is {@link Integer#MAX_VALUE}, which indicates that 543 * locations are updated until the request is explicitly removed. 544 * 545 * @return number of updates 546 */ getNumUpdates()547 public int getNumUpdates() { 548 return mNumUpdates; 549 } 550 551 /** @hide */ decrementNumUpdates()552 public void decrementNumUpdates() { 553 if (mNumUpdates != Integer.MAX_VALUE) { 554 mNumUpdates--; 555 } 556 if (mNumUpdates < 0) { 557 mNumUpdates = 0; 558 } 559 } 560 561 /** Sets the provider to use for this location request. */ setProvider(@onNull String provider)562 public @NonNull LocationRequest setProvider(@NonNull String provider) { 563 checkProvider(provider); 564 mProvider = provider; 565 return this; 566 } 567 568 /** @hide */ 569 @SystemApi getProvider()570 public @NonNull String getProvider() { 571 return mProvider; 572 } 573 574 /** @hide */ 575 @SystemApi setSmallestDisplacement(float meters)576 public @NonNull LocationRequest setSmallestDisplacement(float meters) { 577 checkDisplacement(meters); 578 mSmallestDisplacement = meters; 579 return this; 580 } 581 582 /** @hide */ 583 @SystemApi getSmallestDisplacement()584 public float getSmallestDisplacement() { 585 return mSmallestDisplacement; 586 } 587 588 /** 589 * Sets the WorkSource to use for power blaming of this location request. 590 * 591 * <p>No permissions are required to make this call, however the LocationManager 592 * will throw a SecurityException when requesting location updates if the caller 593 * doesn't have the {@link android.Manifest.permission#UPDATE_DEVICE_STATS} permission. 594 * 595 * @param workSource WorkSource defining power blame for this location request. 596 * @hide 597 */ 598 @SystemApi setWorkSource(@ullable WorkSource workSource)599 public void setWorkSource(@Nullable WorkSource workSource) { 600 mWorkSource = workSource; 601 } 602 603 /** @hide */ 604 @SystemApi getWorkSource()605 public @Nullable WorkSource getWorkSource() { 606 return mWorkSource; 607 } 608 609 /** 610 * Sets whether or not this location request should be hidden from AppOps. 611 * 612 * <p>Hiding a location request from AppOps will remove user visibility in the UI as to this 613 * request's existence. It does not affect power blaming in the Battery page. 614 * 615 * <p>No permissions are required to make this call, however the LocationManager 616 * will throw a SecurityException when requesting location updates if the caller 617 * doesn't have the {@link android.Manifest.permission#UPDATE_APP_OPS_STATS} permission. 618 * 619 * @param hideFromAppOps If true AppOps won't keep track of this location request. 620 * @hide 621 * @see android.app.AppOpsManager 622 */ 623 @SystemApi setHideFromAppOps(boolean hideFromAppOps)624 public void setHideFromAppOps(boolean hideFromAppOps) { 625 mHideFromAppOps = hideFromAppOps; 626 } 627 628 /** @hide */ 629 @SystemApi getHideFromAppOps()630 public boolean getHideFromAppOps() { 631 return mHideFromAppOps; 632 } 633 634 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) checkInterval(long millis)635 private static void checkInterval(long millis) { 636 if (millis < 0) { 637 throw new IllegalArgumentException("invalid interval: " + millis); 638 } 639 } 640 641 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) checkQuality(int quality)642 private static void checkQuality(int quality) { 643 switch (quality) { 644 case ACCURACY_FINE: 645 case ACCURACY_BLOCK: 646 case ACCURACY_CITY: 647 case POWER_NONE: 648 case POWER_LOW: 649 case POWER_HIGH: 650 break; 651 default: 652 throw new IllegalArgumentException("invalid quality: " + quality); 653 } 654 } 655 656 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) checkDisplacement(float meters)657 private static void checkDisplacement(float meters) { 658 if (meters < 0.0f) { 659 throw new IllegalArgumentException("invalid displacement: " + meters); 660 } 661 } 662 663 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) checkProvider(String name)664 private static void checkProvider(String name) { 665 if (name == null) { 666 throw new IllegalArgumentException("invalid provider: null"); 667 } 668 } 669 670 public static final @android.annotation.NonNull Parcelable.Creator<LocationRequest> CREATOR = 671 new Parcelable.Creator<LocationRequest>() { 672 @Override 673 public LocationRequest createFromParcel(Parcel in) { 674 LocationRequest request = new LocationRequest(); 675 request.setQuality(in.readInt()); 676 request.setFastestInterval(in.readLong()); 677 request.setInterval(in.readLong()); 678 request.setExpireAt(in.readLong()); 679 request.setNumUpdates(in.readInt()); 680 request.setSmallestDisplacement(in.readFloat()); 681 request.setHideFromAppOps(in.readInt() != 0); 682 request.setLowPowerMode(in.readInt() != 0); 683 request.setLocationSettingsIgnored(in.readInt() != 0); 684 String provider = in.readString(); 685 if (provider != null) request.setProvider(provider); 686 WorkSource workSource = in.readParcelable(null); 687 if (workSource != null) request.setWorkSource(workSource); 688 return request; 689 } 690 691 @Override 692 public LocationRequest[] newArray(int size) { 693 return new LocationRequest[size]; 694 } 695 }; 696 697 @Override describeContents()698 public int describeContents() { 699 return 0; 700 } 701 702 @Override writeToParcel(Parcel parcel, int flags)703 public void writeToParcel(Parcel parcel, int flags) { 704 parcel.writeInt(mQuality); 705 parcel.writeLong(mFastestInterval); 706 parcel.writeLong(mInterval); 707 parcel.writeLong(mExpireAt); 708 parcel.writeInt(mNumUpdates); 709 parcel.writeFloat(mSmallestDisplacement); 710 parcel.writeInt(mHideFromAppOps ? 1 : 0); 711 parcel.writeInt(mLowPowerMode ? 1 : 0); 712 parcel.writeInt(mLocationSettingsIgnored ? 1 : 0); 713 parcel.writeString(mProvider); 714 parcel.writeParcelable(mWorkSource, 0); 715 } 716 717 /** @hide */ qualityToString(int quality)718 public static String qualityToString(int quality) { 719 switch (quality) { 720 case ACCURACY_FINE: 721 return "ACCURACY_FINE"; 722 case ACCURACY_BLOCK: 723 return "ACCURACY_BLOCK"; 724 case ACCURACY_CITY: 725 return "ACCURACY_CITY"; 726 case POWER_NONE: 727 return "POWER_NONE"; 728 case POWER_LOW: 729 return "POWER_LOW"; 730 case POWER_HIGH: 731 return "POWER_HIGH"; 732 default: 733 return "???"; 734 } 735 } 736 737 @NonNull 738 @Override toString()739 public String toString() { 740 StringBuilder s = new StringBuilder(); 741 s.append("Request[").append(qualityToString(mQuality)); 742 if (mProvider != null) s.append(' ').append(mProvider); 743 if (mQuality != POWER_NONE) { 744 s.append(" requested="); 745 TimeUtils.formatDuration(mInterval, s); 746 } 747 s.append(" fastest="); 748 TimeUtils.formatDuration(mFastestInterval, s); 749 if (mExpireAt != Long.MAX_VALUE) { 750 long expireIn = mExpireAt - SystemClock.elapsedRealtime(); 751 s.append(" expireIn="); 752 TimeUtils.formatDuration(expireIn, s); 753 } 754 if (mNumUpdates != Integer.MAX_VALUE) { 755 s.append(" num=").append(mNumUpdates); 756 } 757 if (mLowPowerMode) { 758 s.append(" lowPowerMode"); 759 } 760 if (mLocationSettingsIgnored) { 761 s.append(" locationSettingsIgnored"); 762 } 763 s.append(']'); 764 return s.toString(); 765 } 766 } 767