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