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 * <receiver android:name="com.example.android.footer.MyFooterInjector"> 385 * <intent-filter> 386 * <action android:name="com.android.settings.location.INJECT_FOOTER" /> 387 * </intent-filter> 388 * <meta-data 389 * android:name="com.android.settings.location.FOOTER_STRING" 390 * android:resource="@string/my_injected_footer_string" /> 391 * </receiver> 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