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