1 /* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.location; 18 19 import static android.Manifest.permission.ACCESS_COARSE_LOCATION; 20 import static android.Manifest.permission.ACCESS_FINE_LOCATION; 21 import static android.Manifest.permission.LOCATION_HARDWARE; 22 import static android.Manifest.permission.WRITE_SECURE_SETTINGS; 23 24 import android.Manifest; 25 import android.annotation.NonNull; 26 import android.annotation.Nullable; 27 import android.annotation.RequiresFeature; 28 import android.annotation.RequiresPermission; 29 import android.annotation.SuppressLint; 30 import android.annotation.SystemApi; 31 import android.annotation.SystemService; 32 import android.annotation.TestApi; 33 import android.annotation.UnsupportedAppUsage; 34 import android.app.PendingIntent; 35 import android.content.Context; 36 import android.content.Intent; 37 import android.content.pm.PackageManager; 38 import android.os.Build; 39 import android.os.Bundle; 40 import android.os.Handler; 41 import android.os.Looper; 42 import android.os.Message; 43 import android.os.Process; 44 import android.os.RemoteException; 45 import android.os.UserHandle; 46 import android.provider.Settings; 47 import android.util.ArrayMap; 48 import android.util.Log; 49 50 import com.android.internal.location.ProviderProperties; 51 52 import java.util.ArrayList; 53 import java.util.List; 54 55 /** 56 * This class provides access to the system location services. These 57 * services allow applications to obtain periodic updates of the 58 * device's geographical location, or to fire an application-specified 59 * {@link Intent} when the device enters the proximity of a given 60 * geographical location. 61 * 62 * <p class="note">Unless noted, all Location API methods require 63 * the {@link android.Manifest.permission#ACCESS_COARSE_LOCATION} or 64 * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} permissions. 65 * If your application only has the coarse permission then it will not have 66 * access to the GPS or passive location providers. Other providers will still 67 * return location results, but the update rate will be throttled and the exact 68 * location will be obfuscated to a coarse level of accuracy. 69 */ 70 @SystemService(Context.LOCATION_SERVICE) 71 @RequiresFeature(PackageManager.FEATURE_LOCATION) 72 public class LocationManager { 73 private static final String TAG = "LocationManager"; 74 75 private final Context mContext; 76 @UnsupportedAppUsage 77 private final ILocationManager mService; 78 private final GnssMeasurementCallbackTransport mGnssMeasurementCallbackTransport; 79 private final GnssNavigationMessageCallbackTransport mGnssNavigationMessageCallbackTransport; 80 private final BatchedLocationCallbackTransport mBatchedLocationCallbackTransport; 81 private final ArrayMap<GnssStatus.Callback, GnssStatusListenerTransport> mGnssStatusListeners = 82 new ArrayMap<>(); 83 private final ArrayMap<OnNmeaMessageListener, GnssStatusListenerTransport> mGnssNmeaListeners = 84 new ArrayMap<>(); 85 private final ArrayMap<GpsStatus.Listener, GnssStatusListenerTransport> mGpsStatusListeners = 86 new ArrayMap<>(); 87 // volatile + GnssStatus final-fields pattern to avoid a partially published object 88 private volatile GnssStatus mGnssStatus; 89 private int mTimeToFirstFix; 90 91 /** 92 * Name of the network location provider. 93 * <p>This provider determines location based on 94 * availability of cell tower and WiFi access points. Results are retrieved 95 * by means of a network lookup. 96 */ 97 public static final String NETWORK_PROVIDER = "network"; 98 99 /** 100 * Name of the GPS location provider. 101 * 102 * <p>This provider determines location using 103 * satellites. Depending on conditions, this provider may take a while to return 104 * a location fix. Requires the permission 105 * {@link android.Manifest.permission#ACCESS_FINE_LOCATION}. 106 * 107 * <p> The extras Bundle for the GPS location provider can contain the 108 * following key/value pairs: 109 * <ul> 110 * <li> satellites - the number of satellites used to derive the fix 111 * </ul> 112 */ 113 public static final String GPS_PROVIDER = "gps"; 114 115 /** 116 * A special location provider for receiving locations without actually initiating 117 * a location fix. 118 * 119 * <p>This provider can be used to passively receive location updates 120 * when other applications or services request them without actually requesting 121 * the locations yourself. This provider will return locations generated by other 122 * providers. You can query the {@link Location#getProvider()} method to determine 123 * the origin of the location update. Requires the permission 124 * {@link android.Manifest.permission#ACCESS_FINE_LOCATION}, although if the GPS is 125 * not enabled this provider might only return coarse fixes. 126 */ 127 public static final String PASSIVE_PROVIDER = "passive"; 128 129 /** 130 * Name of the Fused location provider. 131 * 132 * <p>This provider combines inputs for all possible location sources 133 * to provide the best possible Location fix. It is implicitly 134 * used for all API's that involve the {@link LocationRequest} 135 * object. 136 * 137 * @hide 138 */ 139 public static final String FUSED_PROVIDER = "fused"; 140 141 /** 142 * Key used for the Bundle extra holding a boolean indicating whether 143 * a proximity alert is entering (true) or exiting (false).. 144 */ 145 public static final String KEY_PROXIMITY_ENTERING = "entering"; 146 147 /** 148 * This key is no longer in use. 149 * 150 * Key used for a Bundle extra holding an Integer status value 151 * when a status change is broadcast using a PendingIntent. 152 * 153 * @deprecated Status changes are deprecated and no longer broadcast. 154 */ 155 @Deprecated 156 public static final String KEY_STATUS_CHANGED = "status"; 157 158 /** 159 * Key used for a Bundle extra holding an Boolean status value 160 * when a provider enabled/disabled event is broadcast using a PendingIntent. 161 */ 162 public static final String KEY_PROVIDER_ENABLED = "providerEnabled"; 163 164 /** 165 * Key used for a Bundle extra holding a Location value 166 * when a location change is broadcast using a PendingIntent. 167 */ 168 public static final String KEY_LOCATION_CHANGED = "location"; 169 170 /** 171 * Broadcast intent action when the set of enabled location providers changes. To check the 172 * status of a provider, use {@link #isProviderEnabled(String)}. From Android Q and above, will 173 * include a string intent extra, {@link #EXTRA_PROVIDER_NAME}, with the name of the provider 174 * whose state has changed. 175 * 176 * @see #EXTRA_PROVIDER_NAME 177 */ 178 public static final String PROVIDERS_CHANGED_ACTION = "android.location.PROVIDERS_CHANGED"; 179 180 /** 181 * Intent extra included with {@link #PROVIDERS_CHANGED_ACTION} broadcasts, containing the name 182 * of the location provider that has changed, to be used with location provider APIs. 183 */ 184 public static final String EXTRA_PROVIDER_NAME = "android.location.extra.PROVIDER_NAME"; 185 186 /** 187 * Broadcast intent action when the device location mode changes. To check the location mode, 188 * use {@link #isLocationEnabled()}. 189 */ 190 public static final String MODE_CHANGED_ACTION = "android.location.MODE_CHANGED"; 191 192 /** 193 * Broadcast intent action when {@link android.provider.Settings.Secure#LOCATION_MODE} is 194 * about to be changed through Settings app or Quick Settings. 195 * For use with the {@link android.provider.Settings.Secure#LOCATION_MODE} API. 196 * If you're interacting with {@link #isProviderEnabled(String)}, use 197 * {@link #PROVIDERS_CHANGED_ACTION} instead. 198 * 199 * @deprecated Do not use. 200 * @hide 201 */ 202 @Deprecated 203 public static final String MODE_CHANGING_ACTION = "com.android.settings.location.MODE_CHANGING"; 204 205 /** 206 * Broadcast intent action indicating that a high power location requests 207 * has either started or stopped being active. The current state of 208 * active location requests should be read from AppOpsManager using 209 * {@code OP_MONITOR_HIGH_POWER_LOCATION}. 210 * 211 * @hide 212 */ 213 public static final String HIGH_POWER_REQUEST_CHANGE_ACTION = 214 "android.location.HIGH_POWER_REQUEST_CHANGE"; 215 216 /** 217 * Broadcast intent action for Settings app to inject a footer at the bottom of location 218 * settings. 219 * 220 * <p>This broadcast is used for two things: 221 * <ol> 222 * <li>For receivers to inject a footer with provided text. This is for use only by apps 223 * that are included in the system image. </li> 224 * <li>For receivers to know their footer is injected under location settings.</li> 225 * </ol> 226 * 227 * <p>To inject a footer to location settings, you must declare a broadcast receiver of 228 * {@link LocationManager#SETTINGS_FOOTER_DISPLAYED_ACTION} in the manifest as so: 229 * <pre> 230 * <receiver android:name="com.example.android.footer.MyFooterInjector"> 231 * <intent-filter> 232 * <action android:name="com.android.settings.location.INJECT_FOOTER" /> 233 * </intent-filter> 234 * <meta-data 235 * android:name="com.android.settings.location.FOOTER_STRING" 236 * android:resource="@string/my_injected_footer_string" /> 237 * </receiver> 238 * </pre> 239 * 240 * <p>On entering location settings, Settings app will send a 241 * {@link #SETTINGS_FOOTER_DISPLAYED_ACTION} broadcast to receivers whose footer is successfully 242 * injected. On leaving location settings, the footer becomes not visible to users. Settings app 243 * will send a {@link #SETTINGS_FOOTER_REMOVED_ACTION} broadcast to those receivers. 244 * 245 * @hide 246 */ 247 public static final String SETTINGS_FOOTER_DISPLAYED_ACTION = 248 "com.android.settings.location.DISPLAYED_FOOTER"; 249 250 /** 251 * Broadcast intent action when location settings footer is not visible to users. 252 * 253 * <p>See {@link #SETTINGS_FOOTER_DISPLAYED_ACTION} for more detail on how to use. 254 * 255 * @hide 256 */ 257 public static final String SETTINGS_FOOTER_REMOVED_ACTION = 258 "com.android.settings.location.REMOVED_FOOTER"; 259 260 /** 261 * Metadata name for {@link LocationManager#SETTINGS_FOOTER_DISPLAYED_ACTION} broadcast 262 * receivers to specify a string resource id as location settings footer text. This is for use 263 * only by apps that are included in the system image. 264 * 265 * <p>See {@link #SETTINGS_FOOTER_DISPLAYED_ACTION} for more detail on how to use. 266 * 267 * @hide 268 */ 269 public static final String METADATA_SETTINGS_FOOTER_STRING = 270 "com.android.settings.location.FOOTER_STRING"; 271 272 // Map from LocationListeners to their associated ListenerTransport objects 273 private final ArrayMap<LocationListener, ListenerTransport> mListeners = new ArrayMap<>(); 274 275 private class ListenerTransport extends ILocationListener.Stub { 276 private static final int TYPE_LOCATION_CHANGED = 1; 277 private static final int TYPE_STATUS_CHANGED = 2; 278 private static final int TYPE_PROVIDER_ENABLED = 3; 279 private static final int TYPE_PROVIDER_DISABLED = 4; 280 281 private LocationListener mListener; 282 private final Handler mListenerHandler; 283 ListenerTransport(LocationListener listener, Looper looper)284 ListenerTransport(LocationListener listener, Looper looper) { 285 mListener = listener; 286 287 if (looper == null) { 288 mListenerHandler = new Handler() { 289 @Override 290 public void handleMessage(Message msg) { 291 _handleMessage(msg); 292 } 293 }; 294 } else { 295 mListenerHandler = new Handler(looper) { 296 @Override 297 public void handleMessage(Message msg) { 298 _handleMessage(msg); 299 } 300 }; 301 } 302 } 303 304 @Override onLocationChanged(Location location)305 public void onLocationChanged(Location location) { 306 Message msg = Message.obtain(); 307 msg.what = TYPE_LOCATION_CHANGED; 308 msg.obj = location; 309 sendCallbackMessage(msg); 310 } 311 312 @Override onStatusChanged(String provider, int status, Bundle extras)313 public void onStatusChanged(String provider, int status, Bundle extras) { 314 Message msg = Message.obtain(); 315 msg.what = TYPE_STATUS_CHANGED; 316 Bundle b = new Bundle(); 317 b.putString("provider", provider); 318 b.putInt("status", status); 319 if (extras != null) { 320 b.putBundle("extras", extras); 321 } 322 msg.obj = b; 323 sendCallbackMessage(msg); 324 } 325 326 @Override onProviderEnabled(String provider)327 public void onProviderEnabled(String provider) { 328 Message msg = Message.obtain(); 329 msg.what = TYPE_PROVIDER_ENABLED; 330 msg.obj = provider; 331 sendCallbackMessage(msg); 332 } 333 334 @Override onProviderDisabled(String provider)335 public void onProviderDisabled(String provider) { 336 Message msg = Message.obtain(); 337 msg.what = TYPE_PROVIDER_DISABLED; 338 msg.obj = provider; 339 sendCallbackMessage(msg); 340 } 341 sendCallbackMessage(Message msg)342 private void sendCallbackMessage(Message msg) { 343 if (!mListenerHandler.sendMessage(msg)) { 344 locationCallbackFinished(); 345 } 346 } 347 _handleMessage(Message msg)348 private void _handleMessage(Message msg) { 349 switch (msg.what) { 350 case TYPE_LOCATION_CHANGED: 351 Location location = new Location((Location) msg.obj); 352 mListener.onLocationChanged(location); 353 break; 354 case TYPE_STATUS_CHANGED: 355 Bundle b = (Bundle) msg.obj; 356 String provider = b.getString("provider"); 357 int status = b.getInt("status"); 358 Bundle extras = b.getBundle("extras"); 359 mListener.onStatusChanged(provider, status, extras); 360 break; 361 case TYPE_PROVIDER_ENABLED: 362 mListener.onProviderEnabled((String) msg.obj); 363 break; 364 case TYPE_PROVIDER_DISABLED: 365 mListener.onProviderDisabled((String) msg.obj); 366 break; 367 } 368 locationCallbackFinished(); 369 } 370 locationCallbackFinished()371 private void locationCallbackFinished() { 372 try { 373 mService.locationCallbackFinished(this); 374 } catch (RemoteException e) { 375 throw e.rethrowFromSystemServer(); 376 } 377 } 378 } 379 380 /** 381 * @hide 382 */ 383 @TestApi getBackgroundThrottlingWhitelist()384 public @NonNull String[] getBackgroundThrottlingWhitelist() { 385 try { 386 return mService.getBackgroundThrottlingWhitelist(); 387 } catch (RemoteException e) { 388 throw e.rethrowFromSystemServer(); 389 } 390 } 391 392 /** 393 * @hide 394 */ 395 @TestApi getIgnoreSettingsWhitelist()396 public @NonNull String[] getIgnoreSettingsWhitelist() { 397 try { 398 return mService.getIgnoreSettingsWhitelist(); 399 } catch (RemoteException e) { 400 throw e.rethrowFromSystemServer(); 401 } 402 } 403 404 /** 405 * @hide - hide this constructor because it has a parameter 406 * of type ILocationManager, which is a system private class. The 407 * right way to create an instance of this class is using the 408 * factory Context.getSystemService. 409 */ LocationManager(@onNull Context context, @NonNull ILocationManager service)410 public LocationManager(@NonNull Context context, @NonNull ILocationManager service) { 411 mService = service; 412 mContext = context; 413 mGnssMeasurementCallbackTransport = 414 new GnssMeasurementCallbackTransport(mContext, mService); 415 mGnssNavigationMessageCallbackTransport = 416 new GnssNavigationMessageCallbackTransport(mContext, mService); 417 mBatchedLocationCallbackTransport = 418 new BatchedLocationCallbackTransport(mContext, mService); 419 420 } 421 createProvider(String name, ProviderProperties properties)422 private LocationProvider createProvider(String name, ProviderProperties properties) { 423 return new LocationProvider(name, properties); 424 } 425 426 /** 427 * Returns a list of the names of all known location providers. 428 * <p>All providers are returned, including ones that are not permitted to 429 * be accessed by the calling activity or are currently disabled. 430 * 431 * @return list of Strings containing names of the provider 432 */ getAllProviders()433 public @NonNull List<String> getAllProviders() { 434 try { 435 return mService.getAllProviders(); 436 } catch (RemoteException e) { 437 throw e.rethrowFromSystemServer(); 438 } 439 } 440 441 /** 442 * Returns a list of the names of location providers. 443 * 444 * @param enabledOnly if true then only the providers which are currently 445 * enabled are returned. 446 * @return list of Strings containing names of the providers 447 */ getProviders(boolean enabledOnly)448 public @NonNull List<String> getProviders(boolean enabledOnly) { 449 try { 450 return mService.getProviders(null, enabledOnly); 451 } catch (RemoteException e) { 452 throw e.rethrowFromSystemServer(); 453 } 454 } 455 456 /** 457 * Returns the information associated with the location provider of the 458 * given name, or null if no provider exists by that name. 459 * 460 * @param name the provider name 461 * @return a LocationProvider, or null 462 * 463 * @throws IllegalArgumentException if name is null or does not exist 464 * @throws SecurityException if the caller is not permitted to access the 465 * given provider. 466 */ getProvider(@onNull String name)467 public @Nullable LocationProvider getProvider(@NonNull String name) { 468 checkProvider(name); 469 try { 470 ProviderProperties properties = mService.getProviderProperties(name); 471 if (properties == null) { 472 return null; 473 } 474 return createProvider(name, properties); 475 } catch (RemoteException e) { 476 throw e.rethrowFromSystemServer(); 477 } 478 } 479 480 /** 481 * Returns a list of the names of LocationProviders that satisfy the given 482 * criteria, or null if none do. Only providers that are permitted to be 483 * accessed by the calling activity will be returned. 484 * 485 * @param criteria the criteria that the returned providers must match 486 * @param enabledOnly if true then only the providers which are currently 487 * enabled are returned. 488 * @return list of Strings containing names of the providers 489 */ getProviders(@onNull Criteria criteria, boolean enabledOnly)490 public @NonNull List<String> getProviders(@NonNull Criteria criteria, boolean enabledOnly) { 491 checkCriteria(criteria); 492 try { 493 return mService.getProviders(criteria, enabledOnly); 494 } catch (RemoteException e) { 495 throw e.rethrowFromSystemServer(); 496 } 497 } 498 499 /** 500 * Returns the name of the provider that best meets the given criteria. Only providers 501 * that are permitted to be accessed by the calling activity will be 502 * returned. If several providers meet the criteria, the one with the best 503 * accuracy is returned. If no provider meets the criteria, 504 * the criteria are loosened in the following sequence: 505 * 506 * <ul> 507 * <li> power requirement 508 * <li> accuracy 509 * <li> bearing 510 * <li> speed 511 * <li> altitude 512 * </ul> 513 * 514 * <p> Note that the requirement on monetary cost is not removed 515 * in this process. 516 * 517 * @param criteria the criteria that need to be matched 518 * @param enabledOnly if true then only a provider that is currently enabled is returned 519 * @return name of the provider that best matches the requirements 520 */ getBestProvider(@onNull Criteria criteria, boolean enabledOnly)521 public @Nullable String getBestProvider(@NonNull Criteria criteria, boolean enabledOnly) { 522 checkCriteria(criteria); 523 try { 524 return mService.getBestProvider(criteria, enabledOnly); 525 } catch (RemoteException e) { 526 throw e.rethrowFromSystemServer(); 527 } 528 } 529 530 /** 531 * Register for location updates using the named provider, and a 532 * pending intent. 533 * 534 * <p>See {@link #requestLocationUpdates(long, float, Criteria, PendingIntent)} 535 * for more detail on how to use this method. 536 * 537 * @param provider the name of the provider with which to register 538 * @param minTime minimum time interval between location updates, in milliseconds 539 * @param minDistance minimum distance between location updates, in meters 540 * @param listener a {@link LocationListener} whose 541 * {@link LocationListener#onLocationChanged} method will be called for 542 * each location update 543 * 544 * @throws IllegalArgumentException if provider is null or doesn't exist 545 * on this device 546 * @throws IllegalArgumentException if listener is null 547 * @throws RuntimeException if the calling thread has no Looper 548 * @throws SecurityException if no suitable permission is present 549 */ 550 @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}) requestLocationUpdates(@onNull String provider, long minTime, float minDistance, @NonNull LocationListener listener)551 public void requestLocationUpdates(@NonNull String provider, long minTime, float minDistance, 552 @NonNull LocationListener listener) { 553 checkProvider(provider); 554 checkListener(listener); 555 556 LocationRequest request = LocationRequest.createFromDeprecatedProvider( 557 provider, minTime, minDistance, false); 558 requestLocationUpdates(request, listener, null, null); 559 } 560 561 /** 562 * Register for location updates using the named provider, and a callback on 563 * the specified looper thread. 564 * 565 * <p>See {@link #requestLocationUpdates(long, float, Criteria, PendingIntent)} 566 * for more detail on how to use this method. 567 * 568 * @param provider the name of the provider with which to register 569 * @param minTime minimum time interval between location updates, in milliseconds 570 * @param minDistance minimum distance between location updates, in meters 571 * @param listener a {@link LocationListener} whose 572 * {@link LocationListener#onLocationChanged} method will be called for 573 * each location update 574 * @param looper a Looper object whose message queue will be used to 575 * implement the callback mechanism, or null to make callbacks on the calling 576 * thread 577 * 578 * @throws IllegalArgumentException if provider is null or doesn't exist 579 * @throws IllegalArgumentException if listener is null 580 * @throws SecurityException if no suitable permission is present 581 */ 582 @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}) requestLocationUpdates(@onNull String provider, long minTime, float minDistance, @NonNull LocationListener listener, @Nullable Looper looper)583 public void requestLocationUpdates(@NonNull String provider, long minTime, float minDistance, 584 @NonNull LocationListener listener, @Nullable Looper looper) { 585 checkProvider(provider); 586 checkListener(listener); 587 588 LocationRequest request = LocationRequest.createFromDeprecatedProvider( 589 provider, minTime, minDistance, false); 590 requestLocationUpdates(request, listener, looper, null); 591 } 592 593 /** 594 * Register for location updates using a Criteria, and a callback 595 * on the specified looper thread. 596 * 597 * <p>See {@link #requestLocationUpdates(long, float, Criteria, PendingIntent)} 598 * for more detail on how to use this method. 599 * 600 * @param minTime minimum time interval between location updates, in milliseconds 601 * @param minDistance minimum distance between location updates, in meters 602 * @param criteria contains parameters for the location manager to choose the 603 * appropriate provider and parameters to compute the location 604 * @param listener a {@link LocationListener} whose 605 * {@link LocationListener#onLocationChanged} method will be called for 606 * each location update 607 * @param looper a Looper object whose message queue will be used to 608 * implement the callback mechanism, or null to make callbacks on the calling 609 * thread 610 * 611 * @throws IllegalArgumentException if criteria is null 612 * @throws IllegalArgumentException if listener is null 613 * @throws SecurityException if no suitable permission is present 614 */ 615 @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}) requestLocationUpdates(long minTime, float minDistance, @NonNull Criteria criteria, @NonNull LocationListener listener, @Nullable Looper looper)616 public void requestLocationUpdates(long minTime, float minDistance, @NonNull Criteria criteria, 617 @NonNull LocationListener listener, @Nullable Looper looper) { 618 checkCriteria(criteria); 619 checkListener(listener); 620 621 LocationRequest request = LocationRequest.createFromDeprecatedCriteria( 622 criteria, minTime, minDistance, false); 623 requestLocationUpdates(request, listener, looper, null); 624 } 625 626 /** 627 * Register for location updates using the named provider, and a 628 * pending intent. 629 * 630 * <p>See {@link #requestLocationUpdates(long, float, Criteria, PendingIntent)} 631 * for more detail on how to use this method. 632 * 633 * @param provider the name of the provider with which to register 634 * @param minTime minimum time interval between location updates, in milliseconds 635 * @param minDistance minimum distance between location updates, in meters 636 * @param intent a {@link PendingIntent} to be sent for each location update 637 * 638 * @throws IllegalArgumentException if provider is null or doesn't exist 639 * on this device 640 * @throws IllegalArgumentException if intent is null 641 * @throws SecurityException if no suitable permission is present 642 */ 643 @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}) requestLocationUpdates(@onNull String provider, long minTime, float minDistance, @NonNull PendingIntent intent)644 public void requestLocationUpdates(@NonNull String provider, long minTime, float minDistance, 645 @NonNull PendingIntent intent) { 646 checkProvider(provider); 647 checkPendingIntent(intent); 648 649 LocationRequest request = LocationRequest.createFromDeprecatedProvider( 650 provider, minTime, minDistance, false); 651 requestLocationUpdates(request, null, null, intent); 652 } 653 654 /** 655 * Register for location updates using a Criteria and pending intent. 656 * 657 * <p>The <code>requestLocationUpdates()</code> and 658 * <code>requestSingleUpdate()</code> register the current activity to be 659 * updated periodically by the named provider, or by the provider matching 660 * the specified {@link Criteria}, with location and status updates. 661 * 662 * <p> It may take a while to receive the first location update. If 663 * an immediate location is required, applications may use the 664 * {@link #getLastKnownLocation(String)} method. 665 * 666 * <p> Location updates are received either by {@link LocationListener} 667 * callbacks, or by broadcast intents to a supplied {@link PendingIntent}. 668 * 669 * <p> If the caller supplied a pending intent, then location updates 670 * are sent with a key of {@link #KEY_LOCATION_CHANGED} and a 671 * {@link android.location.Location} value. 672 * 673 * <p> The location update interval can be controlled using the minTime parameter. 674 * The elapsed time between location updates will never be less than 675 * minTime, although it can be more depending on the Location Provider 676 * implementation and the update interval requested by other applications. 677 * 678 * <p> Choosing a sensible value for minTime is important to conserve 679 * battery life. Each location update requires power from 680 * GPS, WIFI, Cell and other radios. Select a minTime value as high as 681 * possible while still providing a reasonable user experience. 682 * If your application is not in the foreground and showing 683 * location to the user then your application should avoid using an active 684 * provider (such as {@link #NETWORK_PROVIDER} or {@link #GPS_PROVIDER}), 685 * but if you insist then select a minTime of 5 * 60 * 1000 (5 minutes) 686 * or greater. If your application is in the foreground and showing 687 * location to the user then it is appropriate to select a faster 688 * update interval. 689 * 690 * <p> The minDistance parameter can also be used to control the 691 * frequency of location updates. If it is greater than 0 then the 692 * location provider will only send your application an update when 693 * the location has changed by at least minDistance meters, AND 694 * at least minTime milliseconds have passed. However it is more 695 * difficult for location providers to save power using the minDistance 696 * parameter, so minTime should be the primary tool to conserving battery 697 * life. 698 * 699 * <p> If your application wants to passively observe location 700 * updates triggered by other applications, but not consume 701 * any additional power otherwise, then use the {@link #PASSIVE_PROVIDER} 702 * This provider does not actively turn on or modify active location 703 * providers, so you do not need to be as careful about minTime and 704 * minDistance. However if your application performs heavy work 705 * on a location update (such as network activity) then you should 706 * select non-zero values for minTime and/or minDistance to rate-limit 707 * your update frequency in the case another application enables a 708 * location provider with extremely fast updates. 709 * 710 * <p>In case the provider is disabled by the user, updates will stop, 711 * and a provider availability update will be sent. 712 * As soon as the provider is enabled again, 713 * location updates will immediately resume and a provider availability 714 * update sent. Providers can also send status updates, at any time, 715 * with extra's specific to the provider. If a callback was supplied 716 * then status and availability updates are via 717 * {@link LocationListener#onProviderDisabled}, 718 * {@link LocationListener#onProviderEnabled} or 719 * {@link LocationListener#onStatusChanged}. Alternately, if a 720 * pending intent was supplied then status and availability updates 721 * are broadcast intents with extra keys of 722 * {@link #KEY_PROVIDER_ENABLED} or {@link #KEY_STATUS_CHANGED}. 723 * 724 * <p> If a {@link LocationListener} is used but with no Looper specified 725 * then the calling thread must already 726 * be a {@link android.os.Looper} thread such as the main thread of the 727 * calling Activity. If a Looper is specified with a {@link LocationListener} 728 * then callbacks are made on the supplied Looper thread. 729 * 730 * <p> When location callbacks are invoked, the system will hold a wakelock 731 * on your application's behalf for some period of time, but not 732 * indefinitely. If your application requires a long running wakelock 733 * within the location callback, you should acquire it yourself. 734 * 735 * <p class="note"> Prior to Jellybean, the minTime parameter was 736 * only a hint, and some location provider implementations ignored it. 737 * From Jellybean and onwards it is mandatory for Android compatible 738 * devices to observe both the minTime and minDistance parameters. 739 * 740 * @param minTime minimum time interval between location updates, in milliseconds 741 * @param minDistance minimum distance between location updates, in meters 742 * @param criteria contains parameters for the location manager to choose the 743 * appropriate provider and parameters to compute the location 744 * @param intent a {@link PendingIntent} to be sent for each location update 745 * 746 * @throws IllegalArgumentException if criteria is null 747 * @throws IllegalArgumentException if intent is null 748 * @throws SecurityException if no suitable permission is present 749 */ 750 @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}) requestLocationUpdates(long minTime, float minDistance, @NonNull Criteria criteria, @NonNull PendingIntent intent)751 public void requestLocationUpdates(long minTime, float minDistance, @NonNull Criteria criteria, 752 @NonNull PendingIntent intent) { 753 checkCriteria(criteria); 754 checkPendingIntent(intent); 755 756 LocationRequest request = LocationRequest.createFromDeprecatedCriteria( 757 criteria, minTime, minDistance, false); 758 requestLocationUpdates(request, null, null, intent); 759 } 760 761 /** 762 * Register for a single location update using the named provider and 763 * a callback. 764 * 765 * <p>See {@link #requestLocationUpdates(long, float, Criteria, PendingIntent)} 766 * for more detail on how to use this method. 767 * 768 * @param provider the name of the provider with which to register 769 * @param listener a {@link LocationListener} whose 770 * {@link LocationListener#onLocationChanged} method will be called when 771 * the location update is available 772 * @param looper a Looper object whose message queue will be used to 773 * implement the callback mechanism, or null to make callbacks on the calling 774 * thread 775 * 776 * @throws IllegalArgumentException if provider is null or doesn't exist 777 * @throws IllegalArgumentException if listener is null 778 * @throws SecurityException if no suitable permission is present 779 */ 780 @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}) requestSingleUpdate( @onNull String provider, @NonNull LocationListener listener, @Nullable Looper looper)781 public void requestSingleUpdate( 782 @NonNull String provider, @NonNull LocationListener listener, @Nullable Looper looper) { 783 checkProvider(provider); 784 checkListener(listener); 785 786 LocationRequest request = LocationRequest.createFromDeprecatedProvider( 787 provider, 0, 0, true); 788 requestLocationUpdates(request, listener, looper, null); 789 } 790 791 /** 792 * Register for a single location update using a Criteria and 793 * a callback. 794 * 795 * <p>See {@link #requestLocationUpdates(long, float, Criteria, PendingIntent)} 796 * for more detail on how to use this method. 797 * 798 * @param criteria contains parameters for the location manager to choose the 799 * appropriate provider and parameters to compute the location 800 * @param listener a {@link LocationListener} whose 801 * {@link LocationListener#onLocationChanged} method will be called when 802 * the location update is available 803 * @param looper a Looper object whose message queue will be used to 804 * implement the callback mechanism, or null to make callbacks on the calling 805 * thread 806 * 807 * @throws IllegalArgumentException if criteria is null 808 * @throws IllegalArgumentException if listener is null 809 * @throws SecurityException if no suitable permission is present 810 */ 811 @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}) requestSingleUpdate( @onNull Criteria criteria, @NonNull LocationListener listener, @Nullable Looper looper)812 public void requestSingleUpdate( 813 @NonNull Criteria criteria, 814 @NonNull LocationListener listener, 815 @Nullable Looper looper) { 816 checkCriteria(criteria); 817 checkListener(listener); 818 819 LocationRequest request = LocationRequest.createFromDeprecatedCriteria( 820 criteria, 0, 0, true); 821 requestLocationUpdates(request, listener, looper, null); 822 } 823 824 /** 825 * Register for a single location update using a named provider and pending intent. 826 * 827 * <p>See {@link #requestLocationUpdates(long, float, Criteria, PendingIntent)} 828 * for more detail on how to use this method. 829 * 830 * @param provider the name of the provider with which to register 831 * @param intent a {@link PendingIntent} to be sent for the location update 832 * 833 * @throws IllegalArgumentException if provider is null or doesn't exist 834 * @throws IllegalArgumentException if intent is null 835 * @throws SecurityException if no suitable permission is present 836 */ 837 @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}) requestSingleUpdate(@onNull String provider, @NonNull PendingIntent intent)838 public void requestSingleUpdate(@NonNull String provider, @NonNull PendingIntent intent) { 839 checkProvider(provider); 840 checkPendingIntent(intent); 841 842 LocationRequest request = LocationRequest.createFromDeprecatedProvider( 843 provider, 0, 0, true); 844 requestLocationUpdates(request, null, null, intent); 845 } 846 847 /** 848 * Register for a single location update using a Criteria and pending intent. 849 * 850 * <p>See {@link #requestLocationUpdates(long, float, Criteria, PendingIntent)} 851 * for more detail on how to use this method. 852 * 853 * @param criteria contains parameters for the location manager to choose the 854 * appropriate provider and parameters to compute the location 855 * @param intent a {@link PendingIntent} to be sent for the location update 856 * 857 * @throws IllegalArgumentException if provider is null or doesn't exist 858 * @throws IllegalArgumentException if intent is null 859 * @throws SecurityException if no suitable permission is present 860 */ 861 @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}) requestSingleUpdate(@onNull Criteria criteria, @NonNull PendingIntent intent)862 public void requestSingleUpdate(@NonNull Criteria criteria, @NonNull PendingIntent intent) { 863 checkCriteria(criteria); 864 checkPendingIntent(intent); 865 866 LocationRequest request = LocationRequest.createFromDeprecatedCriteria( 867 criteria, 0, 0, true); 868 requestLocationUpdates(request, null, null, intent); 869 } 870 871 /** 872 * Register for fused location updates using a LocationRequest and callback. 873 * 874 * <p>Upon a location update, the system delivers the new {@link Location} to the 875 * provided {@link LocationListener}, by calling its {@link 876 * LocationListener#onLocationChanged} method.</p> 877 * 878 * <p>The system will automatically select and enable the best providers 879 * to compute a location for your application. It may use only passive 880 * locations, or just a single location source, or it may fuse together 881 * multiple location sources in order to produce the best possible 882 * result, depending on the quality of service requested in the 883 * {@link LocationRequest}. 884 * 885 * <p>LocationRequest can be null, in which case the system will choose 886 * default, low power parameters for location updates. You will occasionally 887 * receive location updates as available, without a major power impact on the 888 * system. If your application just needs an occasional location update 889 * without any strict demands, then pass a null LocationRequest. 890 * 891 * <p>Only one LocationRequest can be registered for each unique callback 892 * or pending intent. So a subsequent request with the same callback or 893 * pending intent will over-write the previous LocationRequest. 894 * 895 * <p> If a pending intent is supplied then location updates 896 * are sent with a key of {@link #KEY_LOCATION_CHANGED} and a 897 * {@link android.location.Location} value. If a callback is supplied 898 * then location updates are made using the 899 * {@link LocationListener#onLocationChanged} callback, on the specified 900 * Looper thread. If a {@link LocationListener} is used 901 * but with a null Looper then the calling thread must already 902 * be a {@link android.os.Looper} thread (such as the main thread) and 903 * callbacks will occur on this thread. 904 * 905 * <p> Provider status updates and availability updates are deprecated 906 * because the system is performing provider fusion on the applications 907 * behalf. So {@link LocationListener#onProviderDisabled}, 908 * {@link LocationListener#onProviderEnabled}, {@link LocationListener#onStatusChanged} 909 * will not be called, and intents with extra keys of 910 * {@link #KEY_PROVIDER_ENABLED} or {@link #KEY_STATUS_CHANGED} will not 911 * be received. 912 * 913 * <p> To unregister for Location updates, use: {@link #removeUpdates(LocationListener)}. 914 * 915 * @param request quality of service required, null for default low power 916 * @param listener a {@link LocationListener} whose 917 * {@link LocationListener#onLocationChanged} method will be called when 918 * the location update is available 919 * @param looper a Looper object whose message queue will be used to 920 * implement the callback mechanism, or null to make callbacks on the calling 921 * thread 922 * 923 * @throws IllegalArgumentException if listener is null 924 * @throws SecurityException if no suitable permission is present 925 * 926 * @hide 927 */ 928 @SystemApi 929 @TestApi 930 @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}) requestLocationUpdates( @onNull LocationRequest request, @NonNull LocationListener listener, @Nullable Looper looper)931 public void requestLocationUpdates( 932 @NonNull LocationRequest request, 933 @NonNull LocationListener listener, 934 @Nullable Looper looper) { 935 checkListener(listener); 936 requestLocationUpdates(request, listener, looper, null); 937 } 938 939 940 /** 941 * Register for fused location updates using a LocationRequest and a pending intent. 942 * 943 * <p>Upon a location update, the system delivers the new {@link Location} with your provided 944 * {@link PendingIntent}, as the value for {@link LocationManager#KEY_LOCATION_CHANGED} 945 * in the intent's extras.</p> 946 * 947 * <p> To unregister for Location updates, use: {@link #removeUpdates(PendingIntent)}. 948 * 949 * <p> See {@link #requestLocationUpdates(LocationRequest, LocationListener, Looper)} 950 * for more detail. 951 * 952 * @param request quality of service required, null for default low power 953 * @param intent a {@link PendingIntent} to be sent for the location update 954 * 955 * @throws IllegalArgumentException if intent is null 956 * @throws SecurityException if no suitable permission is present 957 * 958 * @hide 959 */ 960 @SystemApi 961 @TestApi 962 @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}) requestLocationUpdates( @onNull LocationRequest request, @NonNull PendingIntent intent)963 public void requestLocationUpdates( 964 @NonNull LocationRequest request, @NonNull PendingIntent intent) { 965 checkPendingIntent(intent); 966 requestLocationUpdates(request, null, null, intent); 967 } 968 969 /** 970 * Set the last known location with a new location. 971 * 972 * <p>A privileged client can inject a {@link Location} if it has a better estimate of what 973 * the recent location is. This is especially useful when the device boots up and the GPS 974 * chipset is in the process of getting the first fix. If the client has cached the location, 975 * it can inject the {@link Location}, so if an app requests for a {@link Location} from {@link 976 * #getLastKnownLocation(String)}, the location information is still useful before getting 977 * the first fix.</p> 978 * 979 * <p> Useful in products like Auto. 980 * 981 * @param newLocation newly available {@link Location} object 982 * @return true if update was successful, false if not 983 * 984 * @throws SecurityException if no suitable permission is present 985 * 986 * @hide 987 */ 988 @RequiresPermission(allOf = {LOCATION_HARDWARE, ACCESS_FINE_LOCATION}) injectLocation(@onNull Location newLocation)989 public boolean injectLocation(@NonNull Location newLocation) { 990 try { 991 return mService.injectLocation(newLocation); 992 } catch (RemoteException e) { 993 throw e.rethrowFromSystemServer(); 994 } 995 } 996 wrapListener(LocationListener listener, Looper looper)997 private ListenerTransport wrapListener(LocationListener listener, Looper looper) { 998 if (listener == null) return null; 999 synchronized (mListeners) { 1000 ListenerTransport transport = mListeners.get(listener); 1001 if (transport == null) { 1002 transport = new ListenerTransport(listener, looper); 1003 } 1004 mListeners.put(listener, transport); 1005 return transport; 1006 } 1007 } 1008 1009 @UnsupportedAppUsage requestLocationUpdates(LocationRequest request, LocationListener listener, Looper looper, PendingIntent intent)1010 private void requestLocationUpdates(LocationRequest request, LocationListener listener, 1011 Looper looper, PendingIntent intent) { 1012 1013 String packageName = mContext.getPackageName(); 1014 1015 // wrap the listener class 1016 ListenerTransport transport = wrapListener(listener, looper); 1017 1018 try { 1019 mService.requestLocationUpdates(request, transport, intent, packageName); 1020 } catch (RemoteException e) { 1021 throw e.rethrowFromSystemServer(); 1022 } 1023 } 1024 1025 /** 1026 * Removes all location updates for the specified LocationListener. 1027 * 1028 * <p>Following this call, updates will no longer 1029 * occur for this listener. 1030 * 1031 * @param listener listener object that no longer needs location updates 1032 * @throws IllegalArgumentException if listener is null 1033 */ removeUpdates(@onNull LocationListener listener)1034 public void removeUpdates(@NonNull LocationListener listener) { 1035 checkListener(listener); 1036 String packageName = mContext.getPackageName(); 1037 1038 ListenerTransport transport; 1039 synchronized (mListeners) { 1040 transport = mListeners.remove(listener); 1041 } 1042 if (transport == null) return; 1043 1044 try { 1045 mService.removeUpdates(transport, null, packageName); 1046 } catch (RemoteException e) { 1047 throw e.rethrowFromSystemServer(); 1048 } 1049 } 1050 1051 /** 1052 * Removes all location updates for the specified pending intent. 1053 * 1054 * <p>Following this call, updates will no longer for this pending intent. 1055 * 1056 * @param intent pending intent object that no longer needs location updates 1057 * @throws IllegalArgumentException if intent is null 1058 */ removeUpdates(@onNull PendingIntent intent)1059 public void removeUpdates(@NonNull PendingIntent intent) { 1060 checkPendingIntent(intent); 1061 String packageName = mContext.getPackageName(); 1062 1063 try { 1064 mService.removeUpdates(null, intent, packageName); 1065 } catch (RemoteException e) { 1066 throw e.rethrowFromSystemServer(); 1067 } 1068 } 1069 1070 /** 1071 * Set a proximity alert for the location given by the position 1072 * (latitude, longitude) and the given radius. 1073 * 1074 * <p> When the device 1075 * detects that it has entered or exited the area surrounding the 1076 * location, the given PendingIntent will be used to create an Intent 1077 * to be fired. 1078 * 1079 * <p> The fired Intent will have a boolean extra added with key 1080 * {@link #KEY_PROXIMITY_ENTERING}. If the value is true, the device is 1081 * entering the proximity region; if false, it is exiting. 1082 * 1083 * <p> Due to the approximate nature of position estimation, if the 1084 * device passes through the given area briefly, it is possible 1085 * that no Intent will be fired. Similarly, an Intent could be 1086 * fired if the device passes very close to the given area but 1087 * does not actually enter it. 1088 * 1089 * <p> After the number of milliseconds given by the expiration 1090 * parameter, the location manager will delete this proximity 1091 * alert and no longer monitor it. A value of -1 indicates that 1092 * there should be no expiration time. 1093 * 1094 * <p> Internally, this method uses both {@link #NETWORK_PROVIDER} 1095 * and {@link #GPS_PROVIDER}. 1096 * 1097 * <p>Before API version 17, this method could be used with 1098 * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} or 1099 * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}. 1100 * From API version 17 and onwards, this method requires 1101 * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} permission. 1102 * 1103 * @param latitude the latitude of the central point of the 1104 * alert region 1105 * @param longitude the longitude of the central point of the 1106 * alert region 1107 * @param radius the radius of the central point of the 1108 * alert region, in meters 1109 * @param expiration time for this proximity alert, in milliseconds, 1110 * or -1 to indicate no expiration 1111 * @param intent a PendingIntent that will be used to generate an Intent to 1112 * fire when entry to or exit from the alert region is detected 1113 * 1114 * @throws SecurityException if {@link android.Manifest.permission#ACCESS_FINE_LOCATION} 1115 * permission is not present 1116 */ 1117 @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}) addProximityAlert(double latitude, double longitude, float radius, long expiration, @NonNull PendingIntent intent)1118 public void addProximityAlert(double latitude, double longitude, float radius, long expiration, 1119 @NonNull PendingIntent intent) { 1120 checkPendingIntent(intent); 1121 if (expiration < 0) expiration = Long.MAX_VALUE; 1122 1123 Geofence fence = Geofence.createCircle(latitude, longitude, radius); 1124 LocationRequest request = new LocationRequest().setExpireIn(expiration); 1125 try { 1126 mService.requestGeofence(request, fence, intent, mContext.getPackageName()); 1127 } catch (RemoteException e) { 1128 throw e.rethrowFromSystemServer(); 1129 } 1130 } 1131 1132 /** 1133 * Add a geofence with the specified LocationRequest quality of service. 1134 * 1135 * <p> When the device 1136 * detects that it has entered or exited the area surrounding the 1137 * location, the given PendingIntent will be used to create an Intent 1138 * to be fired. 1139 * 1140 * <p> The fired Intent will have a boolean extra added with key 1141 * {@link #KEY_PROXIMITY_ENTERING}. If the value is true, the device is 1142 * entering the proximity region; if false, it is exiting. 1143 * 1144 * <p> The geofence engine fuses results from all location providers to 1145 * provide the best balance between accuracy and power. Applications 1146 * can choose the quality of service required using the 1147 * {@link LocationRequest} object. If it is null then a default, 1148 * low power geo-fencing implementation is used. It is possible to cross 1149 * a geo-fence without notification, but the system will do its best 1150 * to detect, using {@link LocationRequest} as a hint to trade-off 1151 * accuracy and power. 1152 * 1153 * <p> The power required by the geofence engine can depend on many factors, 1154 * such as quality and interval requested in {@link LocationRequest}, 1155 * distance to nearest geofence and current device velocity. 1156 * 1157 * @param request quality of service required, null for default low power 1158 * @param fence a geographical description of the geofence area 1159 * @param intent pending intent to receive geofence updates 1160 * 1161 * @throws IllegalArgumentException if fence is null 1162 * @throws IllegalArgumentException if intent is null 1163 * @throws SecurityException if {@link android.Manifest.permission#ACCESS_FINE_LOCATION} 1164 * permission is not present 1165 * 1166 * @hide 1167 */ 1168 @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}) addGeofence( @onNull LocationRequest request, @NonNull Geofence fence, @NonNull PendingIntent intent)1169 public void addGeofence( 1170 @NonNull LocationRequest request, 1171 @NonNull Geofence fence, 1172 @NonNull PendingIntent intent) { 1173 checkPendingIntent(intent); 1174 checkGeofence(fence); 1175 1176 try { 1177 mService.requestGeofence(request, fence, intent, mContext.getPackageName()); 1178 } catch (RemoteException e) { 1179 throw e.rethrowFromSystemServer(); 1180 } 1181 } 1182 1183 /** 1184 * Removes the proximity alert with the given PendingIntent. 1185 * 1186 * <p>Before API version 17, this method could be used with 1187 * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} or 1188 * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}. 1189 * From API version 17 and onwards, this method requires 1190 * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} permission. 1191 * 1192 * @param intent the PendingIntent that no longer needs to be notified of 1193 * proximity alerts 1194 * 1195 * @throws IllegalArgumentException if intent is null 1196 * @throws SecurityException if {@link android.Manifest.permission#ACCESS_FINE_LOCATION} 1197 * permission is not present 1198 */ removeProximityAlert(@onNull PendingIntent intent)1199 public void removeProximityAlert(@NonNull PendingIntent intent) { 1200 checkPendingIntent(intent); 1201 String packageName = mContext.getPackageName(); 1202 1203 try { 1204 mService.removeGeofence(null, intent, packageName); 1205 } catch (RemoteException e) { 1206 throw e.rethrowFromSystemServer(); 1207 } 1208 } 1209 1210 /** 1211 * Remove a single geofence. 1212 * 1213 * <p>This removes only the specified geofence associated with the 1214 * specified pending intent. All other geofences remain unchanged. 1215 * 1216 * @param fence a geofence previously passed to {@link #addGeofence} 1217 * @param intent a pending intent previously passed to {@link #addGeofence} 1218 * 1219 * @throws IllegalArgumentException if fence is null 1220 * @throws IllegalArgumentException if intent is null 1221 * @throws SecurityException if {@link android.Manifest.permission#ACCESS_FINE_LOCATION} 1222 * permission is not present 1223 * 1224 * @hide 1225 */ removeGeofence(@onNull Geofence fence, @NonNull PendingIntent intent)1226 public void removeGeofence(@NonNull Geofence fence, @NonNull PendingIntent intent) { 1227 checkPendingIntent(intent); 1228 checkGeofence(fence); 1229 String packageName = mContext.getPackageName(); 1230 1231 try { 1232 mService.removeGeofence(fence, intent, packageName); 1233 } catch (RemoteException e) { 1234 throw e.rethrowFromSystemServer(); 1235 } 1236 } 1237 1238 /** 1239 * Remove all geofences registered to the specified pending intent. 1240 * 1241 * @param intent a pending intent previously passed to {@link #addGeofence} 1242 * 1243 * @throws IllegalArgumentException if intent is null 1244 * @throws SecurityException if {@link android.Manifest.permission#ACCESS_FINE_LOCATION} 1245 * permission is not present 1246 * 1247 * @hide 1248 */ removeAllGeofences(@onNull PendingIntent intent)1249 public void removeAllGeofences(@NonNull PendingIntent intent) { 1250 checkPendingIntent(intent); 1251 String packageName = mContext.getPackageName(); 1252 1253 try { 1254 mService.removeGeofence(null, intent, packageName); 1255 } catch (RemoteException e) { 1256 throw e.rethrowFromSystemServer(); 1257 } 1258 } 1259 1260 /** 1261 * Returns the current enabled/disabled state of location. To listen for changes, see 1262 * {@link #MODE_CHANGED_ACTION}. 1263 * 1264 * @return true if location is enabled and false if location is disabled. 1265 */ isLocationEnabled()1266 public boolean isLocationEnabled() { 1267 return isLocationEnabledForUser(Process.myUserHandle()); 1268 } 1269 1270 /** 1271 * Returns the current enabled/disabled state of location. 1272 * 1273 * @param userHandle the user to query 1274 * @return true if location is enabled and false if location is disabled. 1275 * 1276 * @hide 1277 */ 1278 @SystemApi isLocationEnabledForUser(@onNull UserHandle userHandle)1279 public boolean isLocationEnabledForUser(@NonNull UserHandle userHandle) { 1280 try { 1281 return mService.isLocationEnabledForUser(userHandle.getIdentifier()); 1282 } catch (RemoteException e) { 1283 throw e.rethrowFromSystemServer(); 1284 } 1285 } 1286 1287 /** 1288 * Enables or disables the location setting. 1289 * 1290 * @param enabled true to enable location and false to disable location. 1291 * @param userHandle the user to set 1292 * 1293 * @hide 1294 */ 1295 @SystemApi 1296 @TestApi 1297 @RequiresPermission(WRITE_SECURE_SETTINGS) setLocationEnabledForUser(boolean enabled, @NonNull UserHandle userHandle)1298 public void setLocationEnabledForUser(boolean enabled, @NonNull UserHandle userHandle) { 1299 Settings.Secure.putIntForUser( 1300 mContext.getContentResolver(), 1301 Settings.Secure.LOCATION_MODE, 1302 enabled 1303 ? Settings.Secure.LOCATION_MODE_ON 1304 : Settings.Secure.LOCATION_MODE_OFF, 1305 userHandle.getIdentifier()); 1306 } 1307 1308 /** 1309 * Returns the current enabled/disabled status of the given provider. To listen for changes, see 1310 * {@link #PROVIDERS_CHANGED_ACTION}. 1311 * 1312 * Before API version {@link android.os.Build.VERSION_CODES#LOLLIPOP}, this method would throw 1313 * {@link SecurityException} if the location permissions were not sufficient to use the 1314 * specified provider. 1315 * 1316 * @param provider the name of the provider 1317 * @return true if the provider exists and is enabled 1318 * 1319 * @throws IllegalArgumentException if provider is null 1320 */ isProviderEnabled(@onNull String provider)1321 public boolean isProviderEnabled(@NonNull String provider) { 1322 return isProviderEnabledForUser(provider, Process.myUserHandle()); 1323 } 1324 1325 /** 1326 * Returns the current enabled/disabled status of the given provider and user. Callers should 1327 * prefer {@link #isLocationEnabledForUser(UserHandle)} unless they depend on provider-specific 1328 * APIs. 1329 * 1330 * Before API version {@link android.os.Build.VERSION_CODES#LOLLIPOP}, this method would throw 1331 * {@link SecurityException} if the location permissions were not sufficient to use the 1332 * specified provider. 1333 * 1334 * @param provider the name of the provider 1335 * @param userHandle the user to query 1336 * @return true if the provider exists and is enabled 1337 * 1338 * @throws IllegalArgumentException if provider is null 1339 * @hide 1340 */ 1341 @SystemApi isProviderEnabledForUser( @onNull String provider, @NonNull UserHandle userHandle)1342 public boolean isProviderEnabledForUser( 1343 @NonNull String provider, @NonNull UserHandle userHandle) { 1344 checkProvider(provider); 1345 1346 try { 1347 return mService.isProviderEnabledForUser(provider, userHandle.getIdentifier()); 1348 } catch (RemoteException e) { 1349 throw e.rethrowFromSystemServer(); 1350 } 1351 } 1352 1353 /** 1354 * Method for enabling or disabling a single location provider. This method is deprecated and 1355 * functions as a best effort. It should not be relied on in any meaningful sense as providers 1356 * may no longer be enabled or disabled by clients. 1357 * 1358 * @param provider the name of the provider 1359 * @param enabled true to enable the provider. false to disable the provider 1360 * @param userHandle the user to set 1361 * @return true if the value was set, false otherwise 1362 * 1363 * @throws IllegalArgumentException if provider is null 1364 * @deprecated Do not manipulate providers individually, use 1365 * {@link #setLocationEnabledForUser(boolean, UserHandle)} instead. 1366 * @hide 1367 */ 1368 @Deprecated 1369 @SystemApi 1370 @RequiresPermission(WRITE_SECURE_SETTINGS) setProviderEnabledForUser( @onNull String provider, boolean enabled, @NonNull UserHandle userHandle)1371 public boolean setProviderEnabledForUser( 1372 @NonNull String provider, boolean enabled, @NonNull UserHandle userHandle) { 1373 checkProvider(provider); 1374 1375 return Settings.Secure.putStringForUser( 1376 mContext.getContentResolver(), 1377 Settings.Secure.LOCATION_PROVIDERS_ALLOWED, 1378 (enabled ? "+" : "-") + provider, 1379 userHandle.getIdentifier()); 1380 } 1381 1382 /** 1383 * Get the last known location. 1384 * 1385 * <p>This location could be very old so use 1386 * {@link Location#getElapsedRealtimeNanos} to calculate its age. It can 1387 * also return null if no previous location is available. 1388 * 1389 * <p>Always returns immediately. 1390 * 1391 * @return The last known location, or null if not available 1392 * @throws SecurityException if no suitable permission is present 1393 * 1394 * @hide 1395 */ 1396 @Nullable getLastLocation()1397 public Location getLastLocation() { 1398 String packageName = mContext.getPackageName(); 1399 1400 try { 1401 return mService.getLastLocation(null, packageName); 1402 } catch (RemoteException e) { 1403 throw e.rethrowFromSystemServer(); 1404 } 1405 } 1406 1407 /** 1408 * Returns a Location indicating the data from the last known 1409 * location fix obtained from the given provider. 1410 * 1411 * <p> This can be done 1412 * without starting the provider. Note that this location could 1413 * be out-of-date, for example if the device was turned off and 1414 * moved to another location. 1415 * 1416 * <p> If the provider is currently disabled, null is returned. 1417 * 1418 * @param provider the name of the provider 1419 * @return the last known location for the provider, or null 1420 * 1421 * @throws SecurityException if no suitable permission is present 1422 * @throws IllegalArgumentException if provider is null or doesn't exist 1423 */ 1424 @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}) 1425 @Nullable getLastKnownLocation(@onNull String provider)1426 public Location getLastKnownLocation(@NonNull String provider) { 1427 checkProvider(provider); 1428 String packageName = mContext.getPackageName(); 1429 LocationRequest request = LocationRequest.createFromDeprecatedProvider( 1430 provider, 0, 0, true); 1431 1432 try { 1433 return mService.getLastLocation(request, packageName); 1434 } catch (RemoteException e) { 1435 throw e.rethrowFromSystemServer(); 1436 } 1437 } 1438 1439 /** 1440 * Creates a mock location provider and adds it to the set of active providers. 1441 * 1442 * @param name the provider name 1443 * 1444 * @throws SecurityException if {@link android.app.AppOpsManager#OPSTR_MOCK_LOCATION 1445 * mock location app op} is not set to {@link android.app.AppOpsManager#MODE_ALLOWED 1446 * allowed} for your app. 1447 * @throws IllegalArgumentException if a provider with the given name already exists 1448 */ addTestProvider( @onNull String name, boolean requiresNetwork, boolean requiresSatellite, boolean requiresCell, boolean hasMonetaryCost, boolean supportsAltitude, boolean supportsSpeed, boolean supportsBearing, int powerRequirement, int accuracy)1449 public void addTestProvider( 1450 @NonNull String name, boolean requiresNetwork, boolean requiresSatellite, 1451 boolean requiresCell, boolean hasMonetaryCost, boolean supportsAltitude, 1452 boolean supportsSpeed, boolean supportsBearing, int powerRequirement, int accuracy) { 1453 ProviderProperties properties = new ProviderProperties(requiresNetwork, 1454 requiresSatellite, requiresCell, hasMonetaryCost, supportsAltitude, supportsSpeed, 1455 supportsBearing, powerRequirement, accuracy); 1456 if (name.matches(LocationProvider.BAD_CHARS_REGEX)) { 1457 throw new IllegalArgumentException("provider name contains illegal character: " + name); 1458 } 1459 1460 try { 1461 mService.addTestProvider(name, properties, mContext.getOpPackageName()); 1462 } catch (RemoteException e) { 1463 throw e.rethrowFromSystemServer(); 1464 } 1465 } 1466 1467 /** 1468 * Removes the mock location provider with the given name. 1469 * 1470 * @param provider the provider name 1471 * 1472 * @throws SecurityException if {@link android.app.AppOpsManager#OPSTR_MOCK_LOCATION 1473 * mock location app op} is not set to {@link android.app.AppOpsManager#MODE_ALLOWED 1474 * allowed} for your app. 1475 * @throws IllegalArgumentException if no provider with the given name exists 1476 */ removeTestProvider(@onNull String provider)1477 public void removeTestProvider(@NonNull String provider) { 1478 try { 1479 mService.removeTestProvider(provider, mContext.getOpPackageName()); 1480 } catch (RemoteException e) { 1481 throw e.rethrowFromSystemServer(); 1482 } 1483 } 1484 1485 /** 1486 * Sets a mock location for the given provider. 1487 * <p>This location will be used in place of any actual location from the provider. 1488 * The location object must have a minimum number of fields set to be 1489 * considered a valid LocationProvider Location, as per documentation 1490 * on {@link Location} class. 1491 * 1492 * @param provider the provider name 1493 * @param loc the mock location 1494 * 1495 * @throws SecurityException if {@link android.app.AppOpsManager#OPSTR_MOCK_LOCATION 1496 * mock location app op} is not set to {@link android.app.AppOpsManager#MODE_ALLOWED 1497 * allowed} for your app. 1498 * @throws IllegalArgumentException if no provider with the given name exists 1499 * @throws IllegalArgumentException if the location is incomplete 1500 */ setTestProviderLocation(@onNull String provider, @NonNull Location loc)1501 public void setTestProviderLocation(@NonNull String provider, @NonNull Location loc) { 1502 if (!loc.isComplete()) { 1503 IllegalArgumentException e = new IllegalArgumentException( 1504 "Incomplete location object, missing timestamp or accuracy? " + loc); 1505 if (mContext.getApplicationInfo().targetSdkVersion <= Build.VERSION_CODES.JELLY_BEAN) { 1506 // just log on old platform (for backwards compatibility) 1507 Log.w(TAG, e); 1508 loc.makeComplete(); 1509 } else { 1510 // really throw it! 1511 throw e; 1512 } 1513 } 1514 1515 try { 1516 mService.setTestProviderLocation(provider, loc, mContext.getOpPackageName()); 1517 } catch (RemoteException e) { 1518 throw e.rethrowFromSystemServer(); 1519 } 1520 } 1521 1522 /** 1523 * Removes any mock location associated with the given provider. 1524 * 1525 * @param provider the provider name 1526 * 1527 * @throws SecurityException if {@link android.app.AppOpsManager#OPSTR_MOCK_LOCATION 1528 * mock location app op} is not set to {@link android.app.AppOpsManager#MODE_ALLOWED 1529 * allowed} for your app. 1530 * @throws IllegalArgumentException if no provider with the given name exists 1531 * 1532 * @deprecated This function has always been a no-op, and may be removed in the future. 1533 */ 1534 @Deprecated clearTestProviderLocation(@onNull String provider)1535 public void clearTestProviderLocation(@NonNull String provider) {} 1536 1537 /** 1538 * Sets a mock enabled value for the given provider. This value will be used in place 1539 * of any actual value from the provider. 1540 * 1541 * @param provider the provider name 1542 * @param enabled the mock enabled value 1543 * 1544 * @throws SecurityException if {@link android.app.AppOpsManager#OPSTR_MOCK_LOCATION 1545 * mock location app op} is not set to {@link android.app.AppOpsManager#MODE_ALLOWED 1546 * allowed} for your app. 1547 * @throws IllegalArgumentException if no provider with the given name exists 1548 */ setTestProviderEnabled(@onNull String provider, boolean enabled)1549 public void setTestProviderEnabled(@NonNull String provider, boolean enabled) { 1550 try { 1551 mService.setTestProviderEnabled(provider, enabled, mContext.getOpPackageName()); 1552 } catch (RemoteException e) { 1553 throw e.rethrowFromSystemServer(); 1554 } 1555 } 1556 1557 /** 1558 * Removes any mock enabled value associated with the given provider. 1559 * 1560 * @param provider the provider name 1561 * 1562 * @throws SecurityException if {@link android.app.AppOpsManager#OPSTR_MOCK_LOCATION 1563 * mock location app op} is not set to {@link android.app.AppOpsManager#MODE_ALLOWED 1564 * allowed} for your app. 1565 * @throws IllegalArgumentException if no provider with the given name exists 1566 * 1567 * @deprecated Use {@link #setTestProviderEnabled(String, boolean)} instead. 1568 */ 1569 @Deprecated clearTestProviderEnabled(@onNull String provider)1570 public void clearTestProviderEnabled(@NonNull String provider) { 1571 setTestProviderEnabled(provider, false); 1572 } 1573 1574 /** 1575 * This method has no effect as provider status has been deprecated and is no longer supported. 1576 * 1577 * @param provider the provider name 1578 * @param status the mock status 1579 * @param extras a Bundle containing mock extras 1580 * @param updateTime the mock update time 1581 * 1582 * @throws SecurityException if {@link android.app.AppOpsManager#OPSTR_MOCK_LOCATION 1583 * mock location app op} is not set to {@link android.app.AppOpsManager#MODE_ALLOWED 1584 * allowed} for your app. 1585 * @throws IllegalArgumentException if no provider with the given name exists 1586 * 1587 * @deprecated This method has no effect. 1588 */ 1589 @Deprecated setTestProviderStatus( @onNull String provider, int status, @Nullable Bundle extras, long updateTime)1590 public void setTestProviderStatus( 1591 @NonNull String provider, int status, @Nullable Bundle extras, long updateTime) { 1592 try { 1593 mService.setTestProviderStatus(provider, status, extras, updateTime, 1594 mContext.getOpPackageName()); 1595 } catch (RemoteException e) { 1596 throw e.rethrowFromSystemServer(); 1597 } 1598 } 1599 1600 /** 1601 * This method has no effect as provider status has been deprecated and is no longer supported. 1602 * 1603 * @param provider the provider name 1604 * @throws SecurityException if {@link android.app.AppOpsManager#OPSTR_MOCK_LOCATION 1605 * mock location app op} is not set to {@link android.app.AppOpsManager#MODE_ALLOWED 1606 * allowed} for your app. 1607 * @throws IllegalArgumentException if no provider with the given name exists 1608 * 1609 * @deprecated This method has no effect. 1610 */ 1611 @Deprecated clearTestProviderStatus(@onNull String provider)1612 public void clearTestProviderStatus(@NonNull String provider) { 1613 setTestProviderStatus(provider, LocationProvider.AVAILABLE, null, 0L); 1614 } 1615 1616 /** 1617 * Get the last list of {@link LocationRequest}s sent to the provider. 1618 * 1619 * @hide 1620 */ 1621 @TestApi 1622 @NonNull getTestProviderCurrentRequests(String providerName)1623 public List<LocationRequest> getTestProviderCurrentRequests(String providerName) { 1624 checkProvider(providerName); 1625 try { 1626 return mService.getTestProviderCurrentRequests(providerName, 1627 mContext.getOpPackageName()); 1628 } catch (RemoteException e) { 1629 throw e.rethrowFromSystemServer(); 1630 } 1631 } 1632 1633 // --- GPS-specific support --- 1634 1635 // This class is used to send Gnss status events to the client's specific thread. 1636 private class GnssStatusListenerTransport extends IGnssStatusListener.Stub { 1637 1638 private final GnssStatus.Callback mGnssCallback; 1639 private final OnNmeaMessageListener mGnssNmeaListener; 1640 1641 private class GnssHandler extends Handler { GnssHandler(Handler handler)1642 GnssHandler(Handler handler) { 1643 super(handler != null ? handler.getLooper() : Looper.myLooper()); 1644 } 1645 1646 @Override handleMessage(Message msg)1647 public void handleMessage(Message msg) { 1648 switch (msg.what) { 1649 case NMEA_RECEIVED: 1650 synchronized (mNmeaBuffer) { 1651 for (Nmea nmea : mNmeaBuffer) { 1652 mGnssNmeaListener.onNmeaMessage(nmea.mNmea, nmea.mTimestamp); 1653 } 1654 mNmeaBuffer.clear(); 1655 } 1656 break; 1657 case GNSS_EVENT_STARTED: 1658 mGnssCallback.onStarted(); 1659 break; 1660 case GNSS_EVENT_STOPPED: 1661 mGnssCallback.onStopped(); 1662 break; 1663 case GNSS_EVENT_FIRST_FIX: 1664 mGnssCallback.onFirstFix(mTimeToFirstFix); 1665 break; 1666 case GNSS_EVENT_SATELLITE_STATUS: 1667 mGnssCallback.onSatelliteStatusChanged(mGnssStatus); 1668 break; 1669 default: 1670 break; 1671 } 1672 } 1673 } 1674 1675 private final Handler mGnssHandler; 1676 1677 private static final int NMEA_RECEIVED = 1; 1678 private static final int GNSS_EVENT_STARTED = 2; 1679 private static final int GNSS_EVENT_STOPPED = 3; 1680 private static final int GNSS_EVENT_FIRST_FIX = 4; 1681 private static final int GNSS_EVENT_SATELLITE_STATUS = 5; 1682 1683 private class Nmea { 1684 long mTimestamp; 1685 String mNmea; 1686 Nmea(long timestamp, String nmea)1687 Nmea(long timestamp, String nmea) { 1688 mTimestamp = timestamp; 1689 mNmea = nmea; 1690 } 1691 } 1692 private final ArrayList<Nmea> mNmeaBuffer; 1693 GnssStatusListenerTransport(GnssStatus.Callback callback, Handler handler)1694 GnssStatusListenerTransport(GnssStatus.Callback callback, Handler handler) { 1695 mGnssCallback = callback; 1696 mGnssHandler = new GnssHandler(handler); 1697 mGnssNmeaListener = null; 1698 mNmeaBuffer = null; 1699 } 1700 GnssStatusListenerTransport(OnNmeaMessageListener listener, Handler handler)1701 GnssStatusListenerTransport(OnNmeaMessageListener listener, Handler handler) { 1702 mGnssCallback = null; 1703 mGnssHandler = new GnssHandler(handler); 1704 mGnssNmeaListener = listener; 1705 mNmeaBuffer = new ArrayList<>(); 1706 } 1707 GnssStatusListenerTransport(GpsStatus.Listener listener, Handler handler)1708 GnssStatusListenerTransport(GpsStatus.Listener listener, Handler handler) { 1709 mGnssHandler = new GnssHandler(handler); 1710 mNmeaBuffer = null; 1711 mGnssCallback = listener != null ? new GnssStatus.Callback() { 1712 @Override 1713 public void onStarted() { 1714 listener.onGpsStatusChanged(GpsStatus.GPS_EVENT_STARTED); 1715 } 1716 1717 @Override 1718 public void onStopped() { 1719 listener.onGpsStatusChanged(GpsStatus.GPS_EVENT_STOPPED); 1720 } 1721 1722 @Override 1723 public void onFirstFix(int ttff) { 1724 listener.onGpsStatusChanged(GpsStatus.GPS_EVENT_FIRST_FIX); 1725 } 1726 1727 @Override 1728 public void onSatelliteStatusChanged(GnssStatus status) { 1729 listener.onGpsStatusChanged(GpsStatus.GPS_EVENT_SATELLITE_STATUS); 1730 } 1731 } : null; 1732 mGnssNmeaListener = null; 1733 } 1734 1735 @Override onGnssStarted()1736 public void onGnssStarted() { 1737 if (mGnssCallback != null) { 1738 mGnssHandler.obtainMessage(GNSS_EVENT_STARTED).sendToTarget(); 1739 } 1740 } 1741 1742 @Override onGnssStopped()1743 public void onGnssStopped() { 1744 if (mGnssCallback != null) { 1745 mGnssHandler.obtainMessage(GNSS_EVENT_STOPPED).sendToTarget(); 1746 } 1747 } 1748 1749 @Override onFirstFix(int ttff)1750 public void onFirstFix(int ttff) { 1751 if (mGnssCallback != null) { 1752 mTimeToFirstFix = ttff; 1753 mGnssHandler.obtainMessage(GNSS_EVENT_FIRST_FIX).sendToTarget(); 1754 } 1755 } 1756 1757 @Override onSvStatusChanged(int svCount, int[] prnWithFlags, float[] cn0s, float[] elevations, float[] azimuths, float[] carrierFreqs)1758 public void onSvStatusChanged(int svCount, int[] prnWithFlags, 1759 float[] cn0s, float[] elevations, float[] azimuths, float[] carrierFreqs) { 1760 if (mGnssCallback != null) { 1761 mGnssStatus = new GnssStatus(svCount, prnWithFlags, cn0s, elevations, azimuths, 1762 carrierFreqs); 1763 1764 mGnssHandler.removeMessages(GNSS_EVENT_SATELLITE_STATUS); 1765 mGnssHandler.obtainMessage(GNSS_EVENT_SATELLITE_STATUS).sendToTarget(); 1766 } 1767 } 1768 1769 @Override onNmeaReceived(long timestamp, String nmea)1770 public void onNmeaReceived(long timestamp, String nmea) { 1771 if (mGnssNmeaListener != null) { 1772 synchronized (mNmeaBuffer) { 1773 mNmeaBuffer.add(new Nmea(timestamp, nmea)); 1774 } 1775 1776 mGnssHandler.removeMessages(NMEA_RECEIVED); 1777 mGnssHandler.obtainMessage(NMEA_RECEIVED).sendToTarget(); 1778 } 1779 } 1780 } 1781 1782 /** 1783 * Adds a GPS status listener. 1784 * 1785 * @param listener GPS status listener object to register 1786 * 1787 * @return true if the listener was successfully added 1788 * 1789 * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present 1790 * @deprecated use {@link #registerGnssStatusCallback(GnssStatus.Callback)} instead. 1791 */ 1792 @Deprecated 1793 @RequiresPermission(ACCESS_FINE_LOCATION) addGpsStatusListener(GpsStatus.Listener listener)1794 public boolean addGpsStatusListener(GpsStatus.Listener listener) { 1795 boolean result; 1796 1797 if (mGpsStatusListeners.get(listener) != null) { 1798 return true; 1799 } 1800 try { 1801 GnssStatusListenerTransport transport = new GnssStatusListenerTransport(listener, null); 1802 result = mService.registerGnssStatusCallback(transport, mContext.getPackageName()); 1803 if (result) { 1804 mGpsStatusListeners.put(listener, transport); 1805 } 1806 } catch (RemoteException e) { 1807 throw e.rethrowFromSystemServer(); 1808 } 1809 1810 return result; 1811 } 1812 1813 /** 1814 * Removes a GPS status listener. 1815 * 1816 * @param listener GPS status listener object to remove 1817 * @deprecated use {@link #unregisterGnssStatusCallback(GnssStatus.Callback)} instead. 1818 */ 1819 @Deprecated removeGpsStatusListener(GpsStatus.Listener listener)1820 public void removeGpsStatusListener(GpsStatus.Listener listener) { 1821 try { 1822 GnssStatusListenerTransport transport = mGpsStatusListeners.remove(listener); 1823 if (transport != null) { 1824 mService.unregisterGnssStatusCallback(transport); 1825 } 1826 } catch (RemoteException e) { 1827 throw e.rethrowFromSystemServer(); 1828 } 1829 } 1830 1831 /** 1832 * Registers a GNSS status callback. 1833 * 1834 * @param callback GNSS status callback object to register 1835 * 1836 * @return true if the listener was successfully added 1837 * 1838 * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present 1839 */ 1840 @RequiresPermission(ACCESS_FINE_LOCATION) registerGnssStatusCallback(@onNull GnssStatus.Callback callback)1841 public boolean registerGnssStatusCallback(@NonNull GnssStatus.Callback callback) { 1842 return registerGnssStatusCallback(callback, null); 1843 } 1844 1845 /** 1846 * Registers a GNSS status callback. 1847 * 1848 * @param callback GNSS status callback object to register 1849 * @param handler the handler that the callback runs on. 1850 * 1851 * @return true if the listener was successfully added 1852 * 1853 * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present 1854 */ 1855 @RequiresPermission(ACCESS_FINE_LOCATION) registerGnssStatusCallback( @onNull GnssStatus.Callback callback, @Nullable Handler handler)1856 public boolean registerGnssStatusCallback( 1857 @NonNull GnssStatus.Callback callback, @Nullable Handler handler) { 1858 boolean result; 1859 synchronized (mGnssStatusListeners) { 1860 if (mGnssStatusListeners.get(callback) != null) { 1861 return true; 1862 } 1863 try { 1864 GnssStatusListenerTransport transport = 1865 new GnssStatusListenerTransport(callback, handler); 1866 result = mService.registerGnssStatusCallback(transport, mContext.getPackageName()); 1867 if (result) { 1868 mGnssStatusListeners.put(callback, transport); 1869 } 1870 } catch (RemoteException e) { 1871 throw e.rethrowFromSystemServer(); 1872 } 1873 } 1874 1875 return result; 1876 } 1877 1878 /** 1879 * Removes a GNSS status callback. 1880 * 1881 * @param callback GNSS status callback object to remove 1882 */ unregisterGnssStatusCallback(@onNull GnssStatus.Callback callback)1883 public void unregisterGnssStatusCallback(@NonNull GnssStatus.Callback callback) { 1884 synchronized (mGnssStatusListeners) { 1885 try { 1886 GnssStatusListenerTransport transport = mGnssStatusListeners.remove(callback); 1887 if (transport != null) { 1888 mService.unregisterGnssStatusCallback(transport); 1889 } 1890 } catch (RemoteException e) { 1891 throw e.rethrowFromSystemServer(); 1892 } 1893 } 1894 } 1895 1896 /** 1897 * Adds an NMEA listener. 1898 * 1899 * @param listener a {@link GpsStatus.NmeaListener} object to register 1900 * 1901 * @return true if the listener was successfully added 1902 * 1903 * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present 1904 * @deprecated use {@link #addNmeaListener(OnNmeaMessageListener)} instead. 1905 * @removed 1906 */ 1907 @Deprecated 1908 @RequiresPermission(ACCESS_FINE_LOCATION) addNmeaListener(GpsStatus.NmeaListener listener)1909 public boolean addNmeaListener(GpsStatus.NmeaListener listener) { 1910 return false; 1911 } 1912 1913 /** 1914 * Removes an NMEA listener. 1915 * 1916 * @param listener a {@link GpsStatus.NmeaListener} object to remove 1917 * @deprecated use {@link #removeNmeaListener(OnNmeaMessageListener)} instead. 1918 * @removed 1919 */ 1920 @Deprecated removeNmeaListener(GpsStatus.NmeaListener listener)1921 public void removeNmeaListener(GpsStatus.NmeaListener listener) {} 1922 1923 /** 1924 * Adds an NMEA listener. 1925 * 1926 * @param listener a {@link OnNmeaMessageListener} object to register 1927 * 1928 * @return true if the listener was successfully added 1929 * 1930 * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present 1931 */ 1932 @RequiresPermission(ACCESS_FINE_LOCATION) addNmeaListener(@onNull OnNmeaMessageListener listener)1933 public boolean addNmeaListener(@NonNull OnNmeaMessageListener listener) { 1934 return addNmeaListener(listener, null); 1935 } 1936 1937 /** 1938 * Adds an NMEA listener. 1939 * 1940 * @param listener a {@link OnNmeaMessageListener} object to register 1941 * @param handler the handler that the listener runs on. 1942 * 1943 * @return true if the listener was successfully added 1944 * 1945 * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present 1946 */ 1947 @RequiresPermission(ACCESS_FINE_LOCATION) addNmeaListener( @onNull OnNmeaMessageListener listener, @Nullable Handler handler)1948 public boolean addNmeaListener( 1949 @NonNull OnNmeaMessageListener listener, @Nullable Handler handler) { 1950 boolean result; 1951 1952 if (mGnssNmeaListeners.get(listener) != null) { 1953 // listener is already registered 1954 return true; 1955 } 1956 try { 1957 GnssStatusListenerTransport transport = 1958 new GnssStatusListenerTransport(listener, handler); 1959 result = mService.registerGnssStatusCallback(transport, mContext.getPackageName()); 1960 if (result) { 1961 mGnssNmeaListeners.put(listener, transport); 1962 } 1963 } catch (RemoteException e) { 1964 throw e.rethrowFromSystemServer(); 1965 } 1966 1967 return result; 1968 } 1969 1970 /** 1971 * Removes an NMEA listener. 1972 * 1973 * @param listener a {@link OnNmeaMessageListener} object to remove 1974 */ removeNmeaListener(@onNull OnNmeaMessageListener listener)1975 public void removeNmeaListener(@NonNull OnNmeaMessageListener listener) { 1976 try { 1977 GnssStatusListenerTransport transport = mGnssNmeaListeners.remove(listener); 1978 if (transport != null) { 1979 mService.unregisterGnssStatusCallback(transport); 1980 } 1981 } catch (RemoteException e) { 1982 throw e.rethrowFromSystemServer(); 1983 } 1984 } 1985 1986 /** 1987 * No-op method to keep backward-compatibility. 1988 * Don't use it. Use {@link #registerGnssMeasurementsCallback} instead. 1989 * @hide 1990 * @deprecated Not supported anymore. 1991 * @removed 1992 */ 1993 @Deprecated 1994 @SystemApi 1995 @SuppressLint("Doclava125") addGpsMeasurementListener(GpsMeasurementsEvent.Listener listener)1996 public boolean addGpsMeasurementListener(GpsMeasurementsEvent.Listener listener) { 1997 return false; 1998 } 1999 2000 /** 2001 * Registers a GPS Measurement callback. 2002 * 2003 * @param callback a {@link GnssMeasurementsEvent.Callback} object to register. 2004 * @return {@code true} if the callback was added successfully, {@code false} otherwise. 2005 */ 2006 @RequiresPermission(ACCESS_FINE_LOCATION) registerGnssMeasurementsCallback( @onNull GnssMeasurementsEvent.Callback callback)2007 public boolean registerGnssMeasurementsCallback( 2008 @NonNull GnssMeasurementsEvent.Callback callback) { 2009 return registerGnssMeasurementsCallback(callback, null); 2010 } 2011 2012 /** 2013 * Registers a GPS Measurement callback. 2014 * 2015 * @param callback a {@link GnssMeasurementsEvent.Callback} object to register. 2016 * @param handler the handler that the callback runs on. 2017 * @return {@code true} if the callback was added successfully, {@code false} otherwise. 2018 */ 2019 @RequiresPermission(ACCESS_FINE_LOCATION) registerGnssMeasurementsCallback( @onNull GnssMeasurementsEvent.Callback callback, @Nullable Handler handler)2020 public boolean registerGnssMeasurementsCallback( 2021 @NonNull GnssMeasurementsEvent.Callback callback, @Nullable Handler handler) { 2022 return mGnssMeasurementCallbackTransport.add(callback, handler); 2023 } 2024 2025 /** 2026 * Injects GNSS measurement corrections into the GNSS chipset. 2027 * 2028 * @param measurementCorrections a {@link GnssMeasurementCorrections} object with the GNSS 2029 * measurement corrections to be injected into the GNSS chipset. 2030 * @hide 2031 */ 2032 @SystemApi 2033 @RequiresPermission(ACCESS_FINE_LOCATION) injectGnssMeasurementCorrections( @onNull GnssMeasurementCorrections measurementCorrections)2034 public void injectGnssMeasurementCorrections( 2035 @NonNull GnssMeasurementCorrections measurementCorrections) { 2036 try { 2037 mGnssMeasurementCallbackTransport.injectGnssMeasurementCorrections( 2038 measurementCorrections); 2039 } catch (RemoteException e) { 2040 throw e.rethrowFromSystemServer(); 2041 } 2042 } 2043 2044 /** 2045 * Returns the supported capabilities of the GNSS chipset. 2046 * 2047 * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present. 2048 * 2049 * @hide 2050 */ 2051 @SystemApi 2052 @RequiresPermission(ACCESS_FINE_LOCATION) getGnssCapabilities()2053 public @NonNull GnssCapabilities getGnssCapabilities() { 2054 try { 2055 long gnssCapabilities = mGnssMeasurementCallbackTransport.getGnssCapabilities(); 2056 if (gnssCapabilities == GnssCapabilities.INVALID_CAPABILITIES) { 2057 gnssCapabilities = 0L; 2058 } 2059 return GnssCapabilities.of(gnssCapabilities); 2060 } catch (RemoteException e) { 2061 throw e.rethrowFromSystemServer(); 2062 } 2063 } 2064 2065 /** 2066 * No-op method to keep backward-compatibility. Don't use it. Use {@link 2067 * #unregisterGnssMeasurementsCallback} instead. 2068 * 2069 * @hide 2070 * @deprecated use {@link #unregisterGnssMeasurementsCallback(GnssMeasurementsEvent.Callback)} 2071 * instead. 2072 * @removed 2073 */ 2074 @Deprecated 2075 @SystemApi 2076 @SuppressLint("Doclava125") removeGpsMeasurementListener(GpsMeasurementsEvent.Listener listener)2077 public void removeGpsMeasurementListener(GpsMeasurementsEvent.Listener listener) {} 2078 2079 /** 2080 * Unregisters a GPS Measurement callback. 2081 * 2082 * @param callback a {@link GnssMeasurementsEvent.Callback} object to remove. 2083 */ unregisterGnssMeasurementsCallback( @onNull GnssMeasurementsEvent.Callback callback)2084 public void unregisterGnssMeasurementsCallback( 2085 @NonNull GnssMeasurementsEvent.Callback callback) { 2086 mGnssMeasurementCallbackTransport.remove(callback); 2087 } 2088 2089 /** 2090 * No-op method to keep backward-compatibility. 2091 * Don't use it. Use {@link #registerGnssNavigationMessageCallback} instead. 2092 * @hide 2093 * @deprecated Not supported anymore. 2094 * @removed 2095 */ 2096 @Deprecated 2097 @SystemApi 2098 @SuppressLint("Doclava125") addGpsNavigationMessageListener(GpsNavigationMessageEvent.Listener listener)2099 public boolean addGpsNavigationMessageListener(GpsNavigationMessageEvent.Listener listener) { 2100 return false; 2101 } 2102 2103 /** 2104 * No-op method to keep backward-compatibility. 2105 * Don't use it. Use {@link #unregisterGnssNavigationMessageCallback} instead. 2106 * @hide 2107 * @deprecated use 2108 * {@link #unregisterGnssNavigationMessageCallback(GnssNavigationMessage.Callback)} 2109 * instead 2110 * @removed 2111 */ 2112 @Deprecated 2113 @SystemApi 2114 @SuppressLint("Doclava125") removeGpsNavigationMessageListener(GpsNavigationMessageEvent.Listener listener)2115 public void removeGpsNavigationMessageListener(GpsNavigationMessageEvent.Listener listener) {} 2116 2117 /** 2118 * Registers a GNSS Navigation Message callback. 2119 * 2120 * @param callback a {@link GnssNavigationMessage.Callback} object to register. 2121 * @return {@code true} if the callback was added successfully, {@code false} otherwise. 2122 */ registerGnssNavigationMessageCallback( @onNull GnssNavigationMessage.Callback callback)2123 public boolean registerGnssNavigationMessageCallback( 2124 @NonNull GnssNavigationMessage.Callback callback) { 2125 return registerGnssNavigationMessageCallback(callback, null); 2126 } 2127 2128 /** 2129 * Registers a GNSS Navigation Message callback. 2130 * 2131 * @param callback a {@link GnssNavigationMessage.Callback} object to register. 2132 * @param handler the handler that the callback runs on. 2133 * @return {@code true} if the callback was added successfully, {@code false} otherwise. 2134 */ 2135 @RequiresPermission(ACCESS_FINE_LOCATION) registerGnssNavigationMessageCallback( @onNull GnssNavigationMessage.Callback callback, @Nullable Handler handler)2136 public boolean registerGnssNavigationMessageCallback( 2137 @NonNull GnssNavigationMessage.Callback callback, @Nullable Handler handler) { 2138 return mGnssNavigationMessageCallbackTransport.add(callback, handler); 2139 } 2140 2141 /** 2142 * Unregisters a GNSS Navigation Message callback. 2143 * 2144 * @param callback a {@link GnssNavigationMessage.Callback} object to remove. 2145 */ unregisterGnssNavigationMessageCallback( @onNull GnssNavigationMessage.Callback callback)2146 public void unregisterGnssNavigationMessageCallback( 2147 @NonNull GnssNavigationMessage.Callback callback) { 2148 mGnssNavigationMessageCallbackTransport.remove(callback); 2149 } 2150 2151 /** 2152 * Retrieves information about the current status of the GPS engine. 2153 * This should only be called from the {@link GpsStatus.Listener#onGpsStatusChanged} 2154 * callback to ensure that the data is copied atomically. 2155 * 2156 * The caller may either pass in a {@link GpsStatus} object to set with the latest 2157 * status information, or pass null to create a new {@link GpsStatus} object. 2158 * 2159 * @param status object containing GPS status details, or null. 2160 * @return status object containing updated GPS status. 2161 */ 2162 @Deprecated 2163 @RequiresPermission(ACCESS_FINE_LOCATION) getGpsStatus(@ullable GpsStatus status)2164 public @Nullable GpsStatus getGpsStatus(@Nullable GpsStatus status) { 2165 if (status == null) { 2166 status = new GpsStatus(); 2167 } 2168 // When mGnssStatus is null, that means that this method is called outside 2169 // onGpsStatusChanged(). Return an empty status to maintain backwards compatibility. 2170 if (mGnssStatus != null) { 2171 status.setStatus(mGnssStatus, mTimeToFirstFix); 2172 } 2173 return status; 2174 } 2175 2176 /** 2177 * Returns the model year of the GNSS hardware and software build. 2178 * 2179 * <p> More details, such as build date, may be available in {@link #getGnssHardwareModelName()}. 2180 * 2181 * <p> May return 0 if the model year is less than 2016. 2182 */ getGnssYearOfHardware()2183 public int getGnssYearOfHardware() { 2184 try { 2185 return mService.getGnssYearOfHardware(); 2186 } catch (RemoteException e) { 2187 throw e.rethrowFromSystemServer(); 2188 } 2189 } 2190 2191 /** 2192 * Returns the Model Name (including Vendor and Hardware/Software Version) of the GNSS hardware 2193 * driver. 2194 * 2195 * <p> No device-specific serial number or ID is returned from this API. 2196 * 2197 * <p> Will return null when the GNSS hardware abstraction layer does not support providing 2198 * this value. 2199 */ 2200 @Nullable getGnssHardwareModelName()2201 public String getGnssHardwareModelName() { 2202 try { 2203 return mService.getGnssHardwareModelName(); 2204 } catch (RemoteException e) { 2205 throw e.rethrowFromSystemServer(); 2206 } 2207 } 2208 2209 /** 2210 * Returns the batch size (in number of Location objects) that are supported by the batching 2211 * interface. 2212 * 2213 * @return Maximum number of location objects that can be returned 2214 * @hide 2215 */ 2216 @SystemApi 2217 @RequiresPermission(Manifest.permission.LOCATION_HARDWARE) getGnssBatchSize()2218 public int getGnssBatchSize() { 2219 try { 2220 return mService.getGnssBatchSize(mContext.getPackageName()); 2221 } catch (RemoteException e) { 2222 throw e.rethrowFromSystemServer(); 2223 } 2224 } 2225 2226 /** 2227 * Start hardware-batching of GNSS locations. This API is primarily used when the AP is 2228 * asleep and the device can batch GNSS locations in the hardware. 2229 * 2230 * Note this is designed (as was the fused location interface before it) for a single user 2231 * SystemApi - requests are not consolidated. Care should be taken when the System switches 2232 * users that may have different batching requests, to stop hardware batching for one user, and 2233 * restart it for the next. 2234 * 2235 * @param periodNanos Time interval, in nanoseconds, that the GNSS locations are requested 2236 * within the batch 2237 * @param wakeOnFifoFull True if the hardware batching should flush the locations in a 2238 * a callback to the listener, when it's internal buffer is full. If 2239 * set to false, the oldest location information is, instead, 2240 * dropped when the buffer is full. 2241 * @param callback The listener on which to return the batched locations 2242 * @param handler The handler on which to process the callback 2243 * 2244 * @return True if batching was successfully started 2245 * @hide 2246 */ 2247 @SystemApi 2248 @RequiresPermission(Manifest.permission.LOCATION_HARDWARE) registerGnssBatchedLocationCallback(long periodNanos, boolean wakeOnFifoFull, @NonNull BatchedLocationCallback callback, @Nullable Handler handler)2249 public boolean registerGnssBatchedLocationCallback(long periodNanos, boolean wakeOnFifoFull, 2250 @NonNull BatchedLocationCallback callback, @Nullable Handler handler) { 2251 mBatchedLocationCallbackTransport.add(callback, handler); 2252 2253 try { 2254 return mService.startGnssBatch(periodNanos, wakeOnFifoFull, mContext.getPackageName()); 2255 } catch (RemoteException e) { 2256 throw e.rethrowFromSystemServer(); 2257 } 2258 } 2259 2260 /** 2261 * Flush the batched GNSS locations. 2262 * All GNSS locations currently ready in the batch are returned via the callback sent in 2263 * startGnssBatch(), and the buffer containing the batched locations is cleared. 2264 * 2265 * @hide 2266 */ 2267 @SystemApi 2268 @RequiresPermission(Manifest.permission.LOCATION_HARDWARE) flushGnssBatch()2269 public void flushGnssBatch() { 2270 try { 2271 mService.flushGnssBatch(mContext.getPackageName()); 2272 } catch (RemoteException e) { 2273 throw e.rethrowFromSystemServer(); 2274 } 2275 } 2276 2277 /** 2278 * Stop batching locations. This API is primarily used when the AP is 2279 * asleep and the device can batch locations in the hardware. 2280 * 2281 * @param callback the specific callback class to remove from the transport layer 2282 * 2283 * @return True if batching was successfully started 2284 * @hide 2285 */ 2286 @SystemApi 2287 @RequiresPermission(Manifest.permission.LOCATION_HARDWARE) unregisterGnssBatchedLocationCallback( @onNull BatchedLocationCallback callback)2288 public boolean unregisterGnssBatchedLocationCallback( 2289 @NonNull BatchedLocationCallback callback) { 2290 2291 mBatchedLocationCallbackTransport.remove(callback); 2292 2293 try { 2294 return mService.stopGnssBatch(); 2295 } catch (RemoteException e) { 2296 throw e.rethrowFromSystemServer(); 2297 } 2298 } 2299 2300 /** 2301 * Sends additional commands to a location provider. 2302 * Can be used to support provider specific extensions to the Location Manager API 2303 * 2304 * @param provider name of the location provider. 2305 * @param command name of the command to send to the provider. 2306 * @param extras optional arguments for the command (or null). 2307 * The provider may optionally fill the extras Bundle with results from the command. 2308 * 2309 * @return true if the command succeeds. 2310 */ sendExtraCommand( @onNull String provider, @NonNull String command, @Nullable Bundle extras)2311 public boolean sendExtraCommand( 2312 @NonNull String provider, @NonNull String command, @Nullable Bundle extras) { 2313 try { 2314 return mService.sendExtraCommand(provider, command, extras); 2315 } catch (RemoteException e) { 2316 throw e.rethrowFromSystemServer(); 2317 } 2318 } 2319 2320 /** 2321 * Used by NetInitiatedActivity to report user response 2322 * for network initiated GPS fix requests. 2323 * 2324 * @hide 2325 */ 2326 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) sendNiResponse(int notifId, int userResponse)2327 public boolean sendNiResponse(int notifId, int userResponse) { 2328 try { 2329 return mService.sendNiResponse(notifId, userResponse); 2330 } catch (RemoteException e) { 2331 throw e.rethrowFromSystemServer(); 2332 } 2333 } 2334 checkProvider(String provider)2335 private static void checkProvider(String provider) { 2336 if (provider == null) { 2337 throw new IllegalArgumentException("invalid provider: " + provider); 2338 } 2339 } 2340 checkCriteria(Criteria criteria)2341 private static void checkCriteria(Criteria criteria) { 2342 if (criteria == null) { 2343 throw new IllegalArgumentException("invalid criteria: " + criteria); 2344 } 2345 } 2346 checkListener(LocationListener listener)2347 private static void checkListener(LocationListener listener) { 2348 if (listener == null) { 2349 throw new IllegalArgumentException("invalid listener: " + listener); 2350 } 2351 } 2352 checkPendingIntent(PendingIntent intent)2353 private void checkPendingIntent(PendingIntent intent) { 2354 if (intent == null) { 2355 throw new IllegalArgumentException("invalid pending intent: " + intent); 2356 } 2357 if (!intent.isTargetedToPackage()) { 2358 IllegalArgumentException e = new IllegalArgumentException( 2359 "pending intent must be targeted to package"); 2360 if (mContext.getApplicationInfo().targetSdkVersion > Build.VERSION_CODES.JELLY_BEAN) { 2361 throw e; 2362 } else { 2363 Log.w(TAG, e); 2364 } 2365 } 2366 } 2367 checkGeofence(Geofence fence)2368 private static void checkGeofence(Geofence fence) { 2369 if (fence == null) { 2370 throw new IllegalArgumentException("invalid geofence: " + fence); 2371 } 2372 } 2373 2374 /** 2375 * Returns true if the given package name matches a location provider package, and false 2376 * otherwise. 2377 * 2378 * @hide 2379 */ 2380 @SystemApi isProviderPackage(@onNull String packageName)2381 public boolean isProviderPackage(@NonNull String packageName) { 2382 try { 2383 return mService.isProviderPackage(packageName); 2384 } catch (RemoteException e) { 2385 e.rethrowFromSystemServer(); 2386 return false; 2387 } 2388 } 2389 2390 /** 2391 * Set the extra location controller package for location services on the device. 2392 * 2393 * @hide 2394 */ 2395 @SystemApi 2396 @RequiresPermission(Manifest.permission.LOCATION_HARDWARE) setExtraLocationControllerPackage(@ullable String packageName)2397 public void setExtraLocationControllerPackage(@Nullable String packageName) { 2398 try { 2399 mService.setExtraLocationControllerPackage(packageName); 2400 } catch (RemoteException e) { 2401 e.rethrowFromSystemServer(); 2402 } 2403 } 2404 2405 /** 2406 * Set the extra location controller package for location services on the device. 2407 * 2408 * @removed 2409 * @deprecated Use {@link #setExtraLocationControllerPackage} instead. 2410 * @hide 2411 */ 2412 @Deprecated 2413 @SystemApi 2414 @RequiresPermission(Manifest.permission.LOCATION_HARDWARE) setLocationControllerExtraPackage(String packageName)2415 public void setLocationControllerExtraPackage(String packageName) { 2416 try { 2417 mService.setExtraLocationControllerPackage(packageName); 2418 } catch (RemoteException e) { 2419 e.rethrowFromSystemServer(); 2420 } 2421 } 2422 2423 /** 2424 * Returns the extra location controller package on the device. 2425 * 2426 * @hide 2427 */ 2428 @SystemApi getExtraLocationControllerPackage()2429 public @Nullable String getExtraLocationControllerPackage() { 2430 try { 2431 return mService.getExtraLocationControllerPackage(); 2432 } catch (RemoteException e) { 2433 e.rethrowFromSystemServer(); 2434 return null; 2435 } 2436 } 2437 2438 /** 2439 * Set whether the extra location controller package is currently enabled on the device. 2440 * 2441 * @removed 2442 * @deprecated Use {@link #setExtraLocationControllerPackageEnabled} instead. 2443 * @hide 2444 */ 2445 @SystemApi 2446 @Deprecated 2447 @RequiresPermission(Manifest.permission.LOCATION_HARDWARE) setLocationControllerExtraPackageEnabled(boolean enabled)2448 public void setLocationControllerExtraPackageEnabled(boolean enabled) { 2449 try { 2450 mService.setExtraLocationControllerPackageEnabled(enabled); 2451 } catch (RemoteException e) { 2452 e.rethrowFromSystemServer(); 2453 } 2454 } 2455 2456 /** 2457 * Set whether the extra location controller package is currently enabled on the device. 2458 * 2459 * @hide 2460 */ 2461 @SystemApi 2462 @RequiresPermission(Manifest.permission.LOCATION_HARDWARE) setExtraLocationControllerPackageEnabled(boolean enabled)2463 public void setExtraLocationControllerPackageEnabled(boolean enabled) { 2464 try { 2465 mService.setExtraLocationControllerPackageEnabled(enabled); 2466 } catch (RemoteException e) { 2467 e.rethrowFromSystemServer(); 2468 } 2469 } 2470 2471 /** 2472 * Returns whether extra location controller package is currently enabled on the device. 2473 * 2474 * @hide 2475 */ 2476 @SystemApi isExtraLocationControllerPackageEnabled()2477 public boolean isExtraLocationControllerPackageEnabled() { 2478 try { 2479 return mService.isExtraLocationControllerPackageEnabled(); 2480 } catch (RemoteException e) { 2481 e.rethrowFromSystemServer(); 2482 return false; 2483 } 2484 } 2485 2486 } 2487