• 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 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