• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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