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