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