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