• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 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.ACCESS_COARSE_LOCATION;
20 import static android.Manifest.permission.ACCESS_FINE_LOCATION;
21 import static android.Manifest.permission.LOCATION_BYPASS;
22 import static android.Manifest.permission.LOCATION_HARDWARE;
23 import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
24 import static android.location.LocationRequest.createFromDeprecatedCriteria;
25 import static android.location.LocationRequest.createFromDeprecatedProvider;
26 
27 import static com.android.internal.util.ConcurrentUtils.DIRECT_EXECUTOR;
28 
29 import android.Manifest;
30 import android.annotation.CallbackExecutor;
31 import android.annotation.NonNull;
32 import android.annotation.Nullable;
33 import android.annotation.RequiresFeature;
34 import android.annotation.RequiresPermission;
35 import android.annotation.SdkConstant;
36 import android.annotation.SdkConstant.SdkConstantType;
37 import android.annotation.SuppressLint;
38 import android.annotation.SystemApi;
39 import android.annotation.SystemService;
40 import android.annotation.TestApi;
41 import android.app.AppOpsManager;
42 import android.app.PendingIntent;
43 import android.app.PropertyInvalidatedCache;
44 import android.compat.Compatibility;
45 import android.compat.annotation.ChangeId;
46 import android.compat.annotation.EnabledAfter;
47 import android.content.Context;
48 import android.content.Intent;
49 import android.content.pm.PackageManager;
50 import android.location.provider.IProviderRequestListener;
51 import android.location.provider.ProviderProperties;
52 import android.location.provider.ProviderRequest;
53 import android.location.provider.ProviderRequest.ChangedListener;
54 import android.os.Build;
55 import android.os.Bundle;
56 import android.os.CancellationSignal;
57 import android.os.Handler;
58 import android.os.HandlerExecutor;
59 import android.os.ICancellationSignal;
60 import android.os.IRemoteCallback;
61 import android.os.Looper;
62 import android.os.PackageTagsList;
63 import android.os.Process;
64 import android.os.RemoteException;
65 import android.os.ServiceManager;
66 import android.os.UserHandle;
67 
68 import com.android.internal.annotations.GuardedBy;
69 import com.android.internal.listeners.ListenerExecutor;
70 import com.android.internal.listeners.ListenerTransport;
71 import com.android.internal.listeners.ListenerTransportManager;
72 import com.android.internal.util.Preconditions;
73 
74 import java.lang.ref.WeakReference;
75 import java.util.ArrayList;
76 import java.util.Collections;
77 import java.util.List;
78 import java.util.Objects;
79 import java.util.Set;
80 import java.util.WeakHashMap;
81 import java.util.concurrent.Executor;
82 import java.util.function.Consumer;
83 
84 /**
85  * This class provides access to the system location services. These services allow applications to
86  * obtain periodic updates of the device's geographical location, or to be notified when the device
87  * enters the proximity of a given geographical location.
88  *
89  * <p class="note">Unless otherwise noted, all Location API methods require the
90  * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION} or
91  * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} permissions. If your application only
92  * has the coarse permission then providers will still return location results, but the exact
93  * location will be obfuscated to a coarse level of accuracy.
94  */
95 @SuppressWarnings({"deprecation"})
96 @SystemService(Context.LOCATION_SERVICE)
97 @RequiresFeature(PackageManager.FEATURE_LOCATION)
98 public class LocationManager {
99 
100     /**
101      * For apps targeting Android S and above, immutable PendingIntents passed into location APIs
102      * will generate an IllegalArgumentException.
103      *
104      * @hide
105      */
106     @ChangeId
107     @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.R)
108     public static final long BLOCK_IMMUTABLE_PENDING_INTENTS = 171317480L;
109 
110     /**
111      * For apps targeting Android S and above, LocationRequest system APIs may not be used with
112      * PendingIntent location requests.
113      *
114      * @hide
115      */
116     @ChangeId
117     @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.R)
118     public static final long BLOCK_PENDING_INTENT_SYSTEM_API_USAGE = 169887240L;
119 
120     /**
121      * For apps targeting Android S and above, location clients may receive historical locations
122      * (from before the present time) under some circumstances.
123      *
124      * @hide
125      */
126     @ChangeId
127     @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.R)
128     public static final long DELIVER_HISTORICAL_LOCATIONS = 73144566L;
129 
130     /**
131      * For apps targeting Android R and above, {@link #getProvider(String)} will no longer throw any
132      * security exceptions.
133      *
134      * @hide
135      */
136     @ChangeId
137     @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.Q)
138     public static final long GET_PROVIDER_SECURITY_EXCEPTIONS = 150935354L;
139 
140     /**
141      * For apps targeting Android K and above, supplied {@link PendingIntent}s must be targeted to a
142      * specific package.
143      *
144      * @hide
145      */
146     @ChangeId
147     @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.JELLY_BEAN)
148     public static final long BLOCK_UNTARGETED_PENDING_INTENTS = 148963590L;
149 
150     /**
151      * For apps targeting Android K and above, incomplete locations may not be passed to
152      * {@link #setTestProviderLocation}.
153      *
154      * @hide
155      */
156     @ChangeId
157     @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.JELLY_BEAN)
158     public static final long BLOCK_INCOMPLETE_LOCATIONS = 148964793L;
159 
160     /**
161      * For apps targeting Android S and above, all {@link GpsStatus} API usage must be replaced with
162      * {@link GnssStatus} APIs.
163      *
164      * @hide
165      */
166     @ChangeId
167     @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.R)
168     public static final long BLOCK_GPS_STATUS_USAGE = 144027538L;
169 
170     /**
171      * Standard name of the network location provider.
172      *
173      * <p>If present, this provider determines location based on nearby of cell tower and WiFi
174      * access points. Operation of this provider may require a data connection.
175      */
176     public static final String NETWORK_PROVIDER = "network";
177 
178     /**
179      * Standard name of the GNSS location provider.
180      *
181      * <p>If present, this provider determines location using GNSS satellites. The responsiveness
182      * and accuracy of location fixes may depend on GNSS signal conditions.
183      *
184      * <p>Locations returned from this provider are with respect to the primary GNSS antenna
185      * position within the device. {@link #getGnssAntennaInfos()} may be used to determine the GNSS
186      * antenna position with respect to the Android Coordinate System, and convert between them if
187      * necessary. This is generally only necessary for high accuracy applications.
188      *
189      * <p>The extras Bundle for locations derived by this location provider may contain the
190      * following key/value pairs:
191      * <ul>
192      * <li> satellites - the number of satellites used to derive the fix
193      * </ul>
194      */
195     public static final String GPS_PROVIDER = "gps";
196 
197     /**
198      * A special location provider for receiving locations without actively initiating a location
199      * fix. This location provider is always present.
200      *
201      * <p>This provider can be used to passively receive location updates when other applications or
202      * services request them without actually requesting the locations yourself. This provider will
203      * only return locations generated by other providers.
204      */
205     public static final String PASSIVE_PROVIDER = "passive";
206 
207     /**
208      * Standard name of the fused location provider.
209      *
210      * <p>If present, this provider may combine inputs from several other location providers to
211      * provide the best possible location fix. It is implicitly used for all requestLocationUpdates
212      * APIs that involve a {@link Criteria}.
213      */
214     public static final String FUSED_PROVIDER = "fused";
215 
216     /**
217      * Key used for the Bundle extra holding a boolean indicating whether
218      * a proximity alert is entering (true) or exiting (false)..
219      */
220     public static final String KEY_PROXIMITY_ENTERING = "entering";
221 
222     /**
223      * This key is no longer in use.
224      *
225      * <p>Key used for a Bundle extra holding an Integer status value when a status change is
226      * broadcast using a PendingIntent.
227      *
228      * @deprecated Status changes are deprecated and no longer broadcast from Android Q onwards.
229      */
230     @Deprecated
231     public static final String KEY_STATUS_CHANGED = "status";
232 
233     /**
234      * Key used for an extra holding a boolean enabled/disabled status value when a provider
235      * enabled/disabled event is broadcast using a PendingIntent.
236      *
237      * @see #requestLocationUpdates(String, LocationRequest, PendingIntent)
238      */
239     public static final String KEY_PROVIDER_ENABLED = "providerEnabled";
240 
241     /**
242      * Key used for an extra holding a {@link Location} value when a location change is sent using
243      * a PendingIntent. If the location change includes a list of batched locations via
244      * {@link #KEY_LOCATIONS} then this key will still be present, and will hold the last location
245      * in the batch. Use {@link Intent#getParcelableExtra(String)} to retrieve the location.
246      *
247      * @see #requestLocationUpdates(String, LocationRequest, PendingIntent)
248      */
249     public static final String KEY_LOCATION_CHANGED = "location";
250 
251     /**
252      * Key used for an extra holding a array of {@link Location}s when a location change is sent
253      * using a PendingIntent. This key will only be present if the location change includes
254      * multiple (ie, batched) locations, otherwise only {@link #KEY_LOCATION_CHANGED} will be
255      * present. Use {@link Intent#getParcelableArrayExtra(String)} to retrieve the locations.
256      *
257      * <p>The array of locations will never be empty, and will ordered from earliest location to
258      * latest location, the same as with {@link LocationListener#onLocationChanged(List)}.
259      *
260      * @see #requestLocationUpdates(String, LocationRequest, PendingIntent)
261      */
262     public static final String KEY_LOCATIONS = "locations";
263 
264     /**
265      * Key used for an extra holding an integer request code when location flush completion is sent
266      * using a PendingIntent.
267      *
268      * @see #requestFlush(String, PendingIntent, int)
269      */
270     public static final String KEY_FLUSH_COMPLETE = "flushComplete";
271 
272     /**
273      * Broadcast intent action when the set of enabled location providers changes. To check the
274      * status of a provider, use {@link #isProviderEnabled(String)}. From Android Q and above, will
275      * include a string intent extra, {@link #EXTRA_PROVIDER_NAME}, with the name of the provider
276      * whose state has changed. From Android R and above, will include a boolean intent extra,
277      * {@link #EXTRA_PROVIDER_ENABLED}, with the enabled state of the provider.
278      *
279      * @see #EXTRA_PROVIDER_NAME
280      * @see #EXTRA_PROVIDER_ENABLED
281      * @see #isProviderEnabled(String)
282      */
283     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
284     public static final String PROVIDERS_CHANGED_ACTION = "android.location.PROVIDERS_CHANGED";
285 
286     /**
287      * Intent extra included with {@link #PROVIDERS_CHANGED_ACTION} broadcasts, containing the name
288      * of the location provider that has changed.
289      *
290      * @see #PROVIDERS_CHANGED_ACTION
291      * @see #EXTRA_PROVIDER_ENABLED
292      */
293     public static final String EXTRA_PROVIDER_NAME = "android.location.extra.PROVIDER_NAME";
294 
295     /**
296      * Intent extra included with {@link #PROVIDERS_CHANGED_ACTION} broadcasts, containing the
297      * boolean enabled state of the location provider that has changed.
298      *
299      * @see #PROVIDERS_CHANGED_ACTION
300      * @see #EXTRA_PROVIDER_NAME
301      */
302     public static final String EXTRA_PROVIDER_ENABLED = "android.location.extra.PROVIDER_ENABLED";
303 
304     /**
305      * Broadcast intent action when the device location enabled state changes. From Android R and
306      * above, will include a boolean intent extra, {@link #EXTRA_LOCATION_ENABLED}, with the enabled
307      * state of location.
308      *
309      * @see #EXTRA_LOCATION_ENABLED
310      * @see #isLocationEnabled()
311      */
312     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
313     public static final String MODE_CHANGED_ACTION = "android.location.MODE_CHANGED";
314 
315     /**
316      * Intent extra included with {@link #MODE_CHANGED_ACTION} broadcasts, containing the boolean
317      * enabled state of location.
318      *
319      * @see #MODE_CHANGED_ACTION
320      */
321     public static final String EXTRA_LOCATION_ENABLED = "android.location.extra.LOCATION_ENABLED";
322 
323     /**
324      * Broadcast intent action when the ADAS (Advanced Driving Assistance Systems) GNSS location
325      * enabled state changes. Includes a boolean intent extra, {@link #EXTRA_ADAS_GNSS_ENABLED},
326      * with the enabled state of ADAS GNSS location. This broadcast only has meaning on automotive
327      * devices.
328      *
329      * @see #EXTRA_ADAS_GNSS_ENABLED
330      * @see #isAdasGnssLocationEnabled()
331      *
332      * @hide
333      */
334     @SystemApi
335     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
336     public static final String ACTION_ADAS_GNSS_ENABLED_CHANGED =
337             "android.location.action.ADAS_GNSS_ENABLED_CHANGED";
338 
339     /**
340      * Intent extra included with {@link #ACTION_ADAS_GNSS_ENABLED_CHANGED} broadcasts, containing
341      * the boolean enabled state of ADAS GNSS location.
342      *
343      * @see #ACTION_ADAS_GNSS_ENABLED_CHANGED
344      *
345      * @hide
346      */
347     @SystemApi
348     public static final String EXTRA_ADAS_GNSS_ENABLED = "android.location.extra.ADAS_GNSS_ENABLED";
349 
350     /**
351      * Broadcast intent action indicating that a high power location requests
352      * has either started or stopped being active.  The current state of
353      * active location requests should be read from AppOpsManager using
354      * {@code OP_MONITOR_HIGH_POWER_LOCATION}.
355      *
356      * @hide
357      * @deprecated This action is unnecessary from Android S forward.
358      */
359     @Deprecated
360     public static final String HIGH_POWER_REQUEST_CHANGE_ACTION =
361             "android.location.HIGH_POWER_REQUEST_CHANGE";
362 
363     /**
364      * Broadcast intent action when GNSS capabilities change. This is most common at boot time as
365      * GNSS capabilities are queried from the chipset. Includes an intent extra,
366      * {@link #EXTRA_GNSS_CAPABILITIES}, with the new {@link GnssCapabilities}.
367      *
368      * @see #EXTRA_GNSS_CAPABILITIES
369      * @see #getGnssCapabilities()
370      */
371     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
372     public static final String ACTION_GNSS_CAPABILITIES_CHANGED =
373             "android.location.action.GNSS_CAPABILITIES_CHANGED";
374 
375     /**
376      * Intent extra included with {@link #ACTION_GNSS_CAPABILITIES_CHANGED} broadcasts, containing
377      * the new {@link GnssCapabilities}.
378      *
379      * @see #ACTION_GNSS_CAPABILITIES_CHANGED
380      */
381     public static final String EXTRA_GNSS_CAPABILITIES = "android.location.extra.GNSS_CAPABILITIES";
382 
383     /**
384      * Broadcast intent action for Settings app to inject a footer at the bottom of location
385      * settings. This is for use only by apps that are included in the system image.
386      *
387      * <p>To inject a footer to location settings, you must declare a broadcast receiver for
388      * this action in the manifest:
389      * <pre>
390      *     &lt;receiver android:name="com.example.android.footer.MyFooterInjector"&gt;
391      *         &lt;intent-filter&gt;
392      *             &lt;action android:name="com.android.settings.location.INJECT_FOOTER" /&gt;
393      *         &lt;/intent-filter&gt;
394      *         &lt;meta-data
395      *             android:name="com.android.settings.location.FOOTER_STRING"
396      *             android:resource="@string/my_injected_footer_string" /&gt;
397      *     &lt;/receiver&gt;
398      * </pre>
399      *
400      * <p>This broadcast receiver will never actually be invoked. See also
401      * {#METADATA_SETTINGS_FOOTER_STRING}.
402      *
403      * @hide
404      */
405     public static final String SETTINGS_FOOTER_DISPLAYED_ACTION =
406             "com.android.settings.location.DISPLAYED_FOOTER";
407 
408     /**
409      * Metadata name for {@link LocationManager#SETTINGS_FOOTER_DISPLAYED_ACTION} broadcast
410      * receivers to specify a string resource id as location settings footer text. This is for use
411      * only by apps that are included in the system image.
412      *
413      * <p>See {@link #SETTINGS_FOOTER_DISPLAYED_ACTION} for more detail on how to use.
414      *
415      * @hide
416      */
417     public static final String METADATA_SETTINGS_FOOTER_STRING =
418             "com.android.settings.location.FOOTER_STRING";
419 
420     private static final long MAX_SINGLE_LOCATION_TIMEOUT_MS = 30 * 1000;
421 
422     private static final String CACHE_KEY_LOCATION_ENABLED_PROPERTY =
423             "cache_key.location_enabled";
424 
getService()425     static ILocationManager getService() throws RemoteException {
426         try {
427             return ILocationManager.Stub.asInterface(
428                     ServiceManager.getServiceOrThrow(Context.LOCATION_SERVICE));
429         } catch (ServiceManager.ServiceNotFoundException e) {
430             throw new RemoteException(e);
431         }
432     }
433 
434     private static volatile LocationEnabledCache sLocationEnabledCache =
435             new LocationEnabledCache(4);
436 
437     @GuardedBy("sLocationListeners")
438     private static final WeakHashMap<LocationListener, WeakReference<LocationListenerTransport>>
439             sLocationListeners = new WeakHashMap<>();
440 
441     // allows lazy instantiation since most processes do not use GNSS APIs
442     private static class GnssLazyLoader {
443         static final GnssStatusTransportManager sGnssStatusListeners =
444                 new GnssStatusTransportManager();
445         static final GnssNmeaTransportManager sGnssNmeaListeners =
446                 new GnssNmeaTransportManager();
447         static final GnssMeasurementsTransportManager sGnssMeasurementsListeners =
448                 new GnssMeasurementsTransportManager();
449         static final GnssAntennaTransportManager sGnssAntennaInfoListeners =
450                 new GnssAntennaTransportManager();
451         static final GnssNavigationTransportManager sGnssNavigationListeners =
452                 new GnssNavigationTransportManager();
453     }
454 
455     private static class ProviderRequestLazyLoader {
456         static final ProviderRequestTransportManager sProviderRequestListeners =
457                 new ProviderRequestTransportManager();
458     }
459 
460     final Context mContext;
461     final ILocationManager mService;
462 
463     /**
464      * @hide
465      */
LocationManager(@onNull Context context, @NonNull ILocationManager service)466     public LocationManager(@NonNull Context context, @NonNull ILocationManager service) {
467         mContext = Objects.requireNonNull(context);
468         mService = Objects.requireNonNull(service);
469     }
470 
471     /**
472      * @hide
473      */
474     @TestApi
getBackgroundThrottlingWhitelist()475     public @NonNull String[] getBackgroundThrottlingWhitelist() {
476         try {
477             return mService.getBackgroundThrottlingWhitelist();
478         } catch (RemoteException e) {
479             throw e.rethrowFromSystemServer();
480         }
481     }
482 
483     /**
484      * @deprecated Do not use.
485      * @hide
486      */
487     @Deprecated
488     @TestApi
getIgnoreSettingsWhitelist()489     public @NonNull String[] getIgnoreSettingsWhitelist() {
490         return new String[0];
491     }
492 
493     /**
494      * For testing purposes only.
495      * @hide
496      */
497     @TestApi
getIgnoreSettingsAllowlist()498     public @NonNull PackageTagsList getIgnoreSettingsAllowlist() {
499         try {
500             return mService.getIgnoreSettingsAllowlist();
501         } catch (RemoteException e) {
502             throw e.rethrowFromSystemServer();
503         }
504     }
505 
506     /**
507      * Returns ADAS packages and their associated attribution tags.
508      *
509      * @hide
510      */
getAdasAllowlist()511     public @NonNull PackageTagsList getAdasAllowlist() {
512         try {
513             return mService.getAdasAllowlist();
514         } catch (RemoteException e) {
515             throw e.rethrowFromSystemServer();
516         }
517     }
518 
519     /**
520      * Returns the extra location controller package on the device.
521      *
522      * @hide
523      */
524     @SystemApi
getExtraLocationControllerPackage()525     public @Nullable String getExtraLocationControllerPackage() {
526         try {
527             return mService.getExtraLocationControllerPackage();
528         } catch (RemoteException e) {
529             throw e.rethrowFromSystemServer();
530         }
531     }
532 
533     /**
534      * Set the extra location controller package for location services on the device.
535      *
536      * @hide
537      */
538     @SystemApi
539     @RequiresPermission(Manifest.permission.LOCATION_HARDWARE)
setExtraLocationControllerPackage(@ullable String packageName)540     public void setExtraLocationControllerPackage(@Nullable String packageName) {
541         try {
542             mService.setExtraLocationControllerPackage(packageName);
543         } catch (RemoteException e) {
544             throw e.rethrowFromSystemServer();
545         }
546     }
547 
548     /**
549      * Set whether the extra location controller package is currently enabled on the device.
550      *
551      * @hide
552      */
553     @SystemApi
554     @RequiresPermission(Manifest.permission.LOCATION_HARDWARE)
setExtraLocationControllerPackageEnabled(boolean enabled)555     public void setExtraLocationControllerPackageEnabled(boolean enabled) {
556         try {
557             mService.setExtraLocationControllerPackageEnabled(enabled);
558         } catch (RemoteException e) {
559             throw e.rethrowFromSystemServer();
560         }
561     }
562 
563     /**
564      * Returns whether extra location controller package is currently enabled on the device.
565      *
566      * @hide
567      */
568     @SystemApi
isExtraLocationControllerPackageEnabled()569     public boolean isExtraLocationControllerPackageEnabled() {
570         try {
571             return mService.isExtraLocationControllerPackageEnabled();
572         } catch (RemoteException e) {
573             throw e.rethrowFromSystemServer();
574         }
575     }
576 
577     /**
578      * Set the extra location controller package for location services on the device.
579      *
580      * @removed
581      * @deprecated Use {@link #setExtraLocationControllerPackage} instead.
582      * @hide
583      */
584     @Deprecated
585     @SystemApi
586     @RequiresPermission(Manifest.permission.LOCATION_HARDWARE)
setLocationControllerExtraPackage(String packageName)587     public void setLocationControllerExtraPackage(String packageName) {
588         try {
589             mService.setExtraLocationControllerPackage(packageName);
590         } catch (RemoteException e) {
591             throw e.rethrowFromSystemServer();
592         }
593     }
594 
595     /**
596      * Set whether the extra location controller package is currently enabled on the device.
597      *
598      * @removed
599      * @deprecated Use {@link #setExtraLocationControllerPackageEnabled} instead.
600      * @hide
601      */
602     @SystemApi
603     @Deprecated
604     @RequiresPermission(Manifest.permission.LOCATION_HARDWARE)
setLocationControllerExtraPackageEnabled(boolean enabled)605     public void setLocationControllerExtraPackageEnabled(boolean enabled) {
606         try {
607             mService.setExtraLocationControllerPackageEnabled(enabled);
608         } catch (RemoteException e) {
609             throw e.rethrowFromSystemServer();
610         }
611     }
612 
613     /**
614      * Returns the current enabled/disabled state of location. To listen for changes, see
615      * {@link #MODE_CHANGED_ACTION}.
616      *
617      * @return true if location is enabled and false if location is disabled.
618      */
isLocationEnabled()619     public boolean isLocationEnabled() {
620         return isLocationEnabledForUser(mContext.getUser());
621     }
622 
623     /**
624      * Returns the current enabled/disabled state of location for the given user.
625      *
626      * @param userHandle the user to query
627      * @return true if location is enabled and false if location is disabled.
628      *
629      * @hide
630      */
631     @SystemApi
isLocationEnabledForUser(@onNull UserHandle userHandle)632     public boolean isLocationEnabledForUser(@NonNull UserHandle userHandle) {
633         // skip the cache for any "special" user ids - special ids like CURRENT_USER may change
634         // their meaning over time and should never be in the cache. we could resolve the special
635         // user ids here, but that would require an x-process call anyways, and the whole point of
636         // the cache is to avoid x-process calls.
637         if (userHandle.getIdentifier() >= 0) {
638             PropertyInvalidatedCache<Integer, Boolean> cache = sLocationEnabledCache;
639             if (cache != null) {
640                 return cache.query(userHandle.getIdentifier());
641             }
642         }
643 
644         try {
645             return mService.isLocationEnabledForUser(userHandle.getIdentifier());
646         } catch (RemoteException e) {
647             throw e.rethrowFromSystemServer();
648         }
649     }
650 
651     /**
652      * Enables or disables location for the given user.
653      *
654      * @param enabled true to enable location and false to disable location.
655      * @param userHandle the user to set
656      *
657      * @hide
658      */
659     @SystemApi
660     @RequiresPermission(WRITE_SECURE_SETTINGS)
setLocationEnabledForUser(boolean enabled, @NonNull UserHandle userHandle)661     public void setLocationEnabledForUser(boolean enabled, @NonNull UserHandle userHandle) {
662         try {
663             mService.setLocationEnabledForUser(enabled, userHandle.getIdentifier());
664         } catch (RemoteException e) {
665             throw e.rethrowFromSystemServer();
666         }
667     }
668 
669     /**
670      * Returns the current enabled/disabled state of ADAS (Advanced Driving Assistance Systems)
671      * GNSS location access for the given user. This controls safety critical automotive access to
672      * GNSS location. This only has meaning on automotive devices.
673      *
674      * @return true if ADAS location is enabled and false if ADAS location is disabled.
675      *
676      * @hide
677      */
678     @SystemApi
isAdasGnssLocationEnabled()679     public boolean isAdasGnssLocationEnabled() {
680         try {
681             return mService.isAdasGnssLocationEnabledForUser(mContext.getUser().getIdentifier());
682         } catch (RemoteException e) {
683             throw e.rethrowFromSystemServer();
684         }
685     }
686 
687     /**
688      * Enables or disables ADAS (Advanced Driving Assistance Systems) GNSS location access for the
689      * given user. This only has meaning on automotive devices.
690      *
691      * @param enabled true to enable ADAS location and false to disable ADAS location.
692      *
693      * @hide
694      */
695     @SystemApi
696     @RequiresPermission(LOCATION_BYPASS)
697     @RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE)
setAdasGnssLocationEnabled(boolean enabled)698     public void setAdasGnssLocationEnabled(boolean enabled) {
699         try {
700             mService.setAdasGnssLocationEnabledForUser(enabled, mContext.getUser().getIdentifier());
701         } catch (RemoteException e) {
702             throw e.rethrowFromSystemServer();
703         }
704     }
705 
706     /**
707      * Returns the current enabled/disabled status of the given provider. To listen for changes, see
708      * {@link #PROVIDERS_CHANGED_ACTION}.
709      *
710      * Before API version {@link android.os.Build.VERSION_CODES#LOLLIPOP}, this method would throw
711      * {@link SecurityException} if the location permissions were not sufficient to use the
712      * specified provider.
713      *
714      * @param provider a provider listed by {@link #getAllProviders()}
715      * @return true if the provider exists and is enabled
716      *
717      * @throws IllegalArgumentException if provider is null
718      */
isProviderEnabled(@onNull String provider)719     public boolean isProviderEnabled(@NonNull String provider) {
720         return isProviderEnabledForUser(provider, Process.myUserHandle());
721     }
722 
723     /**
724      * Returns the current enabled/disabled status of the given provider and user. Callers should
725      * prefer {@link #isLocationEnabledForUser(UserHandle)} unless they depend on provider-specific
726      * APIs.
727      *
728      * Before API version {@link android.os.Build.VERSION_CODES#LOLLIPOP}, this method would throw
729      * {@link SecurityException} if the location permissions were not sufficient to use the
730      * specified provider.
731      *
732      * @param provider a provider listed by {@link #getAllProviders()}
733      * @param userHandle the user to query
734      * @return true if the provider exists and is enabled
735      *
736      * @throws IllegalArgumentException if provider is null
737      * @hide
738      */
739     @SystemApi
isProviderEnabledForUser( @onNull String provider, @NonNull UserHandle userHandle)740     public boolean isProviderEnabledForUser(
741             @NonNull String provider, @NonNull UserHandle userHandle) {
742         Preconditions.checkArgument(provider != null, "invalid null provider");
743 
744         try {
745             return mService.isProviderEnabledForUser(provider, userHandle.getIdentifier());
746         } catch (RemoteException e) {
747             throw e.rethrowFromSystemServer();
748         }
749     }
750 
751     /**
752      * Method for enabling or disabling a single location provider. This method is deprecated and
753      * functions as a best effort. It should not be relied on in any meaningful sense as providers
754      * may no longer be enabled or disabled by clients.
755      *
756      * @param provider a provider listed by {@link #getAllProviders()}
757      * @param enabled whether to enable or disable the provider
758      * @param userHandle the user to set
759      * @return true if the value was set, false otherwise
760      *
761      * @throws IllegalArgumentException if provider is null
762      * @deprecated Do not manipulate providers individually, use
763      * {@link #setLocationEnabledForUser(boolean, UserHandle)} instead.
764      * @hide
765      */
766     @Deprecated
767     @SystemApi
768     @RequiresPermission(WRITE_SECURE_SETTINGS)
setProviderEnabledForUser( @onNull String provider, boolean enabled, @NonNull UserHandle userHandle)769     public boolean setProviderEnabledForUser(
770             @NonNull String provider, boolean enabled, @NonNull UserHandle userHandle) {
771         Preconditions.checkArgument(provider != null, "invalid null provider");
772         return false;
773     }
774 
775     /**
776      * Set whether GNSS requests are suspended on the automotive device.
777      *
778      * For devices where GNSS prevents the system from going into a low power state, GNSS should
779      * be suspended right before going into the lower power state and resumed right after the device
780      * wakes up.
781      *
782      * This method disables GNSS and should only be used for power management use cases such as
783      * suspend-to-RAM or suspend-to-disk.
784      *
785      * @hide
786      */
787     @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
788     @RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE)
789     @RequiresPermission(android.Manifest.permission.CONTROL_AUTOMOTIVE_GNSS)
setAutomotiveGnssSuspended(boolean suspended)790     public void setAutomotiveGnssSuspended(boolean suspended) {
791         try {
792             mService.setAutomotiveGnssSuspended(suspended);
793         } catch (RemoteException e) {
794             throw e.rethrowFromSystemServer();
795         }
796     }
797 
798     /**
799      * Return whether GNSS requests are suspended on the automotive device.
800      *
801      * @return true if GNSS requests are suspended and false if they aren't.
802      *
803      * @hide
804      */
805     @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
806     @RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE)
807     @RequiresPermission(android.Manifest.permission.CONTROL_AUTOMOTIVE_GNSS)
isAutomotiveGnssSuspended()808     public boolean isAutomotiveGnssSuspended() {
809         try {
810             return mService.isAutomotiveGnssSuspended();
811         } catch (RemoteException e) {
812             throw e.rethrowFromSystemServer();
813         }
814     }
815 
816     /**
817      * Gets the last known location from the fused provider, or null if there is no last known
818      * location. The returned location may be quite old in some circumstances, so the age of the
819      * location should always be checked.
820      *
821      * @return the last known location, or null if not available
822      *
823      * @throws SecurityException if no suitable location permission is present
824      *
825      * @hide
826      */
827     @Nullable
828     @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
getLastLocation()829     public Location getLastLocation() {
830         return getLastKnownLocation(FUSED_PROVIDER);
831     }
832 
833     /**
834      * Gets the last known location from the given provider, or null if there is no last known
835      * location. The returned location may be quite old in some circumstances, so the age of the
836      * location should always be checked.
837      *
838      * <p>This will never activate sensors to compute a new location, and will only ever return a
839      * cached location.
840      *
841      * <p>See also {@link #getCurrentLocation(String, CancellationSignal, Executor, Consumer)} which
842      * will always attempt to return a current location, but will potentially use additional power
843      * in the course of the attempt as compared to this method.
844      *
845      * @param provider a provider listed by {@link #getAllProviders()}
846      *
847      * @return the last known location for the given provider, or null if not available
848      *
849      * @throws SecurityException if no suitable permission is present
850      * @throws IllegalArgumentException if provider is null or doesn't exist
851      */
852     @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
853     @Nullable
getLastKnownLocation(@onNull String provider)854     public Location getLastKnownLocation(@NonNull String provider) {
855         return getLastKnownLocation(provider, new LastLocationRequest.Builder().build());
856     }
857 
858     /**
859      * Gets the last known location from the given provider, or null if there is no last known
860      * location.
861      *
862      * <p>See {@link LastLocationRequest} documentation for an explanation of various request
863      * parameters and how they can affect the returned location.
864      *
865      * <p>See {@link #getLastKnownLocation(String)} for more detail on how this method works.
866      *
867      * @param provider            a provider listed by {@link #getAllProviders()}
868      * @param lastLocationRequest the last location request containing location parameters
869      *
870      * @return the last known location for the given provider, or null if not available
871      *
872      * @throws SecurityException if no suitable permission is present
873      * @throws IllegalArgumentException if provider is null or doesn't exist
874      * @throws IllegalArgumentException if lastLocationRequest is null
875      *
876      * @hide
877      */
878     @SystemApi
879     @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
880     @Nullable
getLastKnownLocation(@onNull String provider, @NonNull LastLocationRequest lastLocationRequest)881     public Location getLastKnownLocation(@NonNull String provider,
882             @NonNull LastLocationRequest lastLocationRequest) {
883         Preconditions.checkArgument(provider != null, "invalid null provider");
884         Preconditions.checkArgument(lastLocationRequest != null,
885                 "invalid null last location request");
886 
887         try {
888             return mService.getLastLocation(provider, lastLocationRequest,
889                     mContext.getPackageName(), mContext.getAttributionTag());
890         } catch (RemoteException e) {
891             throw e.rethrowFromSystemServer();
892         }
893     }
894 
895     /**
896      * Asynchronously returns a single current location fix from the given provider.
897      *
898      * <p>See
899      * {@link #getCurrentLocation(String, LocationRequest, CancellationSignal, Executor, Consumer)}
900      * for more information.
901      *
902      * @param provider           a provider listed by {@link #getAllProviders()}
903      * @param cancellationSignal an optional signal that allows for cancelling this call
904      * @param executor           the callback will take place on this {@link Executor}
905      * @param consumer           the callback invoked with either a {@link Location} or null
906      *
907      * @throws IllegalArgumentException if provider is null or doesn't exist
908      * @throws IllegalArgumentException if executor is null
909      * @throws IllegalArgumentException if consumer is null
910      * @throws SecurityException        if no suitable permission is present
911      */
912     @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
getCurrentLocation(@onNull String provider, @Nullable CancellationSignal cancellationSignal, @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Location> consumer)913     public void getCurrentLocation(@NonNull String provider,
914             @Nullable CancellationSignal cancellationSignal,
915             @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Location> consumer) {
916         getCurrentLocation(
917                 provider,
918                 new LocationRequest.Builder(0).build(),
919                 cancellationSignal, executor, consumer);
920     }
921 
922     /**
923      * Asynchronously returns a single current location fix from the given provider based on the
924      * given {@link LocationRequest}.
925      *
926      * <p>See
927      * {@link #getCurrentLocation(String, LocationRequest, CancellationSignal, Executor, Consumer)}
928      * for more information.
929      *
930      * @param locationRequest    the location request containing location parameters
931      * @param cancellationSignal an optional signal that allows for cancelling this call
932      * @param executor           the callback will take place on this {@link Executor}
933      * @param consumer           the callback invoked with either a {@link Location} or null
934      *
935      * @throws IllegalArgumentException if provider is null or doesn't exist
936      * @throws IllegalArgumentException if executor is null
937      * @throws IllegalArgumentException if consumer is null
938      * @throws SecurityException        if no suitable permission is present
939      * @hide
940      * @deprecated Use
941      * {@link #getCurrentLocation(String, LocationRequest, CancellationSignal, Executor, Consumer)}
942      * instead.
943      */
944     @Deprecated
945     @SystemApi
946     @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
getCurrentLocation(@onNull LocationRequest locationRequest, @Nullable CancellationSignal cancellationSignal, @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Location> consumer)947     public void getCurrentLocation(@NonNull LocationRequest locationRequest,
948             @Nullable CancellationSignal cancellationSignal,
949             @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Location> consumer) {
950         Preconditions.checkArgument(locationRequest.getProvider() != null);
951         getCurrentLocation(locationRequest.getProvider(), locationRequest, cancellationSignal,
952                 executor, consumer);
953     }
954 
955     /**
956      * Asynchronously returns a single current location fix from the given provider based on the
957      * given {@link LocationRequest}. This may activate sensors in order to compute a new location,
958      * unlike {@link #getLastKnownLocation(String)}, which will only return a cached fix if
959      * available. The given callback will be invoked once and only once, either with a valid
960      * location or with a null location if the provider was unable to generate a valid location.
961      *
962      * <p>A client may supply an optional {@link CancellationSignal}. If this is used to cancel the
963      * operation, no callback should be expected after the cancellation.
964      *
965      * <p>This method may return locations from the very recent past (on the order of several
966      * seconds), but will never return older locations (for example, several minutes old or older).
967      * Clients may rely upon the guarantee that if this method returns a location, it will represent
968      * the best estimation of the location of the device in the present moment.
969      *
970      * <p>Clients calling this method from the background may notice that the method fails to
971      * determine a valid location fix more often than while in the foreground. Background
972      * applications may be throttled in their location accesses to some degree.
973      *
974      * The given location request may be used to provide hints on how a fresh location is computed
975      * if necessary. In particular {@link LocationRequest#getDurationMillis()} can be used to
976      * provide maximum duration allowed before failing. The system will always cap the maximum
977      * amount of time a request for current location may run to some reasonable value (less than a
978      * minute for example) before the request is failed.
979      *
980      * @param provider           a provider listed by {@link #getAllProviders()}
981      * @param locationRequest    the location request containing location parameters
982      * @param cancellationSignal an optional signal that allows for cancelling this call
983      * @param executor           the callback will take place on this {@link Executor}
984      * @param consumer           the callback invoked with either a {@link Location} or null
985      *
986      * @throws IllegalArgumentException if provider is null or doesn't exist
987      * @throws IllegalArgumentException if executor is null
988      * @throws IllegalArgumentException if consumer is null
989      * @throws SecurityException        if no suitable permission is present
990      */
991     @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
getCurrentLocation(@onNull String provider, @NonNull LocationRequest locationRequest, @Nullable CancellationSignal cancellationSignal, @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Location> consumer)992     public void getCurrentLocation(@NonNull String provider,
993             @NonNull LocationRequest locationRequest,
994             @Nullable CancellationSignal cancellationSignal,
995             @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Location> consumer) {
996         Preconditions.checkArgument(provider != null, "invalid null provider");
997         Preconditions.checkArgument(locationRequest != null, "invalid null location request");
998 
999         if (cancellationSignal != null) {
1000             cancellationSignal.throwIfCanceled();
1001         }
1002 
1003         GetCurrentLocationTransport transport = new GetCurrentLocationTransport(executor, consumer,
1004                 cancellationSignal);
1005 
1006         ICancellationSignal cancelRemote;
1007         try {
1008             cancelRemote = mService.getCurrentLocation(provider,
1009                     locationRequest, transport, mContext.getPackageName(),
1010                     mContext.getAttributionTag(), AppOpsManager.toReceiverId(consumer));
1011         } catch (RemoteException e) {
1012             throw e.rethrowFromSystemServer();
1013         }
1014 
1015         if (cancellationSignal != null) {
1016             cancellationSignal.setRemote(cancelRemote);
1017         }
1018     }
1019 
1020     /**
1021      * Register for a single location update using the named provider and a callback.
1022      *
1023      * <p>See {@link #requestLocationUpdates(String, long, float, LocationListener, Looper)} for
1024      * more detail on how to use this method.
1025      *
1026      * @param provider a provider listed by {@link #getAllProviders()}
1027      * @param listener the listener to receive location updates
1028      * @param looper   the looper handling listener callbacks, or null to use the looper of the
1029      *                 calling thread
1030      *
1031      * @throws IllegalArgumentException if provider is null or doesn't exist
1032      * @throws IllegalArgumentException if listener is null
1033      * @throws SecurityException        if no suitable permission is present
1034      * @deprecated Use {@link #getCurrentLocation(String, CancellationSignal, Executor, Consumer)}
1035      * instead as it does not carry a risk of extreme battery drain.
1036      */
1037     @Deprecated
1038     @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
requestSingleUpdate( @onNull String provider, @NonNull LocationListener listener, @Nullable Looper looper)1039     public void requestSingleUpdate(
1040             @NonNull String provider, @NonNull LocationListener listener, @Nullable Looper looper) {
1041         Preconditions.checkArgument(provider != null, "invalid null provider");
1042 
1043         Handler handler = looper == null ? new Handler() : new Handler(looper);
1044         requestLocationUpdates(
1045                 provider,
1046                 new LocationRequest.Builder(0)
1047                         .setMaxUpdates(1)
1048                         .setDurationMillis(MAX_SINGLE_LOCATION_TIMEOUT_MS)
1049                         .build(),
1050                 new HandlerExecutor(handler),
1051                 listener);
1052     }
1053 
1054     /**
1055      * Register for a single location update using a Criteria and a callback.
1056      *
1057      * <p>Note: Since Android KitKat, Criteria requests will always result in using the
1058      * {@link #FUSED_PROVIDER}.
1059      *
1060      * <p>See {@link #requestLocationUpdates(long, float, Criteria, PendingIntent)} for more detail
1061      * on how to use this method.
1062      *
1063      * @param criteria contains parameters to choose the appropriate provider for location updates
1064      * @param listener the listener to receive location updates
1065      * @param looper   the looper handling listener callbacks, or null to use the looper of the
1066      *                 calling thread
1067      *
1068      * @throws IllegalArgumentException if criteria is null
1069      * @throws IllegalArgumentException if listener is null
1070      * @throws SecurityException        if no suitable permission is present
1071      * @deprecated Use {@link #getCurrentLocation(String, CancellationSignal, Executor, Consumer)}
1072      * instead as it does not carry a risk of extreme battery drain.
1073      */
1074     @Deprecated
1075     @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
requestSingleUpdate( @onNull Criteria criteria, @NonNull LocationListener listener, @Nullable Looper looper)1076     public void requestSingleUpdate(
1077             @NonNull Criteria criteria,
1078             @NonNull LocationListener listener,
1079             @Nullable Looper looper) {
1080         Preconditions.checkArgument(criteria != null, "invalid null criteria");
1081 
1082         Handler handler = looper == null ? new Handler() : new Handler(looper);
1083         requestLocationUpdates(
1084                 FUSED_PROVIDER,
1085                 new LocationRequest.Builder(0)
1086                         .setQuality(criteria)
1087                         .setMaxUpdates(1)
1088                         .setDurationMillis(MAX_SINGLE_LOCATION_TIMEOUT_MS)
1089                         .build(),
1090                 new HandlerExecutor(handler),
1091                 listener);
1092     }
1093 
1094     /**
1095      * Register for a single location update using a named provider and pending intent.
1096      *
1097      * <p>See {@link #requestLocationUpdates(long, float, Criteria, PendingIntent)} for more detail
1098      * on how to use this method.
1099      *
1100      * @param provider      a provider listed by {@link #getAllProviders()}
1101      * @param pendingIntent the pending intent to send location updates
1102      *
1103      * @throws IllegalArgumentException if provider is null or doesn't exist
1104      * @throws IllegalArgumentException if intent is null
1105      * @throws SecurityException        if no suitable permission is present
1106      * @deprecated Use {@link #getCurrentLocation(String, CancellationSignal, Executor, Consumer)}
1107      * instead as it does not carry a risk of extreme battery drain.
1108      */
1109     @Deprecated
1110     @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
requestSingleUpdate(@onNull String provider, @NonNull PendingIntent pendingIntent)1111     public void requestSingleUpdate(@NonNull String provider,
1112             @NonNull PendingIntent pendingIntent) {
1113         Preconditions.checkArgument(provider != null, "invalid null provider");
1114 
1115         requestLocationUpdates(
1116                 provider,
1117                 new LocationRequest.Builder(0)
1118                         .setMaxUpdates(1)
1119                         .setDurationMillis(MAX_SINGLE_LOCATION_TIMEOUT_MS)
1120                         .build(),
1121                 pendingIntent);
1122     }
1123 
1124     /**
1125      * Register for a single location update using a Criteria and pending intent.
1126      *
1127      * <p>Note: Since Android KitKat, Criteria requests will always result in using the
1128      * {@link #FUSED_PROVIDER}.
1129      *
1130      * <p>See {@link #requestLocationUpdates(long, float, Criteria, PendingIntent)} for more detail
1131      * on how to use this method.
1132      *
1133      * @param criteria      contains parameters to choose the appropriate provider for location
1134      *                      updates
1135      * @param pendingIntent the pending intent to send location updates
1136      *
1137      * @throws IllegalArgumentException if provider is null or doesn't exist
1138      * @throws IllegalArgumentException if intent is null
1139      * @throws SecurityException        if no suitable permission is present
1140      * @deprecated Use {@link #getCurrentLocation(String, CancellationSignal, Executor, Consumer)}
1141      * instead as it does not carry a risk of extreme battery drain.
1142      */
1143     @Deprecated
1144     @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
requestSingleUpdate(@onNull Criteria criteria, @NonNull PendingIntent pendingIntent)1145     public void requestSingleUpdate(@NonNull Criteria criteria,
1146             @NonNull PendingIntent pendingIntent) {
1147         Preconditions.checkArgument(criteria != null, "invalid null criteria");
1148 
1149         requestLocationUpdates(
1150                 FUSED_PROVIDER,
1151                 new LocationRequest.Builder(0)
1152                         .setQuality(criteria)
1153                         .setMaxUpdates(1)
1154                         .setDurationMillis(MAX_SINGLE_LOCATION_TIMEOUT_MS)
1155                         .build(),
1156                 pendingIntent);
1157     }
1158 
1159     /**
1160      * Register for location updates from the given provider with the given arguments, and a
1161      * callback on the {@link Looper} of the calling thread.
1162      *
1163      * <p>See {@link #requestLocationUpdates(String, LocationRequest, Executor, LocationListener)}
1164      * for more detail on how this method works.
1165      *
1166      * <p class="note"> Prior to Jellybean, the minTime parameter was only a hint, and some location
1167      * provider implementations ignored it. For Jellybean and onwards however, it is mandatory for
1168      * Android compatible devices to observe both the minTime and minDistance parameters.
1169      *
1170      * @param provider     a provider listed by {@link #getAllProviders()}
1171      * @param minTimeMs    minimum time interval between location updates in milliseconds
1172      * @param minDistanceM minimum distance between location updates in meters
1173      * @param listener     the listener to receive location updates
1174      *
1175      * @throws IllegalArgumentException if provider is null or doesn't exist
1176      * @throws IllegalArgumentException if listener is null
1177      * @throws RuntimeException if the calling thread has no Looper
1178      * @throws SecurityException if no suitable permission is present
1179      */
1180     @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
requestLocationUpdates(@onNull String provider, long minTimeMs, float minDistanceM, @NonNull LocationListener listener)1181     public void requestLocationUpdates(@NonNull String provider, long minTimeMs, float minDistanceM,
1182             @NonNull LocationListener listener) {
1183         requestLocationUpdates(provider, minTimeMs, minDistanceM, listener, null);
1184     }
1185 
1186     /**
1187      * Register for location updates from the given provider with the given arguments, and a
1188      * callback on the specified {@link Looper}.
1189      *
1190      * <p>See {@link #requestLocationUpdates(String, LocationRequest, Executor, LocationListener)}
1191      * for more detail on how this method works.
1192      *
1193      * <p class="note">Prior to Jellybean, the minTime parameter was only a hint, and some location
1194      * provider implementations ignored it. For Jellybean and onwards however, it is mandatory for
1195      * Android compatible devices to observe both the minTime and minDistance parameters.
1196      *
1197      * @param provider     a provider listed by {@link #getAllProviders()}
1198      * @param minTimeMs    minimum time interval between location updates in milliseconds
1199      * @param minDistanceM minimum distance between location updates in meters
1200      * @param listener     the listener to receive location updates
1201      * @param looper       the looper handling listener callbacks, or null to use the looper of the
1202      *                     calling thread
1203      *
1204      * @throws IllegalArgumentException if provider is null or doesn't exist
1205      * @throws IllegalArgumentException if listener is null
1206      * @throws SecurityException if no suitable permission is present
1207      */
1208     @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
requestLocationUpdates(@onNull String provider, long minTimeMs, float minDistanceM, @NonNull LocationListener listener, @Nullable Looper looper)1209     public void requestLocationUpdates(@NonNull String provider, long minTimeMs, float minDistanceM,
1210             @NonNull LocationListener listener, @Nullable Looper looper) {
1211         Handler handler = looper == null ? new Handler() : new Handler(looper);
1212         requestLocationUpdates(provider, minTimeMs, minDistanceM, new HandlerExecutor(handler),
1213                 listener);
1214     }
1215 
1216     /**
1217      * Register for location updates using the named provider, and a callback on
1218      * the specified {@link Executor}.
1219      *
1220      * <p>See {@link #requestLocationUpdates(String, LocationRequest, Executor, LocationListener)}
1221      * for more detail on how this method works.
1222      *
1223      * <p class="note">Prior to Jellybean, the minTime parameter was only a hint, and some location
1224      * provider implementations ignored it. For Jellybean and onwards however, it is mandatory for
1225      * Android compatible devices to observe both the minTime and minDistance parameters.
1226      *
1227      * @param provider     a provider listed by {@link #getAllProviders()}
1228      * @param minTimeMs    minimum time interval between location updates in milliseconds
1229      * @param minDistanceM minimum distance between location updates in meters
1230      * @param executor     the executor handling listener callbacks
1231      * @param listener     the listener to receive location updates
1232      *
1233      * @throws IllegalArgumentException if provider is null or doesn't exist
1234      * @throws IllegalArgumentException if executor is null
1235      * @throws IllegalArgumentException if listener is null
1236      * @throws SecurityException if no suitable permission is present
1237      */
1238     @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
requestLocationUpdates( @onNull String provider, long minTimeMs, float minDistanceM, @NonNull @CallbackExecutor Executor executor, @NonNull LocationListener listener)1239     public void requestLocationUpdates(
1240             @NonNull String provider,
1241             long minTimeMs,
1242             float minDistanceM,
1243             @NonNull @CallbackExecutor Executor executor,
1244             @NonNull LocationListener listener) {
1245         Preconditions.checkArgument(provider != null, "invalid null provider");
1246 
1247         requestLocationUpdates(
1248                 provider,
1249                 createFromDeprecatedProvider(provider, minTimeMs, minDistanceM, false),
1250                 executor,
1251                 listener);
1252     }
1253 
1254     /**
1255      * Register for location updates using a provider selected through the given Criteria, and a
1256      * callback on the specified {@link Looper}.
1257      *
1258      * <p>Note: Since Android KitKat, Criteria requests will always result in using the
1259      * {@link #FUSED_PROVIDER}.
1260      *
1261      * <p>See {@link #requestLocationUpdates(String, LocationRequest, Executor, LocationListener)}
1262      * for more detail on how this method works.
1263      *
1264      * @param minTimeMs minimum time interval between location updates in milliseconds
1265      * @param minDistanceM minimum distance between location updates in meters
1266      * @param criteria contains parameters to choose the appropriate provider for location updates
1267      * @param listener the listener to receive location updates
1268      *
1269      * @throws IllegalArgumentException if criteria is null
1270      * @throws IllegalArgumentException if listener is null
1271      * @throws SecurityException if no suitable permission is present
1272      *
1273      * @deprecated Use
1274      * {@link #requestLocationUpdates(String, long, float, LocationListener, Looper)} instead to
1275      * explicitly select a provider.
1276      */
1277     @Deprecated
1278     @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
requestLocationUpdates(long minTimeMs, float minDistanceM, @NonNull Criteria criteria, @NonNull LocationListener listener, @Nullable Looper looper)1279     public void requestLocationUpdates(long minTimeMs, float minDistanceM,
1280             @NonNull Criteria criteria, @NonNull LocationListener listener,
1281             @Nullable Looper looper) {
1282         Handler handler = looper == null ? new Handler() : new Handler(looper);
1283         requestLocationUpdates(minTimeMs, minDistanceM, criteria, new HandlerExecutor(handler),
1284                 listener);
1285     }
1286 
1287     /**
1288      * Register for location updates using a provider selected through the given Criteria, and a
1289      * callback on the specified {@link Executor}.
1290      *
1291      * <p>Note: Since Android KitKat, Criteria requests will always result in using the
1292      * {@link #FUSED_PROVIDER}.
1293      *
1294      * <p>See {@link #requestLocationUpdates(String, LocationRequest, Executor, LocationListener)}
1295      * for more detail on how this method works.
1296      *
1297      * @param minTimeMs minimum time interval between location updates in milliseconds
1298      * @param minDistanceM minimum distance between location updates in meters
1299      * @param criteria contains parameters to choose the appropriate provider for location updates
1300      * @param executor the executor handling listener callbacks
1301      * @param listener the listener to receive location updates
1302      *
1303      * @throws IllegalArgumentException if criteria is null
1304      * @throws IllegalArgumentException if executor is null
1305      * @throws IllegalArgumentException if listener is null
1306      * @throws SecurityException        if no suitable permission is present
1307      *
1308      * @deprecated Use
1309      * {@link #requestLocationUpdates(String, long, float, Executor, LocationListener)} instead to
1310      * explicitly select a provider.
1311      */
1312     @Deprecated
1313     @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
requestLocationUpdates( long minTimeMs, float minDistanceM, @NonNull Criteria criteria, @NonNull @CallbackExecutor Executor executor, @NonNull LocationListener listener)1314     public void requestLocationUpdates(
1315             long minTimeMs,
1316             float minDistanceM,
1317             @NonNull Criteria criteria,
1318             @NonNull @CallbackExecutor Executor executor,
1319             @NonNull LocationListener listener) {
1320         Preconditions.checkArgument(criteria != null, "invalid null criteria");
1321 
1322         requestLocationUpdates(
1323                 FUSED_PROVIDER,
1324                 createFromDeprecatedCriteria(criteria, minTimeMs, minDistanceM, false),
1325                 executor,
1326                 listener);
1327     }
1328 
1329     /**
1330      * Register for location updates using the named provider, and callbacks delivered via the
1331      * provided {@link PendingIntent}.
1332      *
1333      * <p>See {@link #requestLocationUpdates(String, LocationRequest, PendingIntent)} for more
1334      * detail on how this method works.
1335      *
1336      * @param provider      a provider listed by {@link #getAllProviders()}
1337      * @param minTimeMs     minimum time interval between location updates in milliseconds
1338      * @param minDistanceM  minimum distance between location updates in meters
1339      * @param pendingIntent the pending intent to send location updates
1340      *
1341      * @throws IllegalArgumentException if provider is null or doesn't exist
1342      * @throws IllegalArgumentException if pendingIntent is null
1343      * @throws SecurityException if no suitable permission is present
1344      */
1345     @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
requestLocationUpdates(@onNull String provider, long minTimeMs, float minDistanceM, @NonNull PendingIntent pendingIntent)1346     public void requestLocationUpdates(@NonNull String provider, long minTimeMs, float minDistanceM,
1347             @NonNull PendingIntent pendingIntent) {
1348         Preconditions.checkArgument(provider != null, "invalid null provider");
1349 
1350         requestLocationUpdates(
1351                 provider,
1352                 createFromDeprecatedProvider(provider, minTimeMs, minDistanceM, false),
1353                 pendingIntent);
1354     }
1355 
1356     /**
1357      * Register for location updates using a provider selected through the given Criteria, and
1358      * callbacks delivered via the provided {@link PendingIntent}.
1359      *
1360      * <p>Note: Since Android KitKat, Criteria requests will always result in using the
1361      * {@link #FUSED_PROVIDER}.
1362      *
1363      * <p>See {@link #requestLocationUpdates(String, long, float, PendingIntent)} for more detail on
1364      * how this method works.
1365      *
1366      * @param minTimeMs minimum time interval between location updates in milliseconds
1367      * @param minDistanceM minimum distance between location updates in meters
1368      * @param criteria contains parameters to choose the appropriate provider for location updates
1369      * @param pendingIntent the pending intent to send location updates
1370      *
1371      * @throws IllegalArgumentException if provider is null or doesn't exist
1372      * @throws IllegalArgumentException if pendingIntent is null
1373      * @throws SecurityException if no suitable permission is present
1374      *
1375      * @deprecated Use {@link #requestLocationUpdates(String, long, float, PendingIntent)} instead
1376      * to explicitly select a provider.
1377      */
1378     @Deprecated
1379     @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
requestLocationUpdates(long minTimeMs, float minDistanceM, @NonNull Criteria criteria, @NonNull PendingIntent pendingIntent)1380     public void requestLocationUpdates(long minTimeMs, float minDistanceM,
1381             @NonNull Criteria criteria, @NonNull PendingIntent pendingIntent) {
1382         Preconditions.checkArgument(criteria != null, "invalid null criteria");
1383         requestLocationUpdates(
1384                 FUSED_PROVIDER,
1385                 createFromDeprecatedCriteria(criteria, minTimeMs, minDistanceM, false),
1386                 pendingIntent);
1387     }
1388 
1389     /**
1390      * Register for location updates using a {@link LocationRequest}, and a callback on the
1391      * specified {@link Looper}.
1392      *
1393      * <p>The system will automatically select and enable the best provider based on the given
1394      * {@link LocationRequest}. The LocationRequest can be null, in which case the system will
1395      * choose default low power parameters for location updates, but this is heavily discouraged,
1396      * and an explicit LocationRequest should always be provided.
1397      *
1398      * <p>See {@link #requestLocationUpdates(String, LocationRequest, Executor, LocationListener)}
1399      * for more detail on how this method works.
1400      *
1401      * @param locationRequest the location request containing location parameters
1402      * @param listener the listener to receive location updates
1403      * @param looper the looper handling listener callbacks, or null to use the looper of the
1404      *               calling thread
1405      *
1406      * @throws IllegalArgumentException if listener is null
1407      * @throws SecurityException if no suitable permission is present
1408      *
1409      * @hide
1410      * @deprecated Use
1411      * {@link #requestLocationUpdates(String, LocationRequest, Executor, LocationListener)} instead.
1412      */
1413     @Deprecated
1414     @SystemApi
1415     @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
requestLocationUpdates( @ullable LocationRequest locationRequest, @NonNull LocationListener listener, @Nullable Looper looper)1416     public void requestLocationUpdates(
1417             @Nullable LocationRequest locationRequest,
1418             @NonNull LocationListener listener,
1419             @Nullable Looper looper) {
1420         Handler handler = looper == null ? new Handler() : new Handler(looper);
1421         requestLocationUpdates(locationRequest, new HandlerExecutor(handler), listener);
1422     }
1423 
1424     /**
1425      * Register for location updates using a {@link LocationRequest}, and a callback on the
1426      * specified {@link Executor}.
1427      *
1428      * <p>See {@link #requestLocationUpdates(String, LocationRequest, Executor, LocationListener)}
1429      * for more detail on how this method works.
1430      *
1431      * @param locationRequest the location request containing location parameters
1432      * @param executor the executor handling listener callbacks
1433      * @param listener the listener to receive location updates
1434      *
1435      * @throws IllegalArgumentException if executor is null
1436      * @throws IllegalArgumentException if listener is null
1437      * @throws SecurityException if no suitable permission is present
1438      *
1439      * @hide
1440      * @deprecated Use
1441      * {@link #requestLocationUpdates(String, LocationRequest, Executor, LocationListener)} instead.
1442      */
1443     @Deprecated
1444     @SystemApi
1445     @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
requestLocationUpdates( @ullable LocationRequest locationRequest, @NonNull @CallbackExecutor Executor executor, @NonNull LocationListener listener)1446     public void requestLocationUpdates(
1447             @Nullable LocationRequest locationRequest,
1448             @NonNull @CallbackExecutor Executor executor,
1449             @NonNull LocationListener listener) {
1450         if (locationRequest == null) {
1451             locationRequest = LocationRequest.create();
1452         }
1453         Preconditions.checkArgument(locationRequest.getProvider() != null);
1454         requestLocationUpdates(locationRequest.getProvider(), locationRequest, executor, listener);
1455     }
1456 
1457     /**
1458      * Register for location updates using a {@link LocationRequest}, and callbacks delivered via
1459      * the provided {@link PendingIntent}.
1460      *
1461      * <p>See {@link #requestLocationUpdates(String, LocationRequest, PendingIntent)} for more
1462      * detail on how this method works.
1463      *
1464      * @param locationRequest the location request containing location parameters
1465      * @param pendingIntent the pending intent to send location updates
1466      *
1467      * @throws IllegalArgumentException if pendingIntent is null
1468      * @throws SecurityException if no suitable permission is present
1469      *
1470      * @hide
1471      * @deprecated Use {@link #requestLocationUpdates(String, LocationRequest, PendingIntent)}
1472      * instead.
1473      */
1474     @Deprecated
1475     @SystemApi
1476     @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
requestLocationUpdates( @ullable LocationRequest locationRequest, @NonNull PendingIntent pendingIntent)1477     public void requestLocationUpdates(
1478             @Nullable LocationRequest locationRequest,
1479             @NonNull PendingIntent pendingIntent) {
1480         if (locationRequest == null) {
1481             locationRequest = LocationRequest.create();
1482         }
1483         Preconditions.checkArgument(locationRequest.getProvider() != null);
1484         requestLocationUpdates(locationRequest.getProvider(), locationRequest, pendingIntent);
1485     }
1486 
1487     /**
1488      * Register for location updates from the specified provider, using a {@link LocationRequest},
1489      * and a callback on the specified {@link Executor}.
1490      *
1491      * <p>Only one request can be registered for each unique listener/provider pair, so any
1492      * subsequent requests with the same provider and listener will overwrite all associated
1493      * arguments. The same listener may be used across multiple providers with different requests
1494      * for each provider.
1495      *
1496      * <p>It may take some time to receive the first location update depending on the conditions the
1497      * device finds itself in. In order to take advantage of cached locations, application may
1498      * consider using {@link #getLastKnownLocation(String)} or {@link #getCurrentLocation(String,
1499      * LocationRequest, CancellationSignal, Executor, Consumer)} instead.
1500      *
1501      * <p>See {@link LocationRequest} documentation for an explanation of various request parameters
1502      * and how they can affect the received locations.
1503      *
1504      * <p>If your application wants to passively observe location updates from all providers, then
1505      * use the {@link #PASSIVE_PROVIDER}. This provider does not turn on or modify active location
1506      * providers, so you do not need to be as careful about minimum time and minimum distance
1507      * parameters. However, if your application performs heavy work on a location update (such as
1508      * network activity) then you should set an explicit fastest interval on your location request
1509      * in case another application enables a location provider with extremely fast updates.
1510      *
1511      * <p>In case the provider you have selected is disabled, location updates will cease, and a
1512      * provider availability update will be sent. As soon as the provider is enabled again, another
1513      * provider availability update will be sent and location updates will resume.
1514      *
1515      * <p>Locations returned from {@link #GPS_PROVIDER} are with respect to the primary GNSS antenna
1516      * position within the device. {@link #getGnssAntennaInfos()} may be used to determine the GNSS
1517      * antenna position with respect to the Android Coordinate System, and convert between them if
1518      * necessary. This is generally only necessary for high accuracy applications.
1519      *
1520      * <p>When location callbacks are invoked, the system will hold a wakelock on your
1521      * application's behalf for some period of time, but not indefinitely. If your application
1522      * requires a long running wakelock within the location callback, you should acquire it
1523      * yourself.
1524      *
1525      * <p>Spamming location requests is a drain on system resources, and the system has preventative
1526      * measures in place to ensure that this behavior will never result in more locations than could
1527      * be achieved with a single location request with an equivalent interval that is left in place
1528      * the whole time. As part of this amelioration, applications that target Android S and above
1529      * may receive cached or historical locations through their listener. These locations will never
1530      * be older than the interval of the location request.
1531      *
1532      * <p>To unregister for location updates, use {@link #removeUpdates(LocationListener)}.
1533      *
1534      * @param provider a provider listed by {@link #getAllProviders()}
1535      * @param locationRequest the location request containing location parameters
1536      * @param executor the executor handling listener callbacks
1537      * @param listener the listener to receive location updates
1538      *
1539      * @throws IllegalArgumentException if provider is null or doesn't exist
1540      * @throws IllegalArgumentException if locationRequest is null
1541      * @throws IllegalArgumentException if listener is null
1542      * @throws SecurityException if no suitable permission is present
1543      */
1544     @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
requestLocationUpdates(@onNull String provider, @NonNull LocationRequest locationRequest, @NonNull @CallbackExecutor Executor executor, @NonNull LocationListener listener)1545     public void requestLocationUpdates(@NonNull String provider,
1546             @NonNull LocationRequest locationRequest,
1547             @NonNull @CallbackExecutor Executor executor,
1548             @NonNull LocationListener listener) {
1549         Preconditions.checkArgument(provider != null, "invalid null provider");
1550         Preconditions.checkArgument(locationRequest != null, "invalid null location request");
1551 
1552         try {
1553             synchronized (sLocationListeners) {
1554                 WeakReference<LocationListenerTransport> reference = sLocationListeners.get(
1555                         listener);
1556                 LocationListenerTransport transport = reference != null ? reference.get() : null;
1557                 if (transport == null) {
1558                     transport = new LocationListenerTransport(listener, executor);
1559                 } else {
1560                     Preconditions.checkState(transport.isRegistered());
1561                     transport.setExecutor(executor);
1562                 }
1563 
1564                 mService.registerLocationListener(provider, locationRequest, transport,
1565                         mContext.getPackageName(), mContext.getAttributionTag(),
1566                         AppOpsManager.toReceiverId(listener));
1567 
1568                 sLocationListeners.put(listener, new WeakReference<>(transport));
1569             }
1570         } catch (RemoteException e) {
1571             throw e.rethrowFromSystemServer();
1572         }
1573     }
1574 
1575     /**
1576      * Register for location updates from the specified provider, using a {@link LocationRequest},
1577      * and callbacks delivered via the provided {@link PendingIntent}.
1578      *
1579      * <p>The delivered pending intents will contain extras with the callback information. The keys
1580      * used for the extras are {@link #KEY_LOCATION_CHANGED} and {@link #KEY_PROVIDER_ENABLED}. See
1581      * the documentation for each respective extra key for information on the values.
1582      *
1583      * <p>To unregister for location updates, use {@link #removeUpdates(PendingIntent)}.
1584      *
1585      * @param provider a provider listed by {@link #getAllProviders()}
1586      * @param locationRequest the location request containing location parameters
1587      * @param pendingIntent the pending intent to send location updates
1588      *
1589      * @throws IllegalArgumentException if provider is null or doesn't exist
1590      * @throws IllegalArgumentException if locationRequest is null
1591      * @throws IllegalArgumentException if pendingIntent is null
1592      * @throws SecurityException if no suitable permission is present
1593      */
1594     @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
requestLocationUpdates(@onNull String provider, @NonNull LocationRequest locationRequest, @NonNull PendingIntent pendingIntent)1595     public void requestLocationUpdates(@NonNull String provider,
1596             @NonNull LocationRequest locationRequest,
1597             @NonNull PendingIntent pendingIntent) {
1598         Preconditions.checkArgument(provider != null, "invalid null provider");
1599         Preconditions.checkArgument(locationRequest != null, "invalid null location request");
1600         Preconditions.checkArgument(pendingIntent != null, "invalid null pending intent");
1601 
1602         if (Compatibility.isChangeEnabled(BLOCK_UNTARGETED_PENDING_INTENTS)) {
1603             Preconditions.checkArgument(pendingIntent.isTargetedToPackage(),
1604                     "pending intent must be targeted to a package");
1605         }
1606 
1607         if (Compatibility.isChangeEnabled(BLOCK_IMMUTABLE_PENDING_INTENTS)) {
1608             Preconditions.checkArgument(!pendingIntent.isImmutable(),
1609                     "pending intent must be mutable");
1610         }
1611 
1612         try {
1613             mService.registerLocationPendingIntent(provider, locationRequest, pendingIntent,
1614                     mContext.getPackageName(), mContext.getAttributionTag());
1615         } catch (RemoteException e) {
1616             throw e.rethrowFromSystemServer();
1617         }
1618     }
1619 
1620     /**
1621      * Set the last known location with a new location.
1622      *
1623      * <p>A privileged client can inject a {@link Location} if it has a better estimate of what
1624      * the recent location is.  This is especially useful when the device boots up and the GPS
1625      * chipset is in the process of getting the first fix.  If the client has cached the location,
1626      * it can inject the {@link Location}, so if an app requests for a {@link Location} from {@link
1627      * #getLastKnownLocation(String)}, the location information is still useful before getting
1628      * the first fix.
1629      *
1630      * @param location newly available {@link Location} object
1631      * @return true if the location was injected, false otherwise
1632      *
1633      * @throws IllegalArgumentException if location is null
1634      * @throws SecurityException if permissions are not present
1635      *
1636      * @hide
1637      */
1638     @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
1639     @RequiresPermission(allOf = {LOCATION_HARDWARE, ACCESS_FINE_LOCATION})
injectLocation(@onNull Location location)1640     public boolean injectLocation(@NonNull Location location) {
1641         Preconditions.checkArgument(location != null, "invalid null location");
1642         Preconditions.checkArgument(location.isComplete(),
1643                 "incomplete location object, missing timestamp or accuracy?");
1644 
1645         try {
1646             mService.injectLocation(location);
1647             return true;
1648         } catch (RemoteException e) {
1649             throw e.rethrowFromSystemServer();
1650         }
1651     }
1652 
1653     /**
1654      * Requests that the given provider flush any batched locations to listeners. The given listener
1655      * (registered with the provider) will have {@link LocationListener#onFlushComplete(int)}
1656      * invoked with the given result code after any locations that were flushed have been delivered.
1657      * If {@link #removeUpdates(LocationListener)} is invoked before the flush callback is executed,
1658      * then the flush callback will never be executed.
1659      *
1660      * @param provider    a provider listed by {@link #getAllProviders()}
1661      * @param listener    a listener registered under the provider
1662      * @param requestCode an arbitrary integer passed through to
1663      *                    {@link LocationListener#onFlushComplete(int)}
1664      *
1665      * @throws IllegalArgumentException if provider is null or doesn't exist
1666      * @throws IllegalArgumentException if listener is null or is not registered under the provider
1667      */
1668     @SuppressLint("SamShouldBeLast")
requestFlush(@onNull String provider, @NonNull LocationListener listener, @SuppressLint("ListenerLast") int requestCode)1669     public void requestFlush(@NonNull String provider, @NonNull LocationListener listener,
1670             @SuppressLint("ListenerLast") int requestCode) {
1671         Preconditions.checkArgument(provider != null, "invalid null provider");
1672         Preconditions.checkArgument(listener != null, "invalid null listener");
1673 
1674         synchronized (sLocationListeners) {
1675             WeakReference<LocationListenerTransport> ref = sLocationListeners.get(listener);
1676             LocationListenerTransport transport = ref != null ? ref.get() : null;
1677 
1678             Preconditions.checkArgument(transport != null,
1679                     "unregistered listener cannot be flushed");
1680 
1681             try {
1682                 mService.requestListenerFlush(provider, transport, requestCode);
1683             } catch (RemoteException e) {
1684                 throw e.rethrowFromSystemServer();
1685             }
1686         }
1687     }
1688 
1689     /**
1690      * Requests that the given provider flush any batched locations to listeners. The given
1691      * PendingIntent (registered with the provider) will be sent with {@link #KEY_FLUSH_COMPLETE}
1692      * present in the extra keys, and {@code requestCode} as the corresponding value.
1693      *
1694      * @param provider      a provider listed by {@link #getAllProviders()}
1695      * @param pendingIntent a pendingIntent registered under the provider
1696      * @param requestCode   an arbitrary integer that will be passed back as the extra value for
1697      *                      {@link #KEY_FLUSH_COMPLETE}
1698      *
1699      * @throws IllegalArgumentException if provider is null or doesn't exist
1700      * @throws IllegalArgumentException if pending intent is null or is not registered under the
1701      *                                  provider
1702      */
requestFlush(@onNull String provider, @NonNull PendingIntent pendingIntent, int requestCode)1703     public void requestFlush(@NonNull String provider, @NonNull PendingIntent pendingIntent,
1704             int requestCode) {
1705         Preconditions.checkArgument(provider != null, "invalid null provider");
1706         Preconditions.checkArgument(pendingIntent != null, "invalid null pending intent");
1707 
1708         try {
1709             mService.requestPendingIntentFlush(provider, pendingIntent, requestCode);
1710         } catch (RemoteException e) {
1711             throw e.rethrowFromSystemServer();
1712         }
1713     }
1714 
1715     /**
1716      * Removes all location updates for the specified {@link LocationListener}. The given listener
1717      * is guaranteed not to receive any invocations that <b>happens-after</b> this method is
1718      * invoked.
1719      *
1720      * <p>If the given listener has any batched requests, this method will not flush any incomplete
1721      * location batches before stopping location updates. If you wish to flush any pending locations
1722      * before stopping, you must first call {@link #requestFlush(String, LocationListener, int)} and
1723      * then call this method once the flush is complete. If this method is invoked before the flush
1724      * is complete, you may not receive the flushed locations.
1725      *
1726      * @param listener listener that no longer needs location updates
1727      *
1728      * @throws IllegalArgumentException if listener is null
1729      */
removeUpdates(@onNull LocationListener listener)1730     public void removeUpdates(@NonNull LocationListener listener) {
1731         Preconditions.checkArgument(listener != null, "invalid null listener");
1732 
1733         try {
1734             synchronized (sLocationListeners) {
1735                 WeakReference<LocationListenerTransport> ref = sLocationListeners.remove(listener);
1736                 LocationListenerTransport transport = ref != null ? ref.get() : null;
1737                 if (transport != null) {
1738                     transport.unregister();
1739                     mService.unregisterLocationListener(transport);
1740                 }
1741             }
1742         } catch (RemoteException e) {
1743             throw e.rethrowFromSystemServer();
1744         }
1745     }
1746 
1747     /**
1748      * Removes location updates for the specified {@link PendingIntent}. Following this call, the
1749      * PendingIntent will no longer receive location updates.
1750      *
1751      * <p>See {@link #removeUpdates(LocationListener)} for more detail on how this method works.
1752      *
1753      * @param pendingIntent pending intent that no longer needs location updates
1754      *
1755      * @throws IllegalArgumentException if pendingIntent is null
1756      */
removeUpdates(@onNull PendingIntent pendingIntent)1757     public void removeUpdates(@NonNull PendingIntent pendingIntent) {
1758         Preconditions.checkArgument(pendingIntent != null, "invalid null pending intent");
1759 
1760         try {
1761             mService.unregisterLocationPendingIntent(pendingIntent);
1762         } catch (RemoteException e) {
1763             throw e.rethrowFromSystemServer();
1764         }
1765     }
1766 
1767     /**
1768      * Returns true if the given location provider exists on this device, irrespective of whether
1769      * it is currently enabled or not.
1770      *
1771      * @param provider a potential location provider
1772      * @return true if the location provider exists, false otherwise
1773      *
1774      * @throws IllegalArgumentException if provider is null
1775      */
hasProvider(@onNull String provider)1776     public boolean hasProvider(@NonNull String provider) {
1777         Preconditions.checkArgument(provider != null, "invalid null provider");
1778 
1779         try {
1780             return mService.hasProvider(provider);
1781         } catch (RemoteException e) {
1782             throw e.rethrowFromSystemServer();
1783         }
1784     }
1785 
1786     /**
1787      * Returns a list of the names of all available location providers. All providers are returned,
1788      * including those that are currently disabled.
1789      *
1790      * @return list of provider names
1791      */
getAllProviders()1792     public @NonNull List<String> getAllProviders() {
1793         try {
1794             return mService.getAllProviders();
1795         } catch (RemoteException e) {
1796             throw e.rethrowFromSystemServer();
1797         }
1798     }
1799 
1800     /**
1801      * Returns a list of the names of available location providers. If {@code enabledOnly} is false,
1802      * this is functionally the same as {@link #getAllProviders()}.
1803      *
1804      * @param enabledOnly if true then only enabled providers are included
1805      * @return list of provider names
1806      */
getProviders(boolean enabledOnly)1807     public @NonNull List<String> getProviders(boolean enabledOnly) {
1808         try {
1809             return mService.getProviders(null, enabledOnly);
1810         } catch (RemoteException e) {
1811             throw e.rethrowFromSystemServer();
1812         }
1813     }
1814 
1815     /**
1816      * Returns a list of the names of available location providers that satisfy the given criteria.
1817      *
1818      * @param criteria the criteria that providers must match
1819      * @param enabledOnly if true then only enabled providers are included
1820      * @return list of provider names
1821      *
1822      * @throws IllegalArgumentException if criteria is null
1823      */
getProviders(@onNull Criteria criteria, boolean enabledOnly)1824     public @NonNull List<String> getProviders(@NonNull Criteria criteria, boolean enabledOnly) {
1825         Preconditions.checkArgument(criteria != null, "invalid null criteria");
1826 
1827         try {
1828             return mService.getProviders(criteria, enabledOnly);
1829         } catch (RemoteException e) {
1830             throw e.rethrowFromSystemServer();
1831         }
1832     }
1833 
1834     /**
1835      * Returns the name of the provider that best meets the given criteria. Only providers that are
1836      * permitted to be accessed by the caller will be returned. If several providers meet the
1837      * criteria, the one with the best accuracy is returned. If no provider meets the criteria, the
1838      * criteria are loosened in the following order:
1839      *
1840      * <ul>
1841      * <li> power requirement
1842      * <li> accuracy
1843      * <li> bearing
1844      * <li> speed
1845      * <li> altitude
1846      * </ul>
1847      *
1848      * <p> Note that the requirement on monetary cost is not removed in this process.
1849      *
1850      * @param criteria the criteria that need to be matched
1851      * @param enabledOnly if true then only enabled providers are included
1852      * @return name of the provider that best matches the criteria, or null if none match
1853      *
1854      * @throws IllegalArgumentException if criteria is null
1855      */
getBestProvider(@onNull Criteria criteria, boolean enabledOnly)1856     public @Nullable String getBestProvider(@NonNull Criteria criteria, boolean enabledOnly) {
1857         Preconditions.checkArgument(criteria != null, "invalid null criteria");
1858 
1859         try {
1860             return mService.getBestProvider(criteria, enabledOnly);
1861         } catch (RemoteException e) {
1862             throw e.rethrowFromSystemServer();
1863         }
1864     }
1865 
1866     /**
1867      * Returns the information about the location provider with the given name, or null if no
1868      * provider exists by that name.
1869      *
1870      * @param provider a provider listed by {@link #getAllProviders()}
1871      * @return location provider information, or null if provider does not exist
1872      *
1873      * @throws IllegalArgumentException if provider is null
1874      *
1875      * @deprecated This method has no way to indicate that a provider's properties are unknown, and
1876      * so may return incorrect results on rare occasions. Use {@link #getProviderProperties(String)}
1877      * instead.
1878      */
1879     @Deprecated
getProvider(@onNull String provider)1880     public @Nullable LocationProvider getProvider(@NonNull String provider) {
1881         Preconditions.checkArgument(provider != null, "invalid null provider");
1882 
1883         if (!Compatibility.isChangeEnabled(GET_PROVIDER_SECURITY_EXCEPTIONS)) {
1884             if (NETWORK_PROVIDER.equals(provider) || FUSED_PROVIDER.equals(provider)) {
1885                 try {
1886                     mContext.enforcePermission(ACCESS_FINE_LOCATION, Process.myPid(),
1887                             Process.myUid(), null);
1888                 } catch (SecurityException e) {
1889                     mContext.enforcePermission(ACCESS_COARSE_LOCATION, Process.myPid(),
1890                             Process.myUid(), null);
1891                 }
1892             } else {
1893                 mContext.enforcePermission(ACCESS_FINE_LOCATION, Process.myPid(), Process.myUid(),
1894                         null);
1895             }
1896         }
1897 
1898         try {
1899             ProviderProperties properties = mService.getProviderProperties(provider);
1900             return new LocationProvider(provider, properties);
1901         } catch (IllegalArgumentException e) {
1902             // provider does not exist
1903             return null;
1904         } catch (RemoteException e) {
1905             throw e.rethrowFromSystemServer();
1906         }
1907     }
1908 
1909     /**
1910      * Returns the properties of the given provider, or null if the properties are currently
1911      * unknown. Provider properties may change over time, although this is discouraged, and should
1912      * be rare. The most common transition is when provider properties go from being unknown to
1913      * known, which is most common near boot time.
1914      *
1915      * @param provider a provider listed by {@link #getAllProviders()}
1916      * @return location provider properties, or null if properties are currently unknown
1917      *
1918      * @throws IllegalArgumentException if provider is null or does not exist
1919      */
getProviderProperties(@onNull String provider)1920     public @Nullable ProviderProperties getProviderProperties(@NonNull String provider) {
1921         Preconditions.checkArgument(provider != null, "invalid null provider");
1922 
1923         try {
1924             return mService.getProviderProperties(provider);
1925         } catch (RemoteException e) {
1926             throw e.rethrowFromSystemServer();
1927         }
1928     }
1929 
1930     /**
1931      * Returns true if the given package name matches a location provider package, and false
1932      * otherwise.
1933      *
1934      * @hide
1935      * @deprecated Prefer {@link #isProviderPackage(String, String, String)} instead.
1936      */
1937     @Deprecated
1938     @SystemApi
1939     @RequiresPermission(Manifest.permission.READ_DEVICE_CONFIG)
isProviderPackage(@onNull String packageName)1940     public boolean isProviderPackage(@NonNull String packageName) {
1941         return isProviderPackage(null, packageName, null);
1942     }
1943 
1944     /**
1945      * Returns true if the given provider corresponds to the given package name. If the given
1946      * provider is null, this will return true if any provider corresponds to the given package
1947      * name.
1948      *
1949      * @param provider a provider listed by {@link #getAllProviders()} or null
1950      * @param packageName the package name to test if it is a provider
1951      * @return true if the given arguments correspond to a provider
1952      *
1953      * @deprecated Use {@link #isProviderPackage(String, String, String)} instead.
1954      *
1955      * @hide
1956      * @removed
1957      */
1958     @Deprecated
1959     @SystemApi
1960     @RequiresPermission(Manifest.permission.READ_DEVICE_CONFIG)
isProviderPackage(@ullable String provider, @NonNull String packageName)1961     public boolean isProviderPackage(@Nullable String provider, @NonNull String packageName) {
1962         return isProviderPackage(provider, packageName, null);
1963     }
1964 
1965     /**
1966      * Returns true if the given provider corresponds to the given package name. If the given
1967      * provider is null, this will return true if any provider corresponds to the given package
1968      * name and/or attribution tag. If attribution tag is non-null, the provider identity must match
1969      * both the given package name and attribution tag.
1970      *
1971      * @param provider a provider listed by {@link #getAllProviders()} or null
1972      * @param packageName the package name to test if it is a provider
1973      * @param attributionTag an optional attribution tag within the given package
1974      * @return true if the given arguments correspond to a provider
1975      * @hide
1976      */
1977     @SystemApi
1978     @RequiresPermission(Manifest.permission.READ_DEVICE_CONFIG)
isProviderPackage(@ullable String provider, @NonNull String packageName, @Nullable String attributionTag)1979     public boolean isProviderPackage(@Nullable String provider, @NonNull String packageName,
1980             @Nullable String attributionTag) {
1981         try {
1982             return mService.isProviderPackage(provider, Objects.requireNonNull(packageName),
1983                     attributionTag);
1984         } catch (RemoteException e) {
1985             throw e.rethrowFromSystemServer();
1986         }
1987     }
1988 
1989     /**
1990      * Returns a list of packages associated with the given provider,
1991      * and an empty list if no package is associated with the provider.
1992      *
1993      * @hide
1994      * @deprecated Prefer {@link #isProviderPackage(String, String, String)} instead.
1995      */
1996     @TestApi
1997     @Deprecated
1998     @RequiresPermission(Manifest.permission.READ_DEVICE_CONFIG)
1999     @Nullable
2000     @SuppressWarnings("NullableCollection")
getProviderPackages(@onNull String provider)2001     public List<String> getProviderPackages(@NonNull String provider) {
2002         try {
2003             return mService.getProviderPackages(provider);
2004         } catch (RemoteException e) {
2005             throw e.rethrowFromSystemServer();
2006         }
2007     }
2008 
2009     /**
2010      * Sends additional commands to a location provider. Can be used to support provider specific
2011      * extensions to the Location Manager API.
2012      *
2013      * @param provider a provider listed by {@link #getAllProviders()}
2014      * @param command  name of the command to send to the provider
2015      * @param extras   optional arguments for the command, or null
2016      * @return true always, the return value may be ignored
2017      */
sendExtraCommand( @onNull String provider, @NonNull String command, @Nullable Bundle extras)2018     public boolean sendExtraCommand(
2019             @NonNull String provider, @NonNull String command, @Nullable Bundle extras) {
2020         Preconditions.checkArgument(provider != null, "invalid null provider");
2021         Preconditions.checkArgument(command != null, "invalid null command");
2022 
2023         try {
2024             mService.sendExtraCommand(provider, command, extras);
2025             return true;
2026         } catch (RemoteException e) {
2027             throw e.rethrowFromSystemServer();
2028         }
2029     }
2030 
2031     /**
2032      * Creates a test location provider and adds it to the set of active providers. This provider
2033      * will replace any provider with the same name that exists prior to this call.
2034      *
2035      * @param provider the provider name
2036      *
2037      * @throws IllegalArgumentException if provider is null
2038      * @throws SecurityException if {@link android.app.AppOpsManager#OPSTR_MOCK_LOCATION
2039      * mock location app op} is not set to {@link android.app.AppOpsManager#MODE_ALLOWED
2040      * allowed} for your app.
2041      */
addTestProvider( @onNull String provider, boolean requiresNetwork, boolean requiresSatellite, boolean requiresCell, boolean hasMonetaryCost, boolean supportsAltitude, boolean supportsSpeed, boolean supportsBearing, @ProviderProperties.PowerUsage int powerUsage, @ProviderProperties.Accuracy int accuracy)2042     public void addTestProvider(
2043             @NonNull String provider, boolean requiresNetwork, boolean requiresSatellite,
2044             boolean requiresCell, boolean hasMonetaryCost, boolean supportsAltitude,
2045             boolean supportsSpeed, boolean supportsBearing,
2046             @ProviderProperties.PowerUsage int powerUsage,
2047             @ProviderProperties.Accuracy int accuracy) {
2048         addTestProvider(provider, new ProviderProperties.Builder()
2049                 .setHasNetworkRequirement(requiresNetwork)
2050                 .setHasSatelliteRequirement(requiresSatellite)
2051                 .setHasCellRequirement(requiresCell)
2052                 .setHasMonetaryCost(hasMonetaryCost)
2053                 .setHasAltitudeSupport(supportsAltitude)
2054                 .setHasSpeedSupport(supportsSpeed)
2055                 .setHasBearingSupport(supportsBearing)
2056                 .setPowerUsage(powerUsage)
2057                 .setAccuracy(accuracy)
2058                 .build());
2059     }
2060 
2061     /**
2062      * Creates a test location provider and adds it to the set of active providers. This provider
2063      * will replace any provider with the same name that exists prior to this call.
2064      *
2065      * @param provider the provider name
2066      *
2067      * @throws IllegalArgumentException if provider is null
2068      * @throws IllegalArgumentException if properties is null
2069      * @throws SecurityException if {@link android.app.AppOpsManager#OPSTR_MOCK_LOCATION
2070      * mock location app op} is not set to {@link android.app.AppOpsManager#MODE_ALLOWED
2071      * allowed} for your app.
2072      */
addTestProvider(@onNull String provider, @NonNull ProviderProperties properties)2073     public void addTestProvider(@NonNull String provider, @NonNull ProviderProperties properties) {
2074         addTestProvider(provider, properties, Collections.emptySet());
2075     }
2076 
2077     /**
2078      * Creates a test location provider and adds it to the set of active providers. This provider
2079      * will replace any provider with the same name that exists prior to this call.
2080      *
2081      * @param provider the provider name
2082      * @param properties the provider properties
2083      * @param extraAttributionTags additional attribution tags associated with this provider
2084      *
2085      * @throws IllegalArgumentException if provider is null
2086      * @throws IllegalArgumentException if properties is null
2087      * @throws SecurityException if {@link android.app.AppOpsManager#OPSTR_MOCK_LOCATION
2088      * mock location app op} is not set to {@link android.app.AppOpsManager#MODE_ALLOWED
2089      * allowed} for your app.
2090      */
addTestProvider(@onNull String provider, @NonNull ProviderProperties properties, @NonNull Set<String> extraAttributionTags)2091     public void addTestProvider(@NonNull String provider, @NonNull ProviderProperties properties,
2092             @NonNull Set<String> extraAttributionTags) {
2093         Preconditions.checkArgument(provider != null, "invalid null provider");
2094         Preconditions.checkArgument(properties != null, "invalid null properties");
2095         Preconditions.checkArgument(extraAttributionTags != null,
2096                 "invalid null extra attribution tags");
2097 
2098         try {
2099             mService.addTestProvider(provider, properties, new ArrayList<>(extraAttributionTags),
2100                     mContext.getOpPackageName(), mContext.getFeatureId());
2101         } catch (RemoteException e) {
2102             throw e.rethrowFromSystemServer();
2103         }
2104     }
2105 
2106     /**
2107      * Removes the test location provider with the given name or does nothing if no such test
2108      * location provider exists.
2109      *
2110      * @param provider the provider name
2111      *
2112      * @throws IllegalArgumentException if provider is null
2113      * @throws SecurityException if {@link android.app.AppOpsManager#OPSTR_MOCK_LOCATION
2114      * mock location app op} is not set to {@link android.app.AppOpsManager#MODE_ALLOWED
2115      * allowed} for your app.
2116      */
removeTestProvider(@onNull String provider)2117     public void removeTestProvider(@NonNull String provider) {
2118         Preconditions.checkArgument(provider != null, "invalid null provider");
2119 
2120         try {
2121             mService.removeTestProvider(provider, mContext.getOpPackageName(),
2122                     mContext.getFeatureId());
2123         } catch (RemoteException e) {
2124             throw e.rethrowFromSystemServer();
2125         }
2126     }
2127 
2128     /**
2129      * Sets a new location for the given test provider. This location will be identiable as a mock
2130      * location to all clients via {@link Location#isMock()}.
2131      *
2132      * <p>The location object must have a minimum number of fields set to be considered valid, as
2133      * per documentation on {@link Location} class.
2134      *
2135      * @param provider the provider name
2136      * @param location the mock location
2137      *
2138      * @throws SecurityException if {@link android.app.AppOpsManager#OPSTR_MOCK_LOCATION
2139      * mock location app op} is not set to {@link android.app.AppOpsManager#MODE_ALLOWED
2140      * allowed} for your app.
2141      * @throws IllegalArgumentException if the provider is null or not a test provider
2142      * @throws IllegalArgumentException if the location is null or incomplete
2143      */
setTestProviderLocation(@onNull String provider, @NonNull Location location)2144     public void setTestProviderLocation(@NonNull String provider, @NonNull Location location) {
2145         Preconditions.checkArgument(provider != null, "invalid null provider");
2146         Preconditions.checkArgument(location != null, "invalid null location");
2147 
2148         if (Compatibility.isChangeEnabled(BLOCK_INCOMPLETE_LOCATIONS)) {
2149             Preconditions.checkArgument(location.isComplete(),
2150                     "incomplete location object, missing timestamp or accuracy?");
2151         } else {
2152             location.makeComplete();
2153         }
2154 
2155         try {
2156             mService.setTestProviderLocation(provider, location, mContext.getOpPackageName(),
2157                     mContext.getFeatureId());
2158         } catch (RemoteException e) {
2159             throw e.rethrowFromSystemServer();
2160         }
2161     }
2162 
2163     /**
2164      * Does nothing.
2165      *
2166      * @deprecated This method has always been a no-op, and may be removed in the future.
2167      */
2168     @Deprecated
clearTestProviderLocation(@onNull String provider)2169     public void clearTestProviderLocation(@NonNull String provider) {}
2170 
2171     /**
2172      * Sets the given test provider to be enabled or disabled.
2173      *
2174      * @param provider the provider name
2175      * @param enabled the mock enabled value
2176      *
2177      * @throws SecurityException if {@link android.app.AppOpsManager#OPSTR_MOCK_LOCATION
2178      * mock location app op} is not set to {@link android.app.AppOpsManager#MODE_ALLOWED
2179      * allowed} for your app.
2180      * @throws IllegalArgumentException if provider is null or not a test provider
2181      */
setTestProviderEnabled(@onNull String provider, boolean enabled)2182     public void setTestProviderEnabled(@NonNull String provider, boolean enabled) {
2183         Preconditions.checkArgument(provider != null, "invalid null provider");
2184 
2185         try {
2186             mService.setTestProviderEnabled(provider, enabled, mContext.getOpPackageName(),
2187                     mContext.getFeatureId());
2188         } catch (RemoteException e) {
2189             throw e.rethrowFromSystemServer();
2190         }
2191     }
2192 
2193     /**
2194      * Equivalent to calling {@link #setTestProviderEnabled(String, boolean)} to disable a test
2195      * provider.
2196      *
2197      * @deprecated Use {@link #setTestProviderEnabled(String, boolean)} instead.
2198      */
2199     @Deprecated
clearTestProviderEnabled(@onNull String provider)2200     public void clearTestProviderEnabled(@NonNull String provider) {
2201         setTestProviderEnabled(provider, false);
2202     }
2203 
2204     /**
2205      * This method has no effect as provider status has been deprecated and is no longer supported.
2206      *
2207      * @deprecated This method has no effect.
2208      */
2209     @Deprecated
setTestProviderStatus( @onNull String provider, int status, @Nullable Bundle extras, long updateTime)2210     public void setTestProviderStatus(
2211             @NonNull String provider, int status, @Nullable Bundle extras, long updateTime) {}
2212 
2213     /**
2214      * This method has no effect as provider status has been deprecated and is no longer supported.
2215      *
2216      * @deprecated This method has no effect.
2217      */
2218     @Deprecated
clearTestProviderStatus(@onNull String provider)2219     public void clearTestProviderStatus(@NonNull String provider) {}
2220 
2221     /**
2222      * Sets a proximity alert for the location given by the position (latitude, longitude) and the
2223      * given radius.
2224      *
2225      * <p>When the device detects that it has entered or exited the area surrounding the location,
2226      * the given PendingIntent will be fired.
2227      *
2228      * <p>The fired intent will have a boolean extra added with key {@link #KEY_PROXIMITY_ENTERING}.
2229      * If the value is true, the device is entering the proximity region; if false, it is exiting.
2230      *
2231      * <p>Due to the approximate nature of position estimation, if the device passes through the
2232      * given area briefly, it is possible that no Intent will be fired. Similarly, an intent could
2233      * be fired if the device passes very close to the given area but does not actually enter it.
2234      *
2235      * <p>Before API version 17, this method could be used with
2236      * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} or
2237      * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}. From API version 17 and onwards,
2238      * this method requires {@link android.Manifest.permission#ACCESS_FINE_LOCATION} permission.
2239      *
2240      * @param latitude      the latitude of the central point of the alert region
2241      * @param longitude     the longitude of the central point of the alert region
2242      * @param radius        the radius of the central point of the alert region in meters
2243      * @param expiration    expiration realtime for this proximity alert in milliseconds, or -1 to
2244      *                      indicate no expiration
2245      * @param pendingIntent a {@link PendingIntent} that will sent when entry to or exit from the
2246      *                      alert region is detected
2247      * @throws SecurityException if {@link android.Manifest.permission#ACCESS_FINE_LOCATION}
2248      *                           permission is not present
2249      */
2250     @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
addProximityAlert(double latitude, double longitude, float radius, long expiration, @NonNull PendingIntent pendingIntent)2251     public void addProximityAlert(double latitude, double longitude, float radius, long expiration,
2252             @NonNull PendingIntent pendingIntent) {
2253         Preconditions.checkArgument(pendingIntent != null, "invalid null pending intent");
2254 
2255         if (Compatibility.isChangeEnabled(BLOCK_UNTARGETED_PENDING_INTENTS)) {
2256             Preconditions.checkArgument(pendingIntent.isTargetedToPackage(),
2257                     "pending intent must be targeted to a package");
2258         }
2259 
2260         if (Compatibility.isChangeEnabled(BLOCK_IMMUTABLE_PENDING_INTENTS)) {
2261             Preconditions.checkArgument(!pendingIntent.isImmutable(),
2262                     "pending intent must be mutable");
2263         }
2264 
2265         if (expiration < 0) {
2266             expiration = Long.MAX_VALUE;
2267         }
2268 
2269         try {
2270             Geofence fence = Geofence.createCircle(latitude, longitude, radius, expiration);
2271             mService.requestGeofence(fence, pendingIntent, mContext.getPackageName(),
2272                     mContext.getAttributionTag());
2273         } catch (RemoteException e) {
2274             throw e.rethrowFromSystemServer();
2275         }
2276     }
2277 
2278     /**
2279      * Removes the proximity alert with the given PendingIntent.
2280      *
2281      * <p>Before API version 17, this method could be used with
2282      * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} or
2283      * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}.
2284      * From API version 17 and onwards, this method requires
2285      * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} permission.
2286      *
2287      * @param intent the PendingIntent that no longer needs to be notified of
2288      * proximity alerts
2289      *
2290      * @throws IllegalArgumentException if intent is null
2291      * @throws SecurityException if {@link android.Manifest.permission#ACCESS_FINE_LOCATION}
2292      * permission is not present
2293      */
removeProximityAlert(@onNull PendingIntent intent)2294     public void removeProximityAlert(@NonNull PendingIntent intent) {
2295         Preconditions.checkArgument(intent != null, "invalid null pending intent");
2296 
2297         try {
2298             mService.removeGeofence(intent);
2299         } catch (RemoteException e) {
2300             throw e.rethrowFromSystemServer();
2301         }
2302     }
2303 
2304     // ================= GNSS APIs =================
2305 
2306     /**
2307      * Returns the supported capabilities of the GNSS chipset.
2308      */
getGnssCapabilities()2309     public @NonNull GnssCapabilities getGnssCapabilities() {
2310         try {
2311             return mService.getGnssCapabilities();
2312         } catch (RemoteException e) {
2313             throw e.rethrowFromSystemServer();
2314         }
2315     }
2316 
2317     /**
2318      * Returns the model year of the GNSS hardware and software build, or 0 if the model year
2319      * is before 2016.
2320      */
getGnssYearOfHardware()2321     public int getGnssYearOfHardware() {
2322         try {
2323             return mService.getGnssYearOfHardware();
2324         } catch (RemoteException e) {
2325             throw e.rethrowFromSystemServer();
2326         }
2327     }
2328 
2329     /**
2330      * Returns the model name (including vendor and hardware/software version) of the GNSS hardware
2331      * driver, or null if this information is not available.
2332      *
2333      * <p>No device-specific serial number or ID is returned from this API.
2334      */
2335     @Nullable
getGnssHardwareModelName()2336     public String getGnssHardwareModelName() {
2337         try {
2338             return mService.getGnssHardwareModelName();
2339         } catch (RemoteException e) {
2340             throw e.rethrowFromSystemServer();
2341         }
2342     }
2343 
2344     /**
2345      * Returns the current list of GNSS antenna infos, or null if unknown or unsupported.
2346      *
2347      * @see #getGnssCapabilities()
2348      */
2349     @Nullable
2350     @SuppressLint("NullableCollection")
getGnssAntennaInfos()2351     public List<GnssAntennaInfo> getGnssAntennaInfos() {
2352         try {
2353             return mService.getGnssAntennaInfos();
2354         } catch (RemoteException e) {
2355             throw e.rethrowFromSystemServer();
2356         }
2357     }
2358 
2359     /**
2360      * Retrieves information about the current status of the GPS engine. This should only be called
2361      * from within the {@link GpsStatus.Listener#onGpsStatusChanged} callback to ensure that the
2362      * data is copied atomically.
2363      *
2364      * The caller may either pass in an existing {@link GpsStatus} object to be overwritten, or pass
2365      * null to create a new {@link GpsStatus} object.
2366      *
2367      * @param status object containing GPS status details, or null.
2368      * @return status object containing updated GPS status.
2369      *
2370      * @deprecated GpsStatus APIs are deprecated, use {@link GnssStatus} APIs instead. No longer
2371      * supported in apps targeting S and above.
2372      */
2373     @Deprecated
2374     @RequiresPermission(ACCESS_FINE_LOCATION)
getGpsStatus(@ullable GpsStatus status)2375     public @Nullable GpsStatus getGpsStatus(@Nullable GpsStatus status) {
2376         if (Compatibility.isChangeEnabled(BLOCK_GPS_STATUS_USAGE)) {
2377             throw new UnsupportedOperationException(
2378                     "GpsStatus APIs not supported, please use GnssStatus APIs instead");
2379         }
2380 
2381         GnssStatus gnssStatus = GpsStatusTransport.sGnssStatus;
2382         int ttff = GpsStatusTransport.sTtff;
2383         if (gnssStatus != null) {
2384             if (status == null) {
2385                 status = GpsStatus.create(gnssStatus, ttff);
2386             } else {
2387                 status.setStatus(gnssStatus, ttff);
2388             }
2389         } else if (status == null) {
2390             // even though this method is marked as nullable, legacy behavior was to never return
2391             // a null result, and there are applications that rely on this behavior.
2392             status = GpsStatus.createEmpty();
2393         }
2394         return status;
2395     }
2396 
2397     /**
2398      * Adds a GPS status listener.
2399      *
2400      * @param listener GPS status listener object to register
2401      * @return true if the listener was successfully added
2402      * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
2403      *
2404      * @deprecated use {@link #registerGnssStatusCallback(GnssStatus.Callback)} instead. No longer
2405      * supported in apps targeting S and above.
2406      */
2407     @Deprecated
2408     @RequiresPermission(ACCESS_FINE_LOCATION)
addGpsStatusListener(GpsStatus.Listener listener)2409     public boolean addGpsStatusListener(GpsStatus.Listener listener) {
2410         if (Compatibility.isChangeEnabled(BLOCK_GPS_STATUS_USAGE)) {
2411             throw new UnsupportedOperationException(
2412                     "GpsStatus APIs not supported, please use GnssStatus APIs instead");
2413         }
2414 
2415         GnssLazyLoader.sGnssStatusListeners.addListener(listener,
2416                 new GpsStatusTransport(new HandlerExecutor(new Handler()), mContext, listener));
2417         return true;
2418     }
2419 
2420     /**
2421      * Removes a GPS status listener.
2422      *
2423      * @param listener GPS status listener object to remove
2424      *
2425      * @deprecated use {@link #unregisterGnssStatusCallback(GnssStatus.Callback)} instead. No longer
2426      * supported in apps targeting S and above.
2427      */
2428     @Deprecated
removeGpsStatusListener(GpsStatus.Listener listener)2429     public void removeGpsStatusListener(GpsStatus.Listener listener) {
2430         if (Compatibility.isChangeEnabled(BLOCK_GPS_STATUS_USAGE)) {
2431             throw new UnsupportedOperationException(
2432                     "GpsStatus APIs not supported, please use GnssStatus APIs instead");
2433         }
2434 
2435         GnssLazyLoader.sGnssStatusListeners.removeListener(listener);
2436     }
2437 
2438     /**
2439      * Registers a GNSS status callback. This method must be called from a {@link Looper} thread,
2440      * and callbacks will occur on that looper.
2441      *
2442      * <p>See {@link #registerGnssStatusCallback(Executor, GnssStatus.Callback)} for more detail on
2443      * how this method works.
2444      *
2445      * @param callback the callback to register
2446      * @return {@code true} always
2447      *
2448      * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
2449      *
2450      * @deprecated Use {@link #registerGnssStatusCallback(GnssStatus.Callback, Handler)} or {@link
2451      * #registerGnssStatusCallback(Executor, GnssStatus.Callback)} instead.
2452      */
2453     @Deprecated
2454     @RequiresPermission(ACCESS_FINE_LOCATION)
registerGnssStatusCallback(@onNull GnssStatus.Callback callback)2455     public boolean registerGnssStatusCallback(@NonNull GnssStatus.Callback callback) {
2456         return registerGnssStatusCallback(callback, null);
2457     }
2458 
2459     /**
2460      * Registers a GNSS status callback.
2461      *
2462      * <p>See {@link #registerGnssStatusCallback(Executor, GnssStatus.Callback)} for more detail on
2463      * how this method works.
2464      *
2465      * @param callback the callback to register
2466      * @param handler  the handler the callback runs on
2467      * @return {@code true} always
2468      *
2469      * @throws IllegalArgumentException if callback is null
2470      * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
2471      */
2472     @RequiresPermission(ACCESS_FINE_LOCATION)
registerGnssStatusCallback( @onNull GnssStatus.Callback callback, @Nullable Handler handler)2473     public boolean registerGnssStatusCallback(
2474             @NonNull GnssStatus.Callback callback, @Nullable Handler handler) {
2475         if (handler == null) {
2476             handler = new Handler();
2477         }
2478 
2479         return registerGnssStatusCallback(new HandlerExecutor(handler), callback);
2480     }
2481 
2482     /**
2483      * Registers a GNSS status callback. GNSS status information will only be received while the
2484      * {@link #GPS_PROVIDER} is enabled, and while the client app is in the foreground.
2485      *
2486      * @param executor the executor that the callback runs on
2487      * @param callback the callback to register
2488      * @return {@code true} always
2489      *
2490      * @throws IllegalArgumentException if executor is null
2491      * @throws IllegalArgumentException if callback is null
2492      * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
2493      */
2494     @RequiresPermission(ACCESS_FINE_LOCATION)
registerGnssStatusCallback( @onNull @allbackExecutor Executor executor, @NonNull GnssStatus.Callback callback)2495     public boolean registerGnssStatusCallback(
2496             @NonNull @CallbackExecutor Executor executor,
2497             @NonNull GnssStatus.Callback callback) {
2498         GnssLazyLoader.sGnssStatusListeners.addListener(callback,
2499                 new GnssStatusTransport(executor, mContext, callback));
2500         return true;
2501     }
2502 
2503     /**
2504      * Removes a GNSS status callback.
2505      *
2506      * @param callback GNSS status callback object to remove
2507      */
unregisterGnssStatusCallback(@onNull GnssStatus.Callback callback)2508     public void unregisterGnssStatusCallback(@NonNull GnssStatus.Callback callback) {
2509         GnssLazyLoader.sGnssStatusListeners.removeListener(callback);
2510     }
2511 
2512     /**
2513      * No-op method to keep backward-compatibility.
2514      *
2515      * @deprecated Use {@link #addNmeaListener} instead.
2516      */
2517     @Deprecated
2518     @RequiresPermission(ACCESS_FINE_LOCATION)
addNmeaListener(@onNull GpsStatus.NmeaListener listener)2519     public boolean addNmeaListener(@NonNull GpsStatus.NmeaListener listener) {
2520         return false;
2521     }
2522 
2523     /**
2524      * No-op method to keep backward-compatibility.
2525      *
2526      * @deprecated Use {@link #removeNmeaListener(OnNmeaMessageListener)} instead.
2527      */
2528     @Deprecated
removeNmeaListener(@onNull GpsStatus.NmeaListener listener)2529     public void removeNmeaListener(@NonNull GpsStatus.NmeaListener listener) {}
2530 
2531     /**
2532      * Adds an NMEA listener.
2533      *
2534      * <p>See {@link #addNmeaListener(Executor, OnNmeaMessageListener)} for more detail on how this
2535      * method works.
2536      *
2537      * @param listener the listener to register
2538      * @return {@code true} always
2539      *
2540      * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
2541      * @deprecated Use {@link #addNmeaListener(OnNmeaMessageListener, Handler)} or {@link
2542      * #addNmeaListener(Executor, OnNmeaMessageListener)} instead.
2543      */
2544     @Deprecated
2545     @RequiresPermission(ACCESS_FINE_LOCATION)
addNmeaListener(@onNull OnNmeaMessageListener listener)2546     public boolean addNmeaListener(@NonNull OnNmeaMessageListener listener) {
2547         return addNmeaListener(listener, null);
2548     }
2549 
2550     /**
2551      * Adds an NMEA listener.
2552      *
2553      * <p>See {@link #addNmeaListener(Executor, OnNmeaMessageListener)} for more detail on how this
2554      * method works.
2555      *
2556      * @param listener the listener to register
2557      * @param handler  the handler that the listener runs on
2558      * @return {@code true} always
2559      *
2560      * @throws IllegalArgumentException if listener is null
2561      * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
2562      */
2563     @RequiresPermission(ACCESS_FINE_LOCATION)
addNmeaListener( @onNull OnNmeaMessageListener listener, @Nullable Handler handler)2564     public boolean addNmeaListener(
2565             @NonNull OnNmeaMessageListener listener, @Nullable Handler handler) {
2566         if (handler == null) {
2567             handler = new Handler();
2568         }
2569 
2570         return addNmeaListener(new HandlerExecutor(handler), listener);
2571     }
2572 
2573     /**
2574      * Adds an NMEA listener. GNSS NMEA information will only be received while the
2575      * {@link #GPS_PROVIDER} is enabled, and while the client app is in the foreground.
2576      *
2577      * @param listener the listener to register
2578      * @param executor the executor that the listener runs on
2579      * @return {@code true} always
2580      *
2581      * @throws IllegalArgumentException if executor is null
2582      * @throws IllegalArgumentException if listener is null
2583      * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
2584      */
2585     @RequiresPermission(ACCESS_FINE_LOCATION)
addNmeaListener( @onNull @allbackExecutor Executor executor, @NonNull OnNmeaMessageListener listener)2586     public boolean addNmeaListener(
2587             @NonNull @CallbackExecutor Executor executor,
2588             @NonNull OnNmeaMessageListener listener) {
2589         GnssLazyLoader.sGnssNmeaListeners.addListener(listener,
2590                 new GnssNmeaTransport(executor, mContext, listener));
2591         return true;
2592     }
2593 
2594     /**
2595      * Removes an NMEA listener.
2596      *
2597      * @param listener a {@link OnNmeaMessageListener} object to remove
2598      */
removeNmeaListener(@onNull OnNmeaMessageListener listener)2599     public void removeNmeaListener(@NonNull OnNmeaMessageListener listener) {
2600         GnssLazyLoader.sGnssNmeaListeners.removeListener(listener);
2601     }
2602 
2603     /**
2604      * No-op method to keep backward-compatibility.
2605      *
2606      * @hide
2607      * @deprecated Use {@link #registerGnssMeasurementsCallback} instead.
2608      * @removed
2609      */
2610     @Deprecated
2611     @SystemApi
addGpsMeasurementListener(GpsMeasurementsEvent.Listener listener)2612     public boolean addGpsMeasurementListener(GpsMeasurementsEvent.Listener listener) {
2613         return false;
2614     }
2615 
2616     /**
2617      * No-op method to keep backward-compatibility.
2618      *
2619      * @hide
2620      * @deprecated Use {@link #unregisterGnssMeasurementsCallback} instead.
2621      * @removed
2622      */
2623     @Deprecated
2624     @SystemApi
removeGpsMeasurementListener(GpsMeasurementsEvent.Listener listener)2625     public void removeGpsMeasurementListener(GpsMeasurementsEvent.Listener listener) {}
2626 
2627     /**
2628      * Registers a GNSS measurements callback which will run on a binder thread.
2629      *
2630      * <p>See {@link #registerGnssMeasurementsCallback(Executor, GnssMeasurementsEvent.Callback)
2631      * for more detail on how this method works.
2632      *
2633      * @param callback a {@link GnssMeasurementsEvent.Callback} object to register
2634      * @return {@code true} always
2635      *
2636      * @deprecated Use {@link
2637      * #registerGnssMeasurementsCallback(GnssMeasurementsEvent.Callback, Handler)} or {@link
2638      * #registerGnssMeasurementsCallback(Executor, GnssMeasurementsEvent.Callback)} instead.
2639      */
2640     @Deprecated
2641     @RequiresPermission(ACCESS_FINE_LOCATION)
registerGnssMeasurementsCallback( @onNull GnssMeasurementsEvent.Callback callback)2642     public boolean registerGnssMeasurementsCallback(
2643             @NonNull GnssMeasurementsEvent.Callback callback) {
2644         return registerGnssMeasurementsCallback(DIRECT_EXECUTOR, callback);
2645     }
2646 
2647     /**
2648      * Registers a GNSS measurements callback.
2649      *
2650      * <p>See {@link #registerGnssMeasurementsCallback(Executor, GnssMeasurementsEvent.Callback)
2651      * for more detail on how this method works.
2652      *
2653      * @param callback a {@link GnssMeasurementsEvent.Callback} object to register
2654      * @param handler  the handler that the callback runs on
2655      * @return {@code true} always
2656      *
2657      * @throws IllegalArgumentException if callback is null
2658      * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
2659      */
2660     @RequiresPermission(ACCESS_FINE_LOCATION)
registerGnssMeasurementsCallback( @onNull GnssMeasurementsEvent.Callback callback, @Nullable Handler handler)2661     public boolean registerGnssMeasurementsCallback(
2662             @NonNull GnssMeasurementsEvent.Callback callback, @Nullable Handler handler) {
2663         if (handler == null) {
2664             handler = new Handler();
2665         }
2666 
2667         return registerGnssMeasurementsCallback(new GnssMeasurementRequest.Builder().build(),
2668                 new HandlerExecutor(handler), callback);
2669     }
2670 
2671     /**
2672      * Registers a GNSS measurements callback. GNSS measurements information will only be received
2673      * while the {@link #GPS_PROVIDER} is enabled, and while the client app is in the foreground.
2674      *
2675      * <p>Not all GNSS chipsets support measurements updates, see {@link #getGnssCapabilities()}.
2676      *
2677      * @param executor the executor that the callback runs on
2678      * @param callback the callback to register
2679      * @return {@code true} always
2680      *
2681      * @throws IllegalArgumentException if executor is null
2682      * @throws IllegalArgumentException if callback is null
2683      * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
2684      */
2685     @RequiresPermission(ACCESS_FINE_LOCATION)
registerGnssMeasurementsCallback( @onNull @allbackExecutor Executor executor, @NonNull GnssMeasurementsEvent.Callback callback)2686     public boolean registerGnssMeasurementsCallback(
2687             @NonNull @CallbackExecutor Executor executor,
2688             @NonNull GnssMeasurementsEvent.Callback callback) {
2689         return registerGnssMeasurementsCallback(new GnssMeasurementRequest.Builder().build(),
2690                 executor, callback);
2691     }
2692 
2693     /**
2694      * Registers a GNSS Measurement callback.
2695      *
2696      * @param request  the gnss measurement request containgin measurement parameters
2697      * @param executor the executor that the callback runs on
2698      * @param callback the callack to register
2699      * @return {@code true} always
2700      *
2701      * @throws IllegalArgumentException if request is null
2702      * @throws IllegalArgumentException if executor is null
2703      * @throws IllegalArgumentException if callback is null
2704      * @throws SecurityException        if the ACCESS_FINE_LOCATION permission is not present
2705      * @hide
2706      * @deprecated Use {@link #registerGnssMeasurementsCallback(GnssMeasurementRequest, Executor,
2707      * GnssMeasurementsEvent.Callback)} instead.
2708      */
2709     @Deprecated
2710     @SystemApi
2711     @RequiresPermission(ACCESS_FINE_LOCATION)
registerGnssMeasurementsCallback( @onNull GnssRequest request, @NonNull @CallbackExecutor Executor executor, @NonNull GnssMeasurementsEvent.Callback callback)2712     public boolean registerGnssMeasurementsCallback(
2713             @NonNull GnssRequest request,
2714             @NonNull @CallbackExecutor Executor executor,
2715             @NonNull GnssMeasurementsEvent.Callback callback) {
2716         return registerGnssMeasurementsCallback(request.toGnssMeasurementRequest(), executor,
2717                 callback);
2718     }
2719 
2720     /**
2721      * Registers a GNSS measurement callback.
2722      *
2723      * @param request  extra parameters to pass to GNSS measurement provider. For example, if {@link
2724      *                 GnssMeasurementRequest#isFullTracking()} is true, GNSS chipset switches off
2725      *                 duty cycling.
2726      * @param executor the executor that the callback runs on
2727      * @param callback a {@link GnssMeasurementsEvent.Callback} object to register.
2728      * @return {@code true} always if the callback was added successfully, {@code false} otherwise.
2729      * @throws IllegalArgumentException if request is null
2730      * @throws IllegalArgumentException if executor is null
2731      * @throws IllegalArgumentException if callback is null
2732      * @throws SecurityException        if the ACCESS_FINE_LOCATION permission is not present
2733      */
2734     @RequiresPermission(ACCESS_FINE_LOCATION)
registerGnssMeasurementsCallback( @onNull GnssMeasurementRequest request, @NonNull @CallbackExecutor Executor executor, @NonNull GnssMeasurementsEvent.Callback callback)2735     public boolean registerGnssMeasurementsCallback(
2736             @NonNull GnssMeasurementRequest request,
2737             @NonNull @CallbackExecutor Executor executor,
2738             @NonNull GnssMeasurementsEvent.Callback callback) {
2739         GnssLazyLoader.sGnssMeasurementsListeners.addListener(callback,
2740                 new GnssMeasurementsTransport(executor, mContext, request, callback));
2741         return true;
2742     }
2743 
2744     /**
2745      * Injects GNSS measurement corrections into the GNSS chipset.
2746      *
2747      * @param measurementCorrections measurement corrections to be injected into the chipset
2748      *
2749      * @throws IllegalArgumentException if measurementCorrections is null
2750      * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
2751      * @hide
2752      */
2753     @SystemApi
2754     @RequiresPermission(ACCESS_FINE_LOCATION)
injectGnssMeasurementCorrections( @onNull GnssMeasurementCorrections measurementCorrections)2755     public void injectGnssMeasurementCorrections(
2756             @NonNull GnssMeasurementCorrections measurementCorrections) {
2757         Preconditions.checkArgument(measurementCorrections != null);
2758         try {
2759             mService.injectGnssMeasurementCorrections(measurementCorrections);
2760         } catch (RemoteException e) {
2761             throw e.rethrowFromSystemServer();
2762         }
2763     }
2764 
2765     /**
2766      * Unregisters a GPS Measurement callback.
2767      *
2768      * @param callback a {@link GnssMeasurementsEvent.Callback} object to remove.
2769      */
unregisterGnssMeasurementsCallback( @onNull GnssMeasurementsEvent.Callback callback)2770     public void unregisterGnssMeasurementsCallback(
2771             @NonNull GnssMeasurementsEvent.Callback callback) {
2772         GnssLazyLoader.sGnssMeasurementsListeners.removeListener(callback);
2773     }
2774 
2775     /**
2776      * Registers a GNSS antenna info listener that will receive all changes to antenna info. Use
2777      * {@link #getGnssAntennaInfos()} to get current antenna info.
2778      *
2779      * <p>Not all GNSS chipsets support antenna info updates, see {@link #getGnssCapabilities()}. If
2780      * unsupported, the listener will never be invoked.
2781      *
2782      * <p>Prior to Android S, this requires the {@link Manifest.permission#ACCESS_FINE_LOCATION}
2783      * permission.
2784      *
2785      * @param executor the executor that the listener runs on
2786      * @param listener the listener to register
2787      * @return {@code true} always
2788      *
2789      * @throws IllegalArgumentException if executor is null
2790      * @throws IllegalArgumentException if listener is null
2791      */
registerAntennaInfoListener( @onNull @allbackExecutor Executor executor, @NonNull GnssAntennaInfo.Listener listener)2792     public boolean registerAntennaInfoListener(
2793             @NonNull @CallbackExecutor Executor executor,
2794             @NonNull GnssAntennaInfo.Listener listener) {
2795         GnssLazyLoader.sGnssAntennaInfoListeners.addListener(listener,
2796                 new GnssAntennaInfoTransport(executor, mContext, listener));
2797         return true;
2798     }
2799 
2800     /**
2801      * Unregisters a GNSS antenna info listener.
2802      *
2803      * @param listener a {@link GnssAntennaInfo.Listener} object to remove
2804      */
unregisterAntennaInfoListener(@onNull GnssAntennaInfo.Listener listener)2805     public void unregisterAntennaInfoListener(@NonNull GnssAntennaInfo.Listener listener) {
2806         GnssLazyLoader.sGnssAntennaInfoListeners.removeListener(listener);
2807     }
2808 
2809     /**
2810      * No-op method to keep backward-compatibility.
2811      *
2812      * @hide
2813      * @deprecated Use {@link #registerGnssNavigationMessageCallback} instead.
2814      * @removed
2815      */
2816     @Deprecated
2817     @SystemApi
addGpsNavigationMessageListener(GpsNavigationMessageEvent.Listener listener)2818     public boolean addGpsNavigationMessageListener(GpsNavigationMessageEvent.Listener listener) {
2819         return false;
2820     }
2821 
2822     /**
2823      * No-op method to keep backward-compatibility.
2824      *
2825      * @hide
2826      * @deprecated Use {@link #unregisterGnssNavigationMessageCallback} instead.
2827      * @removed
2828      */
2829     @Deprecated
2830     @SystemApi
removeGpsNavigationMessageListener(GpsNavigationMessageEvent.Listener listener)2831     public void removeGpsNavigationMessageListener(GpsNavigationMessageEvent.Listener listener) {}
2832 
2833     /**
2834      * Registers a GNSS navigation message callback which will run on a binder thread.
2835      *
2836      * <p>See
2837      * {@link #registerGnssNavigationMessageCallback(Executor, GnssNavigationMessage.Callback)} for
2838      * more detail on how this method works.
2839      *
2840      * @param callback the callback to register
2841      * @return {@code true} always
2842      *
2843      * @deprecated Use {@link
2844      * #registerGnssNavigationMessageCallback(GnssNavigationMessage.Callback, Handler)} or {@link
2845      * #registerGnssNavigationMessageCallback(Executor, GnssNavigationMessage.Callback)} instead.
2846      */
2847     @Deprecated
registerGnssNavigationMessageCallback( @onNull GnssNavigationMessage.Callback callback)2848     public boolean registerGnssNavigationMessageCallback(
2849             @NonNull GnssNavigationMessage.Callback callback) {
2850         return registerGnssNavigationMessageCallback(DIRECT_EXECUTOR, callback);
2851     }
2852 
2853     /**
2854      * Registers a GNSS navigation message callback.
2855      *
2856      * <p>See
2857      * {@link #registerGnssNavigationMessageCallback(Executor, GnssNavigationMessage.Callback)} for
2858      * more detail on how this method works.
2859      *
2860      * @param callback the callback to register
2861      * @param handler  the handler that the callback runs on
2862      * @return {@code true} always
2863      *
2864      * @throws IllegalArgumentException if callback is null
2865      * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
2866      */
2867     @RequiresPermission(ACCESS_FINE_LOCATION)
registerGnssNavigationMessageCallback( @onNull GnssNavigationMessage.Callback callback, @Nullable Handler handler)2868     public boolean registerGnssNavigationMessageCallback(
2869             @NonNull GnssNavigationMessage.Callback callback, @Nullable Handler handler) {
2870         if (handler == null) {
2871             handler = new Handler();
2872         }
2873 
2874         return registerGnssNavigationMessageCallback(new HandlerExecutor(handler), callback);
2875     }
2876 
2877     /**
2878      * Registers a GNSS navigation message callback. GNSS navigation messages will only be received
2879      * while the {@link #GPS_PROVIDER} is enabled, and while the client app is in the foreground.
2880      *
2881      * <p>Not all GNSS chipsets support navigation message updates, see
2882      * {@link #getGnssCapabilities()}.
2883      *
2884      * @param executor the executor that the callback runs on
2885      * @param callback the callback to register
2886      * @return {@code true} always
2887      *
2888      * @throws IllegalArgumentException if executor is null
2889      * @throws IllegalArgumentException if callback is null
2890      * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
2891      */
2892     @RequiresPermission(ACCESS_FINE_LOCATION)
registerGnssNavigationMessageCallback( @onNull @allbackExecutor Executor executor, @NonNull GnssNavigationMessage.Callback callback)2893     public boolean registerGnssNavigationMessageCallback(
2894             @NonNull @CallbackExecutor Executor executor,
2895             @NonNull GnssNavigationMessage.Callback callback) {
2896         GnssLazyLoader.sGnssNavigationListeners.addListener(callback,
2897                 new GnssNavigationTransport(executor, mContext, callback));
2898         return true;
2899     }
2900 
2901     /**
2902      * Unregisters a GNSS Navigation Message callback.
2903      *
2904      * @param callback a {@link GnssNavigationMessage.Callback} object to remove.
2905      */
unregisterGnssNavigationMessageCallback( @onNull GnssNavigationMessage.Callback callback)2906     public void unregisterGnssNavigationMessageCallback(
2907             @NonNull GnssNavigationMessage.Callback callback) {
2908         GnssLazyLoader.sGnssNavigationListeners.removeListener(callback);
2909     }
2910 
2911     /**
2912      * Adds a {@link ProviderRequest.ChangedListener} for listening to all providers'
2913      * {@link ProviderRequest} changed events.
2914      *
2915      * @param executor the executor that the callback runs on
2916      * @param listener the listener to register
2917      * @hide
2918      */
2919     @SystemApi
2920     @RequiresPermission(Manifest.permission.LOCATION_HARDWARE)
addProviderRequestChangedListener( @onNull @allbackExecutor Executor executor, @NonNull ChangedListener listener)2921     public void addProviderRequestChangedListener(
2922             @NonNull @CallbackExecutor Executor executor,
2923             @NonNull ChangedListener listener) {
2924         ProviderRequestLazyLoader.sProviderRequestListeners.addListener(listener,
2925                 new ProviderRequestTransport(executor, listener));
2926     }
2927 
2928     /**
2929      * Removes a {@link ProviderRequest.ChangedListener} that has been added.
2930      *
2931      * @param listener the listener to remove.
2932      * @hide
2933      */
2934     @SystemApi
2935     @RequiresPermission(Manifest.permission.LOCATION_HARDWARE)
removeProviderRequestChangedListener( @onNull ProviderRequest.ChangedListener listener)2936     public void removeProviderRequestChangedListener(
2937             @NonNull ProviderRequest.ChangedListener listener) {
2938         ProviderRequestLazyLoader.sProviderRequestListeners.removeListener(listener);
2939     }
2940 
2941     /**
2942      * Returns the batch size (in number of Location objects) that are supported by the batching
2943      * interface.
2944      *
2945      * Prior to Android S this call requires the {@link Manifest.permission#LOCATION_HARDWARE}
2946      * permission.
2947      *
2948      * @return Maximum number of location objects that can be returned
2949      * @deprecated Do not use
2950      * @hide
2951      */
2952     @Deprecated
2953     @SystemApi
getGnssBatchSize()2954     public int getGnssBatchSize() {
2955         try {
2956             return mService.getGnssBatchSize();
2957         } catch (RemoteException e) {
2958             throw e.rethrowFromSystemServer();
2959         }
2960     }
2961 
2962     /**
2963      * Start hardware-batching of GNSS locations. This API is primarily used when the AP is
2964      * asleep and the device can batch GNSS locations in the hardware.
2965      *
2966      * Note this is designed (as was the fused location interface before it) for a single user
2967      * SystemApi - requests are not consolidated.  Care should be taken when the System switches
2968      * users that may have different batching requests, to stop hardware batching for one user, and
2969      * restart it for the next.
2970      *
2971      * @param periodNanos Time interval, in nanoseconds, that the GNSS locations are requested
2972      *                    within the batch
2973      * @param wakeOnFifoFull ignored
2974      * @param callback The listener on which to return the batched locations
2975      * @param handler The handler on which to process the callback
2976      *
2977      * @return True always
2978      * @deprecated Use {@link LocationRequest.Builder#setMaxUpdateDelayMillis(long)} instead.
2979      * @hide
2980      */
2981     @Deprecated
2982     @SystemApi
2983     @RequiresPermission(allOf = {Manifest.permission.LOCATION_HARDWARE,
2984             Manifest.permission.UPDATE_APP_OPS_STATS})
registerGnssBatchedLocationCallback(long periodNanos, boolean wakeOnFifoFull, @NonNull BatchedLocationCallback callback, @Nullable Handler handler)2985     public boolean registerGnssBatchedLocationCallback(long periodNanos, boolean wakeOnFifoFull,
2986             @NonNull BatchedLocationCallback callback, @Nullable Handler handler) {
2987         if (handler == null) {
2988             handler = new Handler();
2989         }
2990 
2991         try {
2992             mService.startGnssBatch(
2993                     periodNanos,
2994                     new BatchedLocationCallbackTransport(callback, handler),
2995                     mContext.getPackageName(),
2996                     mContext.getAttributionTag(),
2997                     AppOpsManager.toReceiverId(callback));
2998             return true;
2999         } catch (RemoteException e) {
3000             throw e.rethrowFromSystemServer();
3001         }
3002     }
3003 
3004     /**
3005      * Flush the batched GNSS locations. All GNSS locations currently ready in the batch are
3006      * returned via the callback sent in startGnssBatch(), and the buffer containing the batched
3007      * locations is cleared.
3008      *
3009      * @hide
3010      * @deprecated Use {@link #requestFlush(String, LocationListener, int)} or
3011      *             {@link #requestFlush(String, PendingIntent, int)} instead.
3012      */
3013     @Deprecated
3014     @SystemApi
3015     @RequiresPermission(Manifest.permission.LOCATION_HARDWARE)
flushGnssBatch()3016     public void flushGnssBatch() {
3017         try {
3018             mService.flushGnssBatch();
3019         } catch (RemoteException e) {
3020             throw e.rethrowFromSystemServer();
3021         }
3022     }
3023 
3024     /**
3025      * Stop batching locations. This API is primarily used when the AP is asleep and the device can
3026      * batch locations in the hardware.
3027      *
3028      * @param callback ignored
3029      *
3030      * @return True always
3031      * @deprecated Use {@link LocationRequest.Builder#setMaxUpdateDelayMillis(long)} instead.
3032      * @hide
3033      */
3034     @Deprecated
3035     @SystemApi
3036     @RequiresPermission(Manifest.permission.LOCATION_HARDWARE)
unregisterGnssBatchedLocationCallback( @onNull BatchedLocationCallback callback)3037     public boolean unregisterGnssBatchedLocationCallback(
3038             @NonNull BatchedLocationCallback callback) {
3039         try {
3040             mService.stopGnssBatch();
3041             return true;
3042         } catch (RemoteException e) {
3043             throw e.rethrowFromSystemServer();
3044         }
3045     }
3046 
3047     private static class GnssStatusTransportManager extends
3048             ListenerTransportManager<GnssStatusTransport> {
3049 
GnssStatusTransportManager()3050         GnssStatusTransportManager() {
3051             super(false);
3052         }
3053 
3054         @Override
registerTransport(GnssStatusTransport transport)3055         protected void registerTransport(GnssStatusTransport transport)
3056                             throws RemoteException {
3057             getService().registerGnssStatusCallback(transport, transport.getPackage(),
3058                     transport.getAttributionTag(),
3059                     AppOpsManager.toReceiverId(transport.getListener()));
3060         }
3061 
3062         @Override
unregisterTransport(GnssStatusTransport transport)3063         protected void unregisterTransport(GnssStatusTransport transport)
3064                             throws RemoteException {
3065             getService().unregisterGnssStatusCallback(transport);
3066         }
3067     }
3068 
3069     private static class GnssNmeaTransportManager extends
3070             ListenerTransportManager<GnssNmeaTransport> {
3071 
GnssNmeaTransportManager()3072         GnssNmeaTransportManager() {
3073             super(false);
3074         }
3075 
3076         @Override
registerTransport(GnssNmeaTransport transport)3077         protected void registerTransport(GnssNmeaTransport transport)
3078                             throws RemoteException {
3079             getService().registerGnssNmeaCallback(transport, transport.getPackage(),
3080                     transport.getAttributionTag(),
3081                     AppOpsManager.toReceiverId(transport.getListener()));
3082         }
3083 
3084         @Override
unregisterTransport(GnssNmeaTransport transport)3085         protected void unregisterTransport(GnssNmeaTransport transport)
3086                             throws RemoteException {
3087             getService().unregisterGnssNmeaCallback(transport);
3088         }
3089     }
3090 
3091     private static class GnssMeasurementsTransportManager extends
3092             ListenerTransportManager<GnssMeasurementsTransport> {
3093 
GnssMeasurementsTransportManager()3094         GnssMeasurementsTransportManager() {
3095             super(false);
3096         }
3097 
3098         @Override
registerTransport(GnssMeasurementsTransport transport)3099         protected void registerTransport(GnssMeasurementsTransport transport)
3100                             throws RemoteException {
3101             getService().addGnssMeasurementsListener(transport.getRequest(), transport,
3102                     transport.getPackage(), transport.getAttributionTag(),
3103                     AppOpsManager.toReceiverId(transport.getListener()));
3104         }
3105 
3106         @Override
unregisterTransport(GnssMeasurementsTransport transport)3107         protected void unregisterTransport(GnssMeasurementsTransport transport)
3108                             throws RemoteException {
3109             getService().removeGnssMeasurementsListener(transport);
3110         }
3111     }
3112 
3113     private static class GnssAntennaTransportManager extends
3114             ListenerTransportManager<GnssAntennaInfoTransport> {
3115 
GnssAntennaTransportManager()3116         GnssAntennaTransportManager() {
3117             super(false);
3118         }
3119 
3120         @Override
registerTransport(GnssAntennaInfoTransport transport)3121         protected void registerTransport(GnssAntennaInfoTransport transport)
3122                 throws RemoteException {
3123             getService().addGnssAntennaInfoListener(transport, transport.getPackage(),
3124                     transport.getAttributionTag(),
3125                     AppOpsManager.toReceiverId(transport.getListener()));
3126         }
3127 
3128         @Override
unregisterTransport(GnssAntennaInfoTransport transport)3129         protected void unregisterTransport(GnssAntennaInfoTransport transport)
3130                 throws RemoteException {
3131             getService().removeGnssAntennaInfoListener(transport);
3132         }
3133     }
3134 
3135     private static class GnssNavigationTransportManager extends
3136             ListenerTransportManager<GnssNavigationTransport> {
3137 
GnssNavigationTransportManager()3138         GnssNavigationTransportManager() {
3139             super(false);
3140         }
3141 
3142         @Override
registerTransport(GnssNavigationTransport transport)3143         protected void registerTransport(GnssNavigationTransport transport)
3144                             throws RemoteException {
3145             getService().addGnssNavigationMessageListener(transport,
3146                     transport.getPackage(), transport.getAttributionTag(),
3147                     AppOpsManager.toReceiverId(transport.getListener()));
3148         }
3149 
3150         @Override
unregisterTransport(GnssNavigationTransport transport)3151         protected void unregisterTransport(GnssNavigationTransport transport)
3152                             throws RemoteException {
3153             getService().removeGnssNavigationMessageListener(transport);
3154         }
3155     }
3156 
3157     private static class ProviderRequestTransportManager extends
3158             ListenerTransportManager<ProviderRequestTransport> {
3159 
ProviderRequestTransportManager()3160         ProviderRequestTransportManager() {
3161             super(false);
3162         }
3163 
3164         @Override
registerTransport(ProviderRequestTransport transport)3165         protected void registerTransport(ProviderRequestTransport transport)
3166                 throws RemoteException {
3167             getService().addProviderRequestListener(transport);
3168         }
3169 
3170         @Override
unregisterTransport(ProviderRequestTransport transport)3171         protected void unregisterTransport(ProviderRequestTransport transport)
3172                 throws RemoteException {
3173             getService().removeProviderRequestListener(transport);
3174         }
3175     }
3176 
3177     private static class GetCurrentLocationTransport extends ILocationCallback.Stub implements
3178             ListenerExecutor, CancellationSignal.OnCancelListener {
3179 
3180         private final Executor mExecutor;
3181         volatile @Nullable Consumer<Location> mConsumer;
3182 
GetCurrentLocationTransport(Executor executor, Consumer<Location> consumer, @Nullable CancellationSignal cancellationSignal)3183         GetCurrentLocationTransport(Executor executor, Consumer<Location> consumer,
3184                 @Nullable CancellationSignal cancellationSignal) {
3185             Preconditions.checkArgument(executor != null, "illegal null executor");
3186             Preconditions.checkArgument(consumer != null, "illegal null consumer");
3187             mExecutor = executor;
3188             mConsumer = consumer;
3189 
3190             if (cancellationSignal != null) {
3191                 cancellationSignal.setOnCancelListener(this);
3192             }
3193         }
3194 
3195         @Override
onCancel()3196         public void onCancel() {
3197             mConsumer = null;
3198         }
3199 
3200         @Override
onLocation(@ullable Location location)3201         public void onLocation(@Nullable Location location) {
3202             executeSafely(mExecutor, () -> mConsumer, new ListenerOperation<Consumer<Location>>() {
3203                 @Override
3204                 public void operate(Consumer<Location> consumer) {
3205                     consumer.accept(location);
3206                 }
3207 
3208                 @Override
3209                 public void onPostExecute(boolean success) {
3210                     mConsumer = null;
3211                 }
3212             });
3213         }
3214     }
3215 
3216     private static class LocationListenerTransport extends ILocationListener.Stub implements
3217             ListenerExecutor {
3218 
3219         private Executor mExecutor;
3220         private volatile @Nullable LocationListener mListener;
3221 
LocationListenerTransport(LocationListener listener, Executor executor)3222         LocationListenerTransport(LocationListener listener, Executor executor) {
3223             Preconditions.checkArgument(listener != null, "invalid null listener");
3224             mListener = listener;
3225             setExecutor(executor);
3226         }
3227 
setExecutor(Executor executor)3228         void setExecutor(Executor executor) {
3229             Preconditions.checkArgument(executor != null, "invalid null executor");
3230             mExecutor = executor;
3231         }
3232 
isRegistered()3233         boolean isRegistered() {
3234             return mListener != null;
3235         }
3236 
unregister()3237         void unregister() {
3238             mListener = null;
3239         }
3240 
3241         @Override
onLocationChanged(List<Location> locations, @Nullable IRemoteCallback onCompleteCallback)3242         public void onLocationChanged(List<Location> locations,
3243                 @Nullable IRemoteCallback onCompleteCallback) {
3244             executeSafely(mExecutor, () -> mListener, new ListenerOperation<LocationListener>() {
3245                 @Override
3246                 public void operate(LocationListener listener) {
3247                     listener.onLocationChanged(locations);
3248                 }
3249 
3250                 @Override
3251                 public void onComplete(boolean success) {
3252                     if (onCompleteCallback != null) {
3253                         try {
3254                             onCompleteCallback.sendResult(null);
3255                         } catch (RemoteException e) {
3256                             throw e.rethrowFromSystemServer();
3257                         }
3258                     }
3259                 }
3260             });
3261         }
3262 
3263         @Override
onFlushComplete(int requestCode)3264         public void onFlushComplete(int requestCode) {
3265             executeSafely(mExecutor, () -> mListener,
3266                     listener -> listener.onFlushComplete(requestCode));
3267         }
3268 
3269         @Override
onProviderEnabledChanged(String provider, boolean enabled)3270         public void onProviderEnabledChanged(String provider, boolean enabled) {
3271             executeSafely(mExecutor, () -> mListener, listener -> {
3272                 if (enabled) {
3273                     listener.onProviderEnabled(provider);
3274                 } else {
3275                     listener.onProviderDisabled(provider);
3276                 }
3277             });
3278         }
3279     }
3280 
3281     /** @deprecated */
3282     @Deprecated
3283     private static class GpsAdapter extends GnssStatus.Callback {
3284 
3285         private final GpsStatus.Listener mGpsListener;
3286 
GpsAdapter(GpsStatus.Listener gpsListener)3287         GpsAdapter(GpsStatus.Listener gpsListener) {
3288             mGpsListener = gpsListener;
3289         }
3290 
3291         @Override
onStarted()3292         public void onStarted() {
3293             mGpsListener.onGpsStatusChanged(GpsStatus.GPS_EVENT_STARTED);
3294         }
3295 
3296         @Override
onStopped()3297         public void onStopped() {
3298             mGpsListener.onGpsStatusChanged(GpsStatus.GPS_EVENT_STOPPED);
3299         }
3300 
3301         @Override
onFirstFix(int ttffMillis)3302         public void onFirstFix(int ttffMillis) {
3303             mGpsListener.onGpsStatusChanged(GpsStatus.GPS_EVENT_FIRST_FIX);
3304         }
3305 
3306         @Override
onSatelliteStatusChanged(GnssStatus status)3307         public void onSatelliteStatusChanged(GnssStatus status) {
3308             mGpsListener.onGpsStatusChanged(GpsStatus.GPS_EVENT_SATELLITE_STATUS);
3309         }
3310     }
3311 
3312     private static class GnssStatusTransport extends IGnssStatusListener.Stub implements
3313             ListenerTransport<GnssStatus.Callback> {
3314 
3315         private final Executor mExecutor;
3316         private final String mPackageName;
3317         private final String mAttributionTag;
3318 
3319         private volatile @Nullable GnssStatus.Callback mListener;
3320 
GnssStatusTransport(Executor executor, Context context, GnssStatus.Callback listener)3321         GnssStatusTransport(Executor executor, Context context, GnssStatus.Callback listener) {
3322             Preconditions.checkArgument(executor != null, "invalid null executor");
3323             Preconditions.checkArgument(listener != null, "invalid null callback");
3324             mExecutor = executor;
3325             mPackageName = context.getPackageName();
3326             mAttributionTag = context.getAttributionTag();
3327             mListener = listener;
3328         }
3329 
getPackage()3330         public String getPackage() {
3331             return mPackageName;
3332         }
3333 
getAttributionTag()3334         public String getAttributionTag() {
3335             return mAttributionTag;
3336         }
3337 
3338         @Override
unregister()3339         public void unregister() {
3340             mListener = null;
3341         }
3342 
3343         @Override
getListener()3344         public @Nullable GnssStatus.Callback getListener() {
3345             return mListener;
3346         }
3347 
3348         @Override
onGnssStarted()3349         public void onGnssStarted() {
3350             execute(mExecutor, GnssStatus.Callback::onStarted);
3351         }
3352 
3353         @Override
onGnssStopped()3354         public void onGnssStopped() {
3355             execute(mExecutor, GnssStatus.Callback::onStopped);
3356         }
3357 
3358         @Override
onFirstFix(int ttff)3359         public void onFirstFix(int ttff) {
3360             execute(mExecutor, listener -> listener.onFirstFix(ttff));
3361 
3362         }
3363 
3364         @Override
onSvStatusChanged(GnssStatus gnssStatus)3365         public void onSvStatusChanged(GnssStatus gnssStatus) {
3366             execute(mExecutor, listener -> listener.onSatelliteStatusChanged(gnssStatus));
3367         }
3368     }
3369 
3370     /** @deprecated */
3371     @Deprecated
3372     private static class GpsStatusTransport extends GnssStatusTransport {
3373 
3374         static volatile int sTtff;
3375         static volatile GnssStatus sGnssStatus;
3376 
GpsStatusTransport(Executor executor, Context context, GpsStatus.Listener listener)3377         GpsStatusTransport(Executor executor, Context context, GpsStatus.Listener listener) {
3378             super(executor, context, new GpsAdapter(listener));
3379         }
3380 
3381         @Override
onFirstFix(int ttff)3382         public void onFirstFix(int ttff) {
3383             sTtff = ttff;
3384             super.onFirstFix(ttff);
3385         }
3386 
3387         @Override
onSvStatusChanged(GnssStatus gnssStatus)3388         public void onSvStatusChanged(GnssStatus gnssStatus) {
3389             sGnssStatus = gnssStatus;
3390             super.onSvStatusChanged(gnssStatus);
3391         }
3392     }
3393 
3394     private static class GnssNmeaTransport extends IGnssNmeaListener.Stub implements
3395             ListenerTransport<OnNmeaMessageListener> {
3396 
3397         private final Executor mExecutor;
3398         private final String mPackageName;
3399         private final String mAttributionTag;
3400 
3401         private volatile @Nullable OnNmeaMessageListener mListener;
3402 
GnssNmeaTransport(Executor executor, Context context, OnNmeaMessageListener listener)3403         GnssNmeaTransport(Executor executor, Context context, OnNmeaMessageListener listener) {
3404             Preconditions.checkArgument(executor != null, "invalid null executor");
3405             Preconditions.checkArgument(listener != null, "invalid null listener");
3406             mExecutor = executor;
3407             mPackageName = context.getPackageName();
3408             mAttributionTag = context.getAttributionTag();
3409             mListener = listener;
3410         }
3411 
getPackage()3412         public String getPackage() {
3413             return mPackageName;
3414         }
3415 
getAttributionTag()3416         public String getAttributionTag() {
3417             return mAttributionTag;
3418         }
3419 
3420         @Override
unregister()3421         public void unregister() {
3422             mListener = null;
3423         }
3424 
3425         @Override
getListener()3426         public @Nullable OnNmeaMessageListener getListener() {
3427             return mListener;
3428         }
3429 
3430         @Override
onNmeaReceived(long timestamp, String nmea)3431         public void onNmeaReceived(long timestamp, String nmea) {
3432             execute(mExecutor, callback -> callback.onNmeaMessage(nmea, timestamp));
3433         }
3434     }
3435 
3436     private static class GnssMeasurementsTransport extends IGnssMeasurementsListener.Stub implements
3437             ListenerTransport<GnssMeasurementsEvent.Callback> {
3438 
3439         private final Executor mExecutor;
3440         private final String mPackageName;
3441         private final String mAttributionTag;
3442         private final GnssMeasurementRequest mRequest;
3443 
3444         private volatile @Nullable GnssMeasurementsEvent.Callback mListener;
3445 
GnssMeasurementsTransport(Executor executor, Context context, GnssMeasurementRequest request, GnssMeasurementsEvent.Callback listener)3446         GnssMeasurementsTransport(Executor executor, Context context,
3447                 GnssMeasurementRequest request, GnssMeasurementsEvent.Callback listener) {
3448             Preconditions.checkArgument(executor != null, "invalid null executor");
3449             Preconditions.checkArgument(listener != null, "invalid null callback");
3450             Preconditions.checkArgument(request != null, "invalid null request");
3451             mExecutor = executor;
3452             mPackageName = context.getPackageName();
3453             mAttributionTag = context.getAttributionTag();
3454             mRequest = request;
3455             mListener = listener;
3456         }
3457 
getPackage()3458         public String getPackage() {
3459             return mPackageName;
3460         }
3461 
getAttributionTag()3462         public String getAttributionTag() {
3463             return mAttributionTag;
3464         }
3465 
getRequest()3466         public GnssMeasurementRequest getRequest() {
3467             return mRequest;
3468         }
3469 
3470         @Override
unregister()3471         public void unregister() {
3472             mListener = null;
3473         }
3474 
3475         @Override
getListener()3476         public @Nullable GnssMeasurementsEvent.Callback getListener() {
3477             return mListener;
3478         }
3479 
3480         @Override
onGnssMeasurementsReceived(GnssMeasurementsEvent event)3481         public void onGnssMeasurementsReceived(GnssMeasurementsEvent event) {
3482             execute(mExecutor, callback -> callback.onGnssMeasurementsReceived(event));
3483         }
3484 
3485         @Override
onStatusChanged(int status)3486         public void onStatusChanged(int status) {
3487             execute(mExecutor, callback -> callback.onStatusChanged(status));
3488         }
3489     }
3490 
3491     private static class GnssAntennaInfoTransport extends IGnssAntennaInfoListener.Stub implements
3492             ListenerTransport<GnssAntennaInfo.Listener> {
3493 
3494         private final Executor mExecutor;
3495         private final String mPackageName;
3496         private final String mAttributionTag;
3497 
3498         private volatile @Nullable GnssAntennaInfo.Listener mListener;
3499 
GnssAntennaInfoTransport(Executor executor, Context context, GnssAntennaInfo.Listener listener)3500         GnssAntennaInfoTransport(Executor executor, Context context,
3501                 GnssAntennaInfo.Listener listener) {
3502             Preconditions.checkArgument(executor != null, "invalid null executor");
3503             Preconditions.checkArgument(listener != null, "invalid null listener");
3504             mExecutor = executor;
3505             mPackageName = context.getPackageName();
3506             mAttributionTag = context.getAttributionTag();
3507             mListener = listener;
3508         }
3509 
getPackage()3510         public String getPackage() {
3511             return mPackageName;
3512         }
3513 
getAttributionTag()3514         public String getAttributionTag() {
3515             return mAttributionTag;
3516         }
3517 
3518         @Override
unregister()3519         public void unregister() {
3520             mListener = null;
3521         }
3522 
3523         @Override
getListener()3524         public @Nullable GnssAntennaInfo.Listener getListener() {
3525             return mListener;
3526         }
3527 
3528         @Override
onGnssAntennaInfoChanged(List<GnssAntennaInfo> antennaInfos)3529         public void onGnssAntennaInfoChanged(List<GnssAntennaInfo> antennaInfos) {
3530             execute(mExecutor, callback -> callback.onGnssAntennaInfoReceived(antennaInfos));
3531         }
3532     }
3533 
3534     private static class GnssNavigationTransport extends IGnssNavigationMessageListener.Stub
3535             implements ListenerTransport<GnssNavigationMessage.Callback> {
3536 
3537         private final Executor mExecutor;
3538         private final String mPackageName;
3539         private final String mAttributionTag;
3540 
3541         private volatile @Nullable GnssNavigationMessage.Callback mListener;
3542 
GnssNavigationTransport(Executor executor, Context context, GnssNavigationMessage.Callback listener)3543         GnssNavigationTransport(Executor executor, Context context,
3544                 GnssNavigationMessage.Callback listener) {
3545             Preconditions.checkArgument(executor != null, "invalid null executor");
3546             Preconditions.checkArgument(listener != null, "invalid null callback");
3547             mExecutor = executor;
3548             mPackageName = context.getPackageName();
3549             mAttributionTag = context.getAttributionTag();
3550             mListener = listener;
3551         }
3552 
getPackage()3553         public String getPackage() {
3554             return mPackageName;
3555         }
3556 
getAttributionTag()3557         public String getAttributionTag() {
3558             return mAttributionTag;
3559         }
3560 
3561         @Override
unregister()3562         public void unregister() {
3563             mListener = null;
3564         }
3565 
3566         @Override
getListener()3567         public @Nullable GnssNavigationMessage.Callback getListener() {
3568             return mListener;
3569         }
3570 
3571         @Override
onGnssNavigationMessageReceived(GnssNavigationMessage event)3572         public void onGnssNavigationMessageReceived(GnssNavigationMessage event) {
3573             execute(mExecutor, listener -> listener.onGnssNavigationMessageReceived(event));
3574         }
3575 
3576         @Override
onStatusChanged(int status)3577         public void onStatusChanged(int status) {
3578             execute(mExecutor, listener -> listener.onStatusChanged(status));
3579         }
3580     }
3581 
3582     private static class ProviderRequestTransport extends IProviderRequestListener.Stub
3583             implements ListenerTransport<ChangedListener> {
3584 
3585         private final Executor mExecutor;
3586 
3587         private volatile @Nullable ProviderRequest.ChangedListener mListener;
3588 
ProviderRequestTransport(Executor executor, ChangedListener listener)3589         ProviderRequestTransport(Executor executor, ChangedListener listener) {
3590             Preconditions.checkArgument(executor != null, "invalid null executor");
3591             Preconditions.checkArgument(listener != null, "invalid null callback");
3592             mExecutor = executor;
3593             mListener = listener;
3594         }
3595 
3596         @Override
unregister()3597         public void unregister() {
3598             mListener = null;
3599         }
3600 
3601         @Override
getListener()3602         public @Nullable ProviderRequest.ChangedListener getListener() {
3603             return mListener;
3604         }
3605 
3606         @Override
onProviderRequestChanged(String provider, ProviderRequest request)3607         public void onProviderRequestChanged(String provider, ProviderRequest request) {
3608             execute(mExecutor, listener -> listener.onProviderRequestChanged(provider, request));
3609         }
3610     }
3611 
3612     /** @deprecated */
3613     @Deprecated
3614     private static class BatchedLocationCallbackWrapper implements LocationListener {
3615 
3616         private final BatchedLocationCallback mCallback;
3617 
BatchedLocationCallbackWrapper(BatchedLocationCallback callback)3618         BatchedLocationCallbackWrapper(BatchedLocationCallback callback) {
3619             mCallback = callback;
3620         }
3621 
3622         @Override
onLocationChanged(@onNull Location location)3623         public void onLocationChanged(@NonNull Location location) {
3624             mCallback.onLocationBatch(Collections.singletonList(location));
3625         }
3626 
3627         @Override
onLocationChanged(@onNull List<Location> locations)3628         public void onLocationChanged(@NonNull List<Location> locations) {
3629             mCallback.onLocationBatch(locations);
3630         }
3631     }
3632 
3633     /** @deprecated */
3634     @Deprecated
3635     private static class BatchedLocationCallbackTransport extends LocationListenerTransport {
3636 
BatchedLocationCallbackTransport(BatchedLocationCallback callback, Handler handler)3637         BatchedLocationCallbackTransport(BatchedLocationCallback callback, Handler handler) {
3638             super(new BatchedLocationCallbackWrapper(callback), new HandlerExecutor(handler));
3639         }
3640     }
3641 
3642     private static class LocationEnabledCache extends PropertyInvalidatedCache<Integer, Boolean> {
3643 
3644         // this is not loaded immediately because this class is created as soon as LocationManager
3645         // is referenced for the first time, and within the system server, the ILocationManager
3646         // service may not have been loaded yet at that time.
3647         private @Nullable ILocationManager mManager;
3648 
LocationEnabledCache(int numEntries)3649         LocationEnabledCache(int numEntries) {
3650             super(numEntries, CACHE_KEY_LOCATION_ENABLED_PROPERTY);
3651         }
3652 
3653         @Override
recompute(Integer userId)3654         public Boolean recompute(Integer userId) {
3655             Preconditions.checkArgument(userId >= 0);
3656 
3657             if (mManager == null) {
3658                 try {
3659                     mManager = getService();
3660                 } catch (RemoteException e) {
3661                     e.rethrowFromSystemServer();
3662                 }
3663             }
3664 
3665             try {
3666                 return mManager.isLocationEnabledForUser(userId);
3667             } catch (RemoteException e) {
3668                 throw e.rethrowFromSystemServer();
3669             }
3670         }
3671     }
3672 
3673     /**
3674      * @hide
3675      */
invalidateLocalLocationEnabledCaches()3676     public static void invalidateLocalLocationEnabledCaches() {
3677         PropertyInvalidatedCache.invalidateCache(CACHE_KEY_LOCATION_ENABLED_PROPERTY);
3678     }
3679 
3680     /**
3681      * @hide
3682      */
disableLocalLocationEnabledCaches()3683     public static void disableLocalLocationEnabledCaches() {
3684         sLocationEnabledCache = null;
3685     }
3686 }
3687