LocationManagerService.java revision 98cb66797422c4ccdee6f1a07636146d784a471b
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 17package com.android.server; 18 19import java.io.BufferedReader; 20import java.io.File; 21import java.io.FileDescriptor; 22import java.io.FileReader; 23import java.io.FileWriter; 24import java.io.IOException; 25import java.io.PrintWriter; 26import java.util.ArrayList; 27import java.util.HashMap; 28import java.util.HashSet; 29import java.util.List; 30import java.util.Map; 31import java.util.Observable; 32import java.util.Observer; 33import java.util.Set; 34import java.util.regex.Pattern; 35 36import android.app.AlarmManager; 37import android.app.PendingIntent; 38import android.content.BroadcastReceiver; 39import android.content.ContentQueryMap; 40import android.content.ContentResolver; 41import android.content.Context; 42import android.content.Intent; 43import android.content.IntentFilter; 44import android.content.pm.PackageManager; 45import android.database.Cursor; 46import android.location.Address; 47import android.location.IGeocodeProvider; 48import android.location.IGpsStatusListener; 49import android.location.ILocationCollector; 50import android.location.ILocationListener; 51import android.location.ILocationManager; 52import android.location.ILocationProvider; 53import android.location.Location; 54import android.location.LocationManager; 55import android.location.LocationProvider; 56import android.location.LocationProviderImpl; 57import android.net.ConnectivityManager; 58import android.net.Uri; 59import android.net.wifi.WifiManager; 60import android.os.Binder; 61import android.os.Bundle; 62import android.os.Handler; 63import android.os.IBinder; 64import android.os.Message; 65import android.os.PowerManager; 66import android.os.Process; 67import android.os.RemoteException; 68import android.os.SystemClock; 69import android.provider.Settings; 70import android.telephony.TelephonyManager; 71import android.util.Config; 72import android.util.Log; 73import android.util.PrintWriterPrinter; 74import android.util.SparseIntArray; 75 76import com.android.internal.location.GpsLocationProvider; 77import com.android.internal.location.LocationProviderProxy; 78import com.android.internal.location.MockProvider; 79import com.android.internal.location.TrackProvider; 80import com.android.server.am.BatteryStatsService; 81 82/** 83 * The service class that manages LocationProviders and issues location 84 * updates and alerts. 85 * 86 * {@hide} 87 */ 88public class LocationManagerService extends ILocationManager.Stub { 89 private static final String TAG = "LocationManagerService"; 90 private static final boolean LOCAL_LOGV = false; 91 92 // Minimum time interval between last known location writes, in milliseconds. 93 private static final long MIN_LAST_KNOWN_LOCATION_TIME = 60L * 1000L; 94 95 // Max time to hold wake lock for, in milliseconds. 96 private static final long MAX_TIME_FOR_WAKE_LOCK = 60 * 1000L; 97 98 // Time to wait after releasing a wake lock for clients to process location update, 99 // in milliseconds. 100 private static final long TIME_AFTER_WAKE_LOCK = 2 * 1000L; 101 102 // The last time a location was written, by provider name. 103 private HashMap<String,Long> mLastWriteTime = new HashMap<String,Long>(); 104 105 private static final Pattern PATTERN_COMMA = Pattern.compile(","); 106 107 private static final String ACCESS_FINE_LOCATION = 108 android.Manifest.permission.ACCESS_FINE_LOCATION; 109 private static final String ACCESS_COARSE_LOCATION = 110 android.Manifest.permission.ACCESS_COARSE_LOCATION; 111 private static final String ACCESS_MOCK_LOCATION = 112 android.Manifest.permission.ACCESS_MOCK_LOCATION; 113 private static final String ACCESS_LOCATION_EXTRA_COMMANDS = 114 android.Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS; 115 116 // Set of providers that are explicitly enabled 117 private final Set<String> mEnabledProviders = new HashSet<String>(); 118 119 // Set of providers that are explicitly disabled 120 private final Set<String> mDisabledProviders = new HashSet<String>(); 121 122 // Locations, status values, and extras for mock providers 123 private final HashMap<String,MockProvider> mMockProviders = new HashMap<String,MockProvider>(); 124 125 private static boolean sProvidersLoaded = false; 126 127 private final Context mContext; 128 private GpsLocationProvider mGpsLocationProvider; 129 private LocationProviderProxy mNetworkLocationProvider; 130 private IGeocodeProvider mGeocodeProvider; 131 private LocationWorkerHandler mLocationHandler; 132 133 // Handler messages 134 private static final int MESSAGE_LOCATION_CHANGED = 1; 135 private static final int MESSAGE_ACQUIRE_WAKE_LOCK = 2; 136 private static final int MESSAGE_RELEASE_WAKE_LOCK = 3; 137 138 // Alarm manager and wakelock variables 139 private final static String ALARM_INTENT = "com.android.location.ALARM_INTENT"; 140 private final static String WAKELOCK_KEY = "LocationManagerService"; 141 private final static String WIFILOCK_KEY = "LocationManagerService"; 142 private AlarmManager mAlarmManager; 143 private long mAlarmInterval = 0; 144 private boolean mScreenOn = true; 145 private PowerManager.WakeLock mWakeLock = null; 146 private WifiManager.WifiLock mWifiLock = null; 147 private long mWakeLockAcquireTime = 0; 148 private boolean mWakeLockGpsReceived = true; 149 private boolean mWakeLockNetworkReceived = true; 150 private boolean mWifiWakeLockAcquired = false; 151 private boolean mCellWakeLockAcquired = false; 152 153 /** 154 * List of all receivers. 155 */ 156 private final HashMap<Object, Receiver> mReceivers = new HashMap<Object, Receiver>(); 157 158 /** 159 * Object used internally for synchronization 160 */ 161 private final Object mLock = new Object(); 162 163 /** 164 * Mapping from provider name to all its UpdateRecords 165 */ 166 private final HashMap<String,ArrayList<UpdateRecord>> mRecordsByProvider = 167 new HashMap<String,ArrayList<UpdateRecord>>(); 168 169 // Proximity listeners 170 private Receiver mProximityListener = null; 171 private HashMap<PendingIntent,ProximityAlert> mProximityAlerts = 172 new HashMap<PendingIntent,ProximityAlert>(); 173 private HashSet<ProximityAlert> mProximitiesEntered = 174 new HashSet<ProximityAlert>(); 175 176 // Last known location for each provider 177 private HashMap<String,Location> mLastKnownLocation = 178 new HashMap<String,Location>(); 179 180 // Last known cell service state 181 private TelephonyManager mTelephonyManager; 182 183 // Location collector 184 private ILocationCollector mCollector; 185 186 // Wifi Manager 187 private WifiManager mWifiManager; 188 189 private int mNetworkState = LocationProvider.TEMPORARILY_UNAVAILABLE; 190 191 // for Settings change notification 192 private ContentQueryMap mSettings; 193 194 /** 195 * A wrapper class holding either an ILocationListener or a PendingIntent to receive 196 * location updates. 197 */ 198 private final class Receiver implements IBinder.DeathRecipient { 199 final ILocationListener mListener; 200 final PendingIntent mPendingIntent; 201 final Object mKey; 202 final HashMap<String,UpdateRecord> mUpdateRecords = new HashMap<String,UpdateRecord>(); 203 204 Receiver(ILocationListener listener) { 205 mListener = listener; 206 mPendingIntent = null; 207 mKey = listener.asBinder(); 208 } 209 210 Receiver(PendingIntent intent) { 211 mPendingIntent = intent; 212 mListener = null; 213 mKey = intent; 214 } 215 216 @Override 217 public boolean equals(Object otherObj) { 218 if (otherObj instanceof Receiver) { 219 return mKey.equals( 220 ((Receiver)otherObj).mKey); 221 } 222 return false; 223 } 224 225 @Override 226 public int hashCode() { 227 return mKey.hashCode(); 228 } 229 230 231 @Override 232 public String toString() { 233 if (mListener != null) { 234 return "Receiver{" 235 + Integer.toHexString(System.identityHashCode(this)) 236 + " Listener " + mKey + "}"; 237 } else { 238 return "Receiver{" 239 + Integer.toHexString(System.identityHashCode(this)) 240 + " Intent " + mKey + "}"; 241 } 242 } 243 244 public boolean isListener() { 245 return mListener != null; 246 } 247 248 public boolean isPendingIntent() { 249 return mPendingIntent != null; 250 } 251 252 public ILocationListener getListener() { 253 if (mListener != null) { 254 return mListener; 255 } 256 throw new IllegalStateException("Request for non-existent listener"); 257 } 258 259 public PendingIntent getPendingIntent() { 260 if (mPendingIntent != null) { 261 return mPendingIntent; 262 } 263 throw new IllegalStateException("Request for non-existent intent"); 264 } 265 266 public boolean callStatusChangedLocked(String provider, int status, Bundle extras) { 267 if (mListener != null) { 268 try { 269 mListener.onStatusChanged(provider, status, extras); 270 } catch (RemoteException e) { 271 return false; 272 } 273 } else { 274 Intent statusChanged = new Intent(); 275 statusChanged.putExtras(extras); 276 statusChanged.putExtra(LocationManager.KEY_STATUS_CHANGED, status); 277 try { 278 mPendingIntent.send(mContext, 0, statusChanged, null, null); 279 } catch (PendingIntent.CanceledException e) { 280 return false; 281 } 282 } 283 return true; 284 } 285 286 public boolean callLocationChangedLocked(Location location) { 287 if (mListener != null) { 288 try { 289 mListener.onLocationChanged(location); 290 } catch (RemoteException e) { 291 return false; 292 } 293 } else { 294 Intent locationChanged = new Intent(); 295 locationChanged.putExtra(LocationManager.KEY_LOCATION_CHANGED, location); 296 try { 297 mPendingIntent.send(mContext, 0, locationChanged, null, null); 298 } catch (PendingIntent.CanceledException e) { 299 return false; 300 } 301 } 302 return true; 303 } 304 305 public void binderDied() { 306 if (LOCAL_LOGV) { 307 Log.v(TAG, "Location listener died"); 308 } 309 synchronized (mLock) { 310 removeUpdatesLocked(this); 311 } 312 } 313 } 314 315 private final class SettingsObserver implements Observer { 316 public void update(Observable o, Object arg) { 317 synchronized (mLock) { 318 updateProvidersLocked(); 319 } 320 } 321 } 322 323 private Location readLastKnownLocationLocked(String provider) { 324 Location location = null; 325 String s = null; 326 try { 327 File f = new File(LocationManager.SYSTEM_DIR + "/location." 328 + provider); 329 if (!f.exists()) { 330 return null; 331 } 332 BufferedReader reader = new BufferedReader(new FileReader(f), 256); 333 s = reader.readLine(); 334 } catch (IOException e) { 335 Log.w(TAG, "Unable to read last known location", e); 336 } 337 338 if (s == null) { 339 return null; 340 } 341 try { 342 String[] tokens = PATTERN_COMMA.split(s); 343 int idx = 0; 344 long time = Long.parseLong(tokens[idx++]); 345 double latitude = Double.parseDouble(tokens[idx++]); 346 double longitude = Double.parseDouble(tokens[idx++]); 347 double altitude = Double.parseDouble(tokens[idx++]); 348 float bearing = Float.parseFloat(tokens[idx++]); 349 float speed = Float.parseFloat(tokens[idx++]); 350 351 location = new Location(provider); 352 location.setTime(time); 353 location.setLatitude(latitude); 354 location.setLongitude(longitude); 355 location.setAltitude(altitude); 356 location.setBearing(bearing); 357 location.setSpeed(speed); 358 } catch (NumberFormatException nfe) { 359 Log.e(TAG, "NumberFormatException reading last known location", nfe); 360 return null; 361 } 362 363 return location; 364 } 365 366 private void writeLastKnownLocationLocked(String provider, 367 Location location) { 368 long now = SystemClock.elapsedRealtime(); 369 Long last = mLastWriteTime.get(provider); 370 if ((last != null) 371 && (now - last.longValue() < MIN_LAST_KNOWN_LOCATION_TIME)) { 372 return; 373 } 374 mLastWriteTime.put(provider, now); 375 376 StringBuilder sb = new StringBuilder(100); 377 sb.append(location.getTime()); 378 sb.append(','); 379 sb.append(location.getLatitude()); 380 sb.append(','); 381 sb.append(location.getLongitude()); 382 sb.append(','); 383 sb.append(location.getAltitude()); 384 sb.append(','); 385 sb.append(location.getBearing()); 386 sb.append(','); 387 sb.append(location.getSpeed()); 388 389 FileWriter writer = null; 390 try { 391 File d = new File(LocationManager.SYSTEM_DIR); 392 if (!d.exists()) { 393 if (!d.mkdirs()) { 394 Log.w(TAG, "Unable to create directory to write location"); 395 return; 396 } 397 } 398 File f = new File(LocationManager.SYSTEM_DIR + "/location." + provider); 399 writer = new FileWriter(f); 400 writer.write(sb.toString()); 401 } catch (IOException e) { 402 Log.w(TAG, "Unable to write location", e); 403 } finally { 404 if (writer != null) { 405 try { 406 writer.close(); 407 } catch (IOException e) { 408 Log.w(TAG, "Exception closing file", e); 409 } 410 } 411 } 412 } 413 414 /** 415 * Load providers from /data/location/<provider_name>/ 416 * class 417 * kml 418 * nmea 419 * track 420 * location 421 * properties 422 */ 423 private void loadProviders() { 424 synchronized (mLock) { 425 if (sProvidersLoaded) { 426 return; 427 } 428 429 // Load providers 430 loadProvidersLocked(); 431 sProvidersLoaded = true; 432 } 433 } 434 435 private void loadProvidersLocked() { 436 try { 437 _loadProvidersLocked(); 438 } catch (Exception e) { 439 Log.e(TAG, "Exception loading providers:", e); 440 } 441 } 442 443 private void _loadProvidersLocked() { 444 // Attempt to load "real" providers first 445 if (GpsLocationProvider.isSupported()) { 446 // Create a gps location provider 447 mGpsLocationProvider = new GpsLocationProvider(mContext, this); 448 LocationProviderImpl.addProvider(mGpsLocationProvider); 449 } 450 451 // Load fake providers if real providers are not available 452 File f = new File(LocationManager.PROVIDER_DIR); 453 if (f.isDirectory()) { 454 File[] subdirs = f.listFiles(); 455 for (int i = 0; i < subdirs.length; i++) { 456 if (!subdirs[i].isDirectory()) { 457 continue; 458 } 459 460 String name = subdirs[i].getName(); 461 462 if (LOCAL_LOGV) { 463 Log.v(TAG, "Found dir " + subdirs[i].getAbsolutePath()); 464 Log.v(TAG, "name = " + name); 465 } 466 467 // Don't create a fake provider if a real provider exists 468 if (LocationProviderImpl.getProvider(name) == null) { 469 LocationProviderImpl provider = null; 470 try { 471 File classFile = new File(subdirs[i], "class"); 472 // Look for a 'class' file 473 provider = LocationProviderImpl.loadFromClass(classFile); 474 475 // Look for an 'kml', 'nmea', or 'track' file 476 if (provider == null) { 477 // Load properties from 'properties' file, if present 478 File propertiesFile = new File(subdirs[i], "properties"); 479 480 if (propertiesFile.exists()) { 481 provider = new TrackProvider(name, this); 482 ((TrackProvider)provider).readProperties(propertiesFile); 483 484 File kmlFile = new File(subdirs[i], "kml"); 485 if (kmlFile.exists()) { 486 ((TrackProvider) provider).readKml(kmlFile); 487 } else { 488 File nmeaFile = new File(subdirs[i], "nmea"); 489 if (nmeaFile.exists()) { 490 ((TrackProvider) provider).readNmea(name, nmeaFile); 491 } else { 492 File trackFile = new File(subdirs[i], "track"); 493 if (trackFile.exists()) { 494 ((TrackProvider) provider).readTrack(trackFile); 495 } 496 } 497 } 498 } 499 } 500 if (provider != null) { 501 LocationProviderImpl.addProvider(provider); 502 } 503 // Grab the initial location of a TrackProvider and 504 // store it as the last known location for that provider 505 if (provider instanceof TrackProvider) { 506 TrackProvider tp = (TrackProvider) provider; 507 mLastKnownLocation.put(tp.getName(), tp.getInitialLocation()); 508 } 509 } catch (Exception e) { 510 Log.e(TAG, "Exception loading provder " + name, e); 511 } 512 } 513 } 514 } 515 516 updateProvidersLocked(); 517 } 518 519 /** 520 * @param context the context that the LocationManagerService runs in 521 */ 522 public LocationManagerService(Context context) { 523 super(); 524 mContext = context; 525 mLocationHandler = new LocationWorkerHandler(); 526 527 if (LOCAL_LOGV) { 528 Log.v(TAG, "Constructed LocationManager Service"); 529 } 530 531 // Alarm manager, needs to be done before calling loadProviders() below 532 mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); 533 534 // Create a wake lock, needs to be done before calling loadProviders() below 535 PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); 536 mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY); 537 538 // Load providers 539 loadProviders(); 540 541 // Listen for Radio changes 542 mTelephonyManager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE); 543 544 // Register for Network (Wifi or Mobile) updates 545 NetworkStateBroadcastReceiver networkReceiver = new NetworkStateBroadcastReceiver(); 546 IntentFilter networkIntentFilter = new IntentFilter(); 547 networkIntentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); 548 networkIntentFilter.addAction(GpsLocationProvider.GPS_ENABLED_CHANGE_ACTION); 549 context.registerReceiver(networkReceiver, networkIntentFilter); 550 551 // Register for power updates 552 PowerStateBroadcastReceiver powerStateReceiver = new PowerStateBroadcastReceiver(); 553 IntentFilter intentFilter = new IntentFilter(); 554 intentFilter.addAction(ALARM_INTENT); 555 intentFilter.addAction(Intent.ACTION_SCREEN_OFF); 556 intentFilter.addAction(Intent.ACTION_SCREEN_ON); 557 intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); 558 intentFilter.addAction(Intent.ACTION_PACKAGE_RESTARTED); 559 context.registerReceiver(powerStateReceiver, intentFilter); 560 561 // listen for settings changes 562 ContentResolver resolver = mContext.getContentResolver(); 563 Cursor settingsCursor = resolver.query(Settings.Secure.CONTENT_URI, null, 564 "(" + Settings.System.NAME + "=?)", 565 new String[]{Settings.Secure.LOCATION_PROVIDERS_ALLOWED}, 566 null); 567 mSettings = new ContentQueryMap(settingsCursor, Settings.System.NAME, true, mLocationHandler); 568 SettingsObserver settingsObserver = new SettingsObserver(); 569 mSettings.addObserver(settingsObserver); 570 571 // Get the wifi manager 572 mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); 573 574 // Create a wifi lock for future use 575 mWifiLock = getWifiWakelockLocked(); 576 } 577 578 public void setNetworkLocationProvider(ILocationProvider provider) { 579 if (Binder.getCallingUid() != Process.SYSTEM_UID) { 580 throw new SecurityException( 581 "Installing location providers outside of the system is not supported"); 582 } 583 584 synchronized (mLock) { 585 mNetworkLocationProvider = 586 new LocationProviderProxy(LocationManager.NETWORK_PROVIDER, this, provider); 587 LocationProviderImpl.addProvider(mNetworkLocationProvider); 588 updateProvidersLocked(); 589 590 // notify NetworkLocationProvider of any events it might have missed 591 mNetworkLocationProvider.updateNetworkState(mNetworkState); 592 mNetworkLocationProvider.updateCellLockStatus(mCellWakeLockAcquired); 593 } 594 } 595 596 public void setLocationCollector(ILocationCollector collector) { 597 if (Binder.getCallingUid() != Process.SYSTEM_UID) { 598 throw new SecurityException( 599 "Installing location collectors outside of the system is not supported"); 600 } 601 602 mCollector = collector; 603 } 604 605 public void setGeocodeProvider(IGeocodeProvider provider) { 606 if (Binder.getCallingUid() != Process.SYSTEM_UID) { 607 throw new SecurityException( 608 "Installing location providers outside of the system is not supported"); 609 } 610 611 mGeocodeProvider = provider; 612 } 613 614 private WifiManager.WifiLock getWifiWakelockLocked() { 615 if (mWifiLock == null && mWifiManager != null) { 616 mWifiLock = mWifiManager.createWifiLock(WifiManager.WIFI_MODE_SCAN_ONLY, WIFILOCK_KEY); 617 mWifiLock.setReferenceCounted(false); 618 } 619 return mWifiLock; 620 } 621 622 private boolean isAllowedBySettingsLocked(String provider) { 623 if (mEnabledProviders.contains(provider)) { 624 return true; 625 } 626 if (mDisabledProviders.contains(provider)) { 627 return false; 628 } 629 // Use system settings 630 ContentResolver resolver = mContext.getContentResolver(); 631 String allowedProviders = Settings.Secure.getString(resolver, 632 Settings.Secure.LOCATION_PROVIDERS_ALLOWED); 633 634 return ((allowedProviders != null) && (allowedProviders.contains(provider))); 635 } 636 637 private void checkPermissionsSafe(String provider) { 638 if (LocationManager.GPS_PROVIDER.equals(provider) 639 && (mContext.checkCallingPermission(ACCESS_FINE_LOCATION) 640 != PackageManager.PERMISSION_GRANTED)) { 641 throw new SecurityException("Requires ACCESS_FINE_LOCATION permission"); 642 } 643 if (LocationManager.NETWORK_PROVIDER.equals(provider) 644 && (mContext.checkCallingPermission(ACCESS_FINE_LOCATION) 645 != PackageManager.PERMISSION_GRANTED) 646 && (mContext.checkCallingPermission(ACCESS_COARSE_LOCATION) 647 != PackageManager.PERMISSION_GRANTED)) { 648 throw new SecurityException( 649 "Requires ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION permission"); 650 } 651 } 652 653 private boolean isAllowedProviderSafe(String provider) { 654 if (LocationManager.GPS_PROVIDER.equals(provider) 655 && (mContext.checkCallingPermission(ACCESS_FINE_LOCATION) 656 != PackageManager.PERMISSION_GRANTED)) { 657 return false; 658 } 659 if (LocationManager.NETWORK_PROVIDER.equals(provider) 660 && (mContext.checkCallingPermission(ACCESS_FINE_LOCATION) 661 != PackageManager.PERMISSION_GRANTED) 662 && (mContext.checkCallingPermission(ACCESS_COARSE_LOCATION) 663 != PackageManager.PERMISSION_GRANTED)) { 664 return false; 665 } 666 667 return true; 668 } 669 670 public List<String> getAllProviders() { 671 try { 672 synchronized (mLock) { 673 return _getAllProvidersLocked(); 674 } 675 } catch (SecurityException se) { 676 throw se; 677 } catch (Exception e) { 678 Log.e(TAG, "getAllProviders got exception:", e); 679 return null; 680 } 681 } 682 683 private List<String> _getAllProvidersLocked() { 684 if (LOCAL_LOGV) { 685 Log.v(TAG, "getAllProviders"); 686 } 687 List<LocationProviderImpl> providers = LocationProviderImpl.getProviders(); 688 ArrayList<String> out = new ArrayList<String>(providers.size()); 689 690 for (LocationProviderImpl p : providers) { 691 out.add(p.getName()); 692 } 693 return out; 694 } 695 696 public List<String> getProviders(boolean enabledOnly) { 697 try { 698 synchronized (mLock) { 699 return _getProvidersLocked(enabledOnly); 700 } 701 } catch (SecurityException se) { 702 throw se; 703 } catch (Exception e) { 704 Log.e(TAG, "getProviders got exception:", e); 705 return null; 706 } 707 } 708 709 private List<String> _getProvidersLocked(boolean enabledOnly) { 710 if (LOCAL_LOGV) { 711 Log.v(TAG, "getProviders"); 712 } 713 List<LocationProviderImpl> providers = LocationProviderImpl.getProviders(); 714 ArrayList<String> out = new ArrayList<String>(); 715 716 for (LocationProviderImpl p : providers) { 717 String name = p.getName(); 718 if (isAllowedProviderSafe(name)) { 719 if (enabledOnly && !isAllowedBySettingsLocked(name)) { 720 continue; 721 } 722 out.add(name); 723 } 724 } 725 return out; 726 } 727 728 private void updateProvidersLocked() { 729 for (LocationProviderImpl p : LocationProviderImpl.getProviders()) { 730 boolean isEnabled = p.isEnabled(); 731 String name = p.getName(); 732 boolean shouldBeEnabled = isAllowedBySettingsLocked(name); 733 734 if (isEnabled && !shouldBeEnabled) { 735 updateProviderListenersLocked(name, false); 736 } else if (!isEnabled && shouldBeEnabled) { 737 updateProviderListenersLocked(name, true); 738 } 739 740 } 741 } 742 743 private void updateProviderListenersLocked(String provider, boolean enabled) { 744 int listeners = 0; 745 746 LocationProviderImpl p = LocationProviderImpl.getProvider(provider); 747 if (p == null) { 748 return; 749 } 750 751 ArrayList<Receiver> deadReceivers = null; 752 753 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider); 754 if (records != null) { 755 final int N = records.size(); 756 for (int i=0; i<N; i++) { 757 UpdateRecord record = records.get(i); 758 // Sends a notification message to the receiver 759 try { 760 Receiver receiver = record.mReceiver; 761 if (receiver.isListener()) { 762 if (enabled) { 763 receiver.getListener().onProviderEnabled(provider); 764 } else { 765 receiver.getListener().onProviderDisabled(provider); 766 } 767 } else { 768 Intent providerIntent = new Intent(); 769 providerIntent.putExtra(LocationManager.KEY_PROVIDER_ENABLED, enabled); 770 try { 771 receiver.getPendingIntent().send(mContext, 0, 772 providerIntent, null, null); 773 } catch (PendingIntent.CanceledException e) { 774 if (deadReceivers == null) { 775 deadReceivers = new ArrayList<Receiver>(); 776 deadReceivers.add(receiver); 777 } 778 } 779 } 780 } catch (RemoteException e) { 781 // The death link will clean this up. 782 } 783 listeners++; 784 } 785 } 786 787 if (deadReceivers != null) { 788 for (int i=deadReceivers.size()-1; i>=0; i--) { 789 removeUpdatesLocked(deadReceivers.get(i)); 790 } 791 } 792 793 if (enabled) { 794 p.enable(); 795 if (listeners > 0) { 796 p.setMinTime(getMinTimeLocked(provider)); 797 p.enableLocationTracking(true); 798 updateWakelockStatusLocked(mScreenOn); 799 } 800 } else { 801 p.enableLocationTracking(false); 802 p.disable(); 803 updateWakelockStatusLocked(mScreenOn); 804 } 805 } 806 807 private long getMinTimeLocked(String provider) { 808 long minTime = Long.MAX_VALUE; 809 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider); 810 if (records != null) { 811 for (int i=records.size()-1; i>=0; i--) { 812 minTime = Math.min(minTime, records.get(i).mMinTime); 813 } 814 } 815 return minTime; 816 } 817 818 private class UpdateRecord { 819 final String mProvider; 820 final Receiver mReceiver; 821 final long mMinTime; 822 final float mMinDistance; 823 final int mUid; 824 Location mLastFixBroadcast; 825 long mLastStatusBroadcast; 826 827 /** 828 * Note: must be constructed with lock held. 829 */ 830 UpdateRecord(String provider, long minTime, float minDistance, 831 Receiver receiver, int uid) { 832 mProvider = provider; 833 mReceiver = receiver; 834 mMinTime = minTime; 835 mMinDistance = minDistance; 836 mUid = uid; 837 838 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider); 839 if (records == null) { 840 records = new ArrayList<UpdateRecord>(); 841 mRecordsByProvider.put(provider, records); 842 } 843 if (!records.contains(this)) { 844 records.add(this); 845 } 846 } 847 848 /** 849 * Method to be called when a record will no longer be used. Calling this multiple times 850 * must have the same effect as calling it once. 851 */ 852 void disposeLocked() { 853 ArrayList<UpdateRecord> records = mRecordsByProvider.get(this.mProvider); 854 records.remove(this); 855 } 856 857 @Override 858 public String toString() { 859 return "UpdateRecord{" 860 + Integer.toHexString(System.identityHashCode(this)) 861 + " " + mProvider + " " + mReceiver + "}"; 862 } 863 864 void dump(PrintWriter pw, String prefix) { 865 pw.println(prefix + this); 866 pw.println(prefix + "mProvider=" + mProvider + " mReceiver=" + mReceiver); 867 pw.println(prefix + "mMinTime=" + mMinTime + " mMinDistance=" + mMinDistance); 868 pw.println(prefix + "mUid=" + mUid); 869 pw.println(prefix + "mLastFixBroadcast:"); 870 mLastFixBroadcast.dump(new PrintWriterPrinter(pw), prefix + " "); 871 pw.println(prefix + "mLastStatusBroadcast=" + mLastStatusBroadcast); 872 } 873 874 /** 875 * Calls dispose(). 876 */ 877 @Override protected void finalize() { 878 synchronized (mLock) { 879 disposeLocked(); 880 } 881 } 882 } 883 884 private Receiver getReceiver(ILocationListener listener) { 885 IBinder binder = listener.asBinder(); 886 Receiver receiver = mReceivers.get(binder); 887 if (receiver == null) { 888 receiver = new Receiver(listener); 889 mReceivers.put(binder, receiver); 890 891 try { 892 if (receiver.isListener()) { 893 receiver.getListener().asBinder().linkToDeath(receiver, 0); 894 } 895 } catch (RemoteException e) { 896 Log.e(TAG, "linkToDeath failed:", e); 897 return null; 898 } 899 } 900 return receiver; 901 } 902 903 private Receiver getReceiver(PendingIntent intent) { 904 Receiver receiver = mReceivers.get(intent); 905 if (receiver == null) { 906 receiver = new Receiver(intent); 907 mReceivers.put(intent, receiver); 908 } 909 return receiver; 910 } 911 912 private boolean providerHasListener(String provider, int uid, Receiver excludedReceiver) { 913 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider); 914 if (records != null) { 915 for (int i = records.size() - 1; i >= 0; i--) { 916 UpdateRecord record = records.get(i); 917 if (record.mUid == uid && record.mReceiver != excludedReceiver) { 918 return true; 919 } 920 } 921 } 922 if (LocationManager.GPS_PROVIDER.equals(provider) || 923 LocationManager.NETWORK_PROVIDER.equals(provider)) { 924 for (ProximityAlert alert : mProximityAlerts.values()) { 925 if (alert.mUid == uid) { 926 return true; 927 } 928 } 929 } 930 return false; 931 } 932 933 public void requestLocationUpdates(String provider, 934 long minTime, float minDistance, ILocationListener listener) { 935 936 try { 937 synchronized (mLock) { 938 requestLocationUpdatesLocked(provider, minTime, minDistance, getReceiver(listener)); 939 } 940 } catch (SecurityException se) { 941 throw se; 942 } catch (Exception e) { 943 Log.e(TAG, "requestUpdates got exception:", e); 944 } 945 } 946 947 public void requestLocationUpdatesPI(String provider, 948 long minTime, float minDistance, PendingIntent intent) { 949 try { 950 synchronized (mLock) { 951 requestLocationUpdatesLocked(provider, minTime, minDistance, getReceiver(intent)); 952 } 953 } catch (SecurityException se) { 954 throw se; 955 } catch (Exception e) { 956 Log.e(TAG, "requestUpdates got exception:", e); 957 } 958 } 959 960 private void requestLocationUpdatesLocked(String provider, 961 long minTime, float minDistance, Receiver receiver) { 962 if (LOCAL_LOGV) { 963 Log.v(TAG, "_requestLocationUpdates: listener = " + receiver); 964 } 965 966 LocationProviderImpl impl = LocationProviderImpl.getProvider(provider); 967 if (impl == null) { 968 throw new IllegalArgumentException("provider=" + provider); 969 } 970 971 checkPermissionsSafe(provider); 972 973 // so wakelock calls will succeed 974 final int callingUid = Binder.getCallingUid(); 975 boolean newUid = !providerHasListener(provider, callingUid, null); 976 long identity = Binder.clearCallingIdentity(); 977 try { 978 UpdateRecord r = new UpdateRecord(provider, minTime, minDistance, receiver, callingUid); 979 UpdateRecord oldRecord = receiver.mUpdateRecords.put(provider, r); 980 if (oldRecord != null) { 981 oldRecord.disposeLocked(); 982 } 983 984 if (newUid) { 985 impl.addListener(callingUid); 986 } 987 988 boolean isProviderEnabled = isAllowedBySettingsLocked(provider); 989 if (isProviderEnabled) { 990 long minTimeForProvider = getMinTimeLocked(provider); 991 impl.setMinTime(minTimeForProvider); 992 impl.enableLocationTracking(true); 993 updateWakelockStatusLocked(mScreenOn); 994 } else { 995 try { 996 // Notify the listener that updates are currently disabled 997 if (receiver.isListener()) { 998 receiver.getListener().onProviderDisabled(provider); 999 } 1000 } catch(RemoteException e) { 1001 Log.w(TAG, "RemoteException calling onProviderDisabled on " + 1002 receiver.getListener()); 1003 } 1004 } 1005 } finally { 1006 Binder.restoreCallingIdentity(identity); 1007 } 1008 } 1009 1010 public void removeUpdates(ILocationListener listener) { 1011 try { 1012 synchronized (mLock) { 1013 removeUpdatesLocked(getReceiver(listener)); 1014 } 1015 } catch (SecurityException se) { 1016 throw se; 1017 } catch (Exception e) { 1018 Log.e(TAG, "removeUpdates got exception:", e); 1019 } 1020 } 1021 1022 public void removeUpdatesPI(PendingIntent intent) { 1023 try { 1024 synchronized (mLock) { 1025 removeUpdatesLocked(getReceiver(intent)); 1026 } 1027 } catch (SecurityException se) { 1028 throw se; 1029 } catch (Exception e) { 1030 Log.e(TAG, "removeUpdates got exception:", e); 1031 } 1032 } 1033 1034 private void removeUpdatesLocked(Receiver receiver) { 1035 if (LOCAL_LOGV) { 1036 Log.v(TAG, "_removeUpdates: listener = " + receiver); 1037 } 1038 1039 // so wakelock calls will succeed 1040 final int callingUid = Binder.getCallingUid(); 1041 long identity = Binder.clearCallingIdentity(); 1042 try { 1043 if (mReceivers.remove(receiver.mKey) != null && receiver.isListener()) { 1044 receiver.getListener().asBinder().unlinkToDeath(receiver, 0); 1045 } 1046 1047 // Record which providers were associated with this listener 1048 HashSet<String> providers = new HashSet<String>(); 1049 HashMap<String,UpdateRecord> oldRecords = receiver.mUpdateRecords; 1050 if (oldRecords != null) { 1051 // Call dispose() on the obsolete update records. 1052 for (UpdateRecord record : oldRecords.values()) { 1053 if (!providerHasListener(record.mProvider, callingUid, receiver)) { 1054 LocationProviderImpl impl = 1055 LocationProviderImpl.getProvider(record.mProvider); 1056 if (impl != null) { 1057 impl.removeListener(callingUid); 1058 } 1059 } 1060 record.disposeLocked(); 1061 } 1062 // Accumulate providers 1063 providers.addAll(oldRecords.keySet()); 1064 } 1065 1066 // See if the providers associated with this listener have any 1067 // other listeners; if one does, inform it of the new smallest minTime 1068 // value; if one does not, disable location tracking for it 1069 for (String provider : providers) { 1070 // If provider is already disabled, don't need to do anything 1071 if (!isAllowedBySettingsLocked(provider)) { 1072 continue; 1073 } 1074 1075 boolean hasOtherListener = false; 1076 ArrayList<UpdateRecord> recordsForProvider = mRecordsByProvider.get(provider); 1077 if (recordsForProvider != null && recordsForProvider.size() > 0) { 1078 hasOtherListener = true; 1079 } 1080 1081 LocationProviderImpl p = LocationProviderImpl.getProvider(provider); 1082 if (p != null) { 1083 if (hasOtherListener) { 1084 p.setMinTime(getMinTimeLocked(provider)); 1085 } else { 1086 p.enableLocationTracking(false); 1087 } 1088 } 1089 } 1090 1091 updateWakelockStatusLocked(mScreenOn); 1092 } finally { 1093 Binder.restoreCallingIdentity(identity); 1094 } 1095 } 1096 1097 public boolean addGpsStatusListener(IGpsStatusListener listener) { 1098 if (mGpsLocationProvider == null) { 1099 return false; 1100 } 1101 if (mContext.checkCallingPermission(ACCESS_FINE_LOCATION) != 1102 PackageManager.PERMISSION_GRANTED) { 1103 throw new SecurityException("Requires ACCESS_FINE_LOCATION permission"); 1104 } 1105 1106 try { 1107 mGpsLocationProvider.addGpsStatusListener(listener); 1108 } catch (RemoteException e) { 1109 Log.w(TAG, "RemoteException in addGpsStatusListener"); 1110 return false; 1111 } 1112 return true; 1113 } 1114 1115 public void removeGpsStatusListener(IGpsStatusListener listener) { 1116 synchronized (mLock) { 1117 mGpsLocationProvider.removeGpsStatusListener(listener); 1118 } 1119 } 1120 1121 public boolean sendExtraCommand(String provider, String command, Bundle extras) { 1122 // first check for permission to the provider 1123 checkPermissionsSafe(provider); 1124 // and check for ACCESS_LOCATION_EXTRA_COMMANDS 1125 if ((mContext.checkCallingPermission(ACCESS_LOCATION_EXTRA_COMMANDS) 1126 != PackageManager.PERMISSION_GRANTED)) { 1127 throw new SecurityException("Requires ACCESS_LOCATION_EXTRA_COMMANDS permission"); 1128 } 1129 1130 synchronized (mLock) { 1131 LocationProviderImpl impl = LocationProviderImpl.getProvider(provider); 1132 if (provider == null) { 1133 return false; 1134 } 1135 1136 return impl.sendExtraCommand(command, extras); 1137 } 1138 } 1139 1140 class ProximityAlert { 1141 final int mUid; 1142 final double mLatitude; 1143 final double mLongitude; 1144 final float mRadius; 1145 final long mExpiration; 1146 final PendingIntent mIntent; 1147 final Location mLocation; 1148 1149 public ProximityAlert(int uid, double latitude, double longitude, 1150 float radius, long expiration, PendingIntent intent) { 1151 mUid = uid; 1152 mLatitude = latitude; 1153 mLongitude = longitude; 1154 mRadius = radius; 1155 mExpiration = expiration; 1156 mIntent = intent; 1157 1158 mLocation = new Location(""); 1159 mLocation.setLatitude(latitude); 1160 mLocation.setLongitude(longitude); 1161 } 1162 1163 long getExpiration() { 1164 return mExpiration; 1165 } 1166 1167 PendingIntent getIntent() { 1168 return mIntent; 1169 } 1170 1171 boolean isInProximity(double latitude, double longitude) { 1172 Location loc = new Location(""); 1173 loc.setLatitude(latitude); 1174 loc.setLongitude(longitude); 1175 1176 double radius = loc.distanceTo(mLocation); 1177 return radius <= mRadius; 1178 } 1179 1180 @Override 1181 public String toString() { 1182 return "ProximityAlert{" 1183 + Integer.toHexString(System.identityHashCode(this)) 1184 + " uid " + mUid + mIntent + "}"; 1185 } 1186 1187 void dump(PrintWriter pw, String prefix) { 1188 pw.println(prefix + this); 1189 pw.println(prefix + "mLatitude=" + mLatitude + " mLongitude=" + mLongitude); 1190 pw.println(prefix + "mRadius=" + mRadius + " mExpiration=" + mExpiration); 1191 pw.println(prefix + "mIntent=" + mIntent); 1192 pw.println(prefix + "mLocation:"); 1193 mLocation.dump(new PrintWriterPrinter(pw), prefix + " "); 1194 } 1195 } 1196 1197 // Listener for receiving locations to trigger proximity alerts 1198 class ProximityListener extends ILocationListener.Stub { 1199 1200 boolean isGpsAvailable = false; 1201 1202 // Note: this is called with the lock held. 1203 public void onLocationChanged(Location loc) { 1204 1205 // If Gps is available, then ignore updates from NetworkLocationProvider 1206 if (loc.getProvider().equals(LocationManager.GPS_PROVIDER)) { 1207 isGpsAvailable = true; 1208 } 1209 if (isGpsAvailable && loc.getProvider().equals(LocationManager.NETWORK_PROVIDER)) { 1210 return; 1211 } 1212 1213 // Process proximity alerts 1214 long now = System.currentTimeMillis(); 1215 double latitude = loc.getLatitude(); 1216 double longitude = loc.getLongitude(); 1217 ArrayList<PendingIntent> intentsToRemove = null; 1218 1219 for (ProximityAlert alert : mProximityAlerts.values()) { 1220 PendingIntent intent = alert.getIntent(); 1221 long expiration = alert.getExpiration(); 1222 1223 if ((expiration == -1) || (now <= expiration)) { 1224 boolean entered = mProximitiesEntered.contains(alert); 1225 boolean inProximity = 1226 alert.isInProximity(latitude, longitude); 1227 if (!entered && inProximity) { 1228 if (LOCAL_LOGV) { 1229 Log.v(TAG, "Entered alert"); 1230 } 1231 mProximitiesEntered.add(alert); 1232 Intent enteredIntent = new Intent(); 1233 enteredIntent.putExtra(LocationManager.KEY_PROXIMITY_ENTERING, true); 1234 try { 1235 intent.send(mContext, 0, enteredIntent, null, null); 1236 } catch (PendingIntent.CanceledException e) { 1237 if (LOCAL_LOGV) { 1238 Log.v(TAG, "Canceled proximity alert: " + alert, e); 1239 } 1240 if (intentsToRemove == null) { 1241 intentsToRemove = new ArrayList<PendingIntent>(); 1242 } 1243 intentsToRemove.add(intent); 1244 } 1245 } else if (entered && !inProximity) { 1246 if (LOCAL_LOGV) { 1247 Log.v(TAG, "Exited alert"); 1248 } 1249 mProximitiesEntered.remove(alert); 1250 Intent exitedIntent = new Intent(); 1251 exitedIntent.putExtra(LocationManager.KEY_PROXIMITY_ENTERING, false); 1252 try { 1253 intent.send(mContext, 0, exitedIntent, null, null); 1254 } catch (PendingIntent.CanceledException e) { 1255 if (LOCAL_LOGV) { 1256 Log.v(TAG, "Canceled proximity alert: " + alert, e); 1257 } 1258 if (intentsToRemove == null) { 1259 intentsToRemove = new ArrayList<PendingIntent>(); 1260 } 1261 intentsToRemove.add(intent); 1262 } 1263 } 1264 } else { 1265 // Mark alert for expiration 1266 if (LOCAL_LOGV) { 1267 Log.v(TAG, "Expiring proximity alert: " + alert); 1268 } 1269 if (intentsToRemove == null) { 1270 intentsToRemove = new ArrayList<PendingIntent>(); 1271 } 1272 intentsToRemove.add(alert.getIntent()); 1273 } 1274 } 1275 1276 // Remove expired alerts 1277 if (intentsToRemove != null) { 1278 for (PendingIntent i : intentsToRemove) { 1279 mProximityAlerts.remove(i); 1280 ProximityAlert alert = mProximityAlerts.get(i); 1281 mProximitiesEntered.remove(alert); 1282 } 1283 } 1284 1285 } 1286 1287 // Note: this is called with the lock held. 1288 public void onProviderDisabled(String provider) { 1289 if (provider.equals(LocationManager.GPS_PROVIDER)) { 1290 isGpsAvailable = false; 1291 } 1292 } 1293 1294 // Note: this is called with the lock held. 1295 public void onProviderEnabled(String provider) { 1296 // ignore 1297 } 1298 1299 // Note: this is called with the lock held. 1300 public void onStatusChanged(String provider, int status, Bundle extras) { 1301 if ((provider.equals(LocationManager.GPS_PROVIDER)) && 1302 (status != LocationProvider.AVAILABLE)) { 1303 isGpsAvailable = false; 1304 } 1305 } 1306 } 1307 1308 public void addProximityAlert(double latitude, double longitude, 1309 float radius, long expiration, PendingIntent intent) { 1310 try { 1311 synchronized (mLock) { 1312 addProximityAlertLocked(latitude, longitude, radius, expiration, intent); 1313 } 1314 } catch (SecurityException se) { 1315 throw se; 1316 } catch (Exception e) { 1317 Log.e(TAG, "addProximityAlert got exception:", e); 1318 } 1319 } 1320 1321 private void addProximityAlertLocked(double latitude, double longitude, 1322 float radius, long expiration, PendingIntent intent) { 1323 if (LOCAL_LOGV) { 1324 Log.v(TAG, "addProximityAlert: latitude = " + latitude + 1325 ", longitude = " + longitude + 1326 ", expiration = " + expiration + 1327 ", intent = " + intent); 1328 } 1329 1330 // Require ability to access all providers for now 1331 if (!isAllowedProviderSafe(LocationManager.GPS_PROVIDER) || 1332 !isAllowedProviderSafe(LocationManager.NETWORK_PROVIDER)) { 1333 throw new SecurityException("Requires ACCESS_FINE_LOCATION permission"); 1334 } 1335 1336 if (expiration != -1) { 1337 expiration += System.currentTimeMillis(); 1338 } 1339 ProximityAlert alert = new ProximityAlert(Binder.getCallingUid(), 1340 latitude, longitude, radius, expiration, intent); 1341 mProximityAlerts.put(intent, alert); 1342 1343 if (mProximityListener == null) { 1344 mProximityListener = new Receiver(new ProximityListener()); 1345 1346 LocationProvider provider = LocationProviderImpl.getProvider( 1347 LocationManager.GPS_PROVIDER); 1348 if (provider != null) { 1349 requestLocationUpdatesLocked(provider.getName(), 1000L, 1.0f, mProximityListener); 1350 } 1351 1352 provider = 1353 LocationProviderImpl.getProvider(LocationManager.NETWORK_PROVIDER); 1354 if (provider != null) { 1355 requestLocationUpdatesLocked(provider.getName(), 1000L, 1.0f, mProximityListener); 1356 } 1357 } 1358 } 1359 1360 public void removeProximityAlert(PendingIntent intent) { 1361 try { 1362 synchronized (mLock) { 1363 removeProximityAlertLocked(intent); 1364 } 1365 } catch (SecurityException se) { 1366 throw se; 1367 } catch (Exception e) { 1368 Log.e(TAG, "removeProximityAlert got exception:", e); 1369 } 1370 } 1371 1372 private void removeProximityAlertLocked(PendingIntent intent) { 1373 if (LOCAL_LOGV) { 1374 Log.v(TAG, "removeProximityAlert: intent = " + intent); 1375 } 1376 1377 mProximityAlerts.remove(intent); 1378 if (mProximityAlerts.size() == 0) { 1379 removeUpdatesLocked(mProximityListener); 1380 mProximityListener = null; 1381 } 1382 } 1383 1384 /** 1385 * @return null if the provider does not exits 1386 * @throw SecurityException if the provider is not allowed to be 1387 * accessed by the caller 1388 */ 1389 public Bundle getProviderInfo(String provider) { 1390 try { 1391 synchronized (mLock) { 1392 return _getProviderInfoLocked(provider); 1393 } 1394 } catch (SecurityException se) { 1395 throw se; 1396 } catch (Exception e) { 1397 Log.e(TAG, "_getProviderInfo got exception:", e); 1398 return null; 1399 } 1400 } 1401 1402 private Bundle _getProviderInfoLocked(String provider) { 1403 LocationProviderImpl p = LocationProviderImpl.getProvider(provider); 1404 if (p == null) { 1405 return null; 1406 } 1407 1408 checkPermissionsSafe(provider); 1409 1410 Bundle b = new Bundle(); 1411 b.putBoolean("network", p.requiresNetwork()); 1412 b.putBoolean("satellite", p.requiresSatellite()); 1413 b.putBoolean("cell", p.requiresCell()); 1414 b.putBoolean("cost", p.hasMonetaryCost()); 1415 b.putBoolean("altitude", p.supportsAltitude()); 1416 b.putBoolean("speed", p.supportsSpeed()); 1417 b.putBoolean("bearing", p.supportsBearing()); 1418 b.putInt("power", p.getPowerRequirement()); 1419 b.putInt("accuracy", p.getAccuracy()); 1420 1421 return b; 1422 } 1423 1424 public boolean isProviderEnabled(String provider) { 1425 try { 1426 synchronized (mLock) { 1427 return _isProviderEnabledLocked(provider); 1428 } 1429 } catch (SecurityException se) { 1430 throw se; 1431 } catch (Exception e) { 1432 Log.e(TAG, "isProviderEnabled got exception:", e); 1433 return false; 1434 } 1435 } 1436 1437 public void setLocation(Location location) { 1438 mLocationHandler.removeMessages(MESSAGE_LOCATION_CHANGED, location); 1439 Message m = Message.obtain(mLocationHandler, MESSAGE_LOCATION_CHANGED, location); 1440 mLocationHandler.sendMessageAtFrontOfQueue(m); 1441 } 1442 1443 private boolean _isProviderEnabledLocked(String provider) { 1444 checkPermissionsSafe(provider); 1445 1446 LocationProviderImpl p = LocationProviderImpl.getProvider(provider); 1447 if (p == null) { 1448 throw new IllegalArgumentException("provider=" + provider); 1449 } 1450 return isAllowedBySettingsLocked(provider); 1451 } 1452 1453 public Location getLastKnownLocation(String provider) { 1454 try { 1455 synchronized (mLock) { 1456 return _getLastKnownLocationLocked(provider); 1457 } 1458 } catch (SecurityException se) { 1459 throw se; 1460 } catch (Exception e) { 1461 Log.e(TAG, "getLastKnownLocation got exception:", e); 1462 return null; 1463 } 1464 } 1465 1466 private Location _getLastKnownLocationLocked(String provider) { 1467 checkPermissionsSafe(provider); 1468 1469 LocationProviderImpl p = LocationProviderImpl.getProvider(provider); 1470 if (p == null) { 1471 throw new IllegalArgumentException("provider=" + provider); 1472 } 1473 1474 if (!isAllowedBySettingsLocked(provider)) { 1475 return null; 1476 } 1477 1478 Location location = mLastKnownLocation.get(provider); 1479 if (location == null) { 1480 // Get the persistent last known location for the provider 1481 location = readLastKnownLocationLocked(provider); 1482 if (location != null) { 1483 mLastKnownLocation.put(provider, location); 1484 } 1485 } 1486 1487 return location; 1488 } 1489 1490 private static boolean shouldBroadcastSafe(Location loc, Location lastLoc, UpdateRecord record) { 1491 // Always broadcast the first update 1492 if (lastLoc == null) { 1493 return true; 1494 } 1495 1496 // Don't broadcast same location again regardless of condition 1497 // TODO - we should probably still rebroadcast if user explicitly sets a minTime > 0 1498 if (loc.getTime() == lastLoc.getTime()) { 1499 return false; 1500 } 1501 1502 // Check whether sufficient distance has been traveled 1503 double minDistance = record.mMinDistance; 1504 if (minDistance > 0.0) { 1505 if (loc.distanceTo(lastLoc) <= minDistance) { 1506 return false; 1507 } 1508 } 1509 1510 return true; 1511 } 1512 1513 private void handleLocationChangedLocked(Location location) { 1514 String provider = location.getProvider(); 1515 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider); 1516 if (records == null || records.size() == 0) { 1517 return; 1518 } 1519 1520 LocationProviderImpl p = LocationProviderImpl.getProvider(provider); 1521 if (p == null) { 1522 return; 1523 } 1524 1525 // Update last known location for provider 1526 Location lastLocation = mLastKnownLocation.get(provider); 1527 if (lastLocation == null) { 1528 mLastKnownLocation.put(provider, new Location(location)); 1529 } else { 1530 lastLocation.set(location); 1531 } 1532 writeLastKnownLocationLocked(provider, location); 1533 1534 if (LocationManager.NETWORK_PROVIDER.equals(p.getName())) { 1535 mWakeLockNetworkReceived = true; 1536 } else if (p instanceof GpsLocationProvider) { 1537 // Gps location received signal is in NetworkStateBroadcastReceiver 1538 } 1539 1540 // Fetch latest status update time 1541 long newStatusUpdateTime = p.getStatusUpdateTime(); 1542 1543 // Get latest status 1544 Bundle extras = new Bundle(); 1545 int status = p.getStatus(extras); 1546 1547 ArrayList<Receiver> deadReceivers = null; 1548 1549 // Broadcast location or status to all listeners 1550 final int N = records.size(); 1551 for (int i=0; i<N; i++) { 1552 UpdateRecord r = records.get(i); 1553 Receiver receiver = r.mReceiver; 1554 1555 Location lastLoc = r.mLastFixBroadcast; 1556 if ((lastLoc == null) || shouldBroadcastSafe(location, lastLoc, r)) { 1557 if (lastLoc == null) { 1558 lastLoc = new Location(location); 1559 r.mLastFixBroadcast = lastLoc; 1560 } else { 1561 lastLoc.set(location); 1562 } 1563 if (!receiver.callLocationChangedLocked(location)) { 1564 Log.w(TAG, "RemoteException calling onLocationChanged on " + receiver); 1565 if (deadReceivers == null) { 1566 deadReceivers = new ArrayList<Receiver>(); 1567 } 1568 deadReceivers.add(receiver); 1569 } 1570 } 1571 1572 long prevStatusUpdateTime = r.mLastStatusBroadcast; 1573 if ((newStatusUpdateTime > prevStatusUpdateTime) && 1574 (prevStatusUpdateTime != 0 || status != LocationProvider.AVAILABLE)) { 1575 1576 r.mLastStatusBroadcast = newStatusUpdateTime; 1577 if (!receiver.callStatusChangedLocked(provider, status, extras)) { 1578 Log.w(TAG, "RemoteException calling onStatusChanged on " + receiver); 1579 if (deadReceivers == null) { 1580 deadReceivers = new ArrayList<Receiver>(); 1581 } 1582 if (!deadReceivers.contains(receiver)) { 1583 deadReceivers.add(receiver); 1584 } 1585 } 1586 } 1587 } 1588 1589 if (deadReceivers != null) { 1590 for (int i=deadReceivers.size()-1; i>=0; i--) { 1591 removeUpdatesLocked(deadReceivers.get(i)); 1592 } 1593 } 1594 } 1595 1596 private class LocationWorkerHandler extends Handler { 1597 1598 @Override 1599 public void handleMessage(Message msg) { 1600 try { 1601 if (msg.what == MESSAGE_LOCATION_CHANGED) { 1602 // log("LocationWorkerHandler: MESSAGE_LOCATION_CHANGED!"); 1603 1604 synchronized (mLock) { 1605 Location location = (Location) msg.obj; 1606 1607 if (mCollector != null && 1608 LocationManager.GPS_PROVIDER.equals(location.getProvider())) { 1609 try { 1610 mCollector.updateLocation(location); 1611 } catch (RemoteException e) { 1612 Log.w(TAG, "mCollector.updateLocation failed"); 1613 } 1614 } 1615 1616 String provider = location.getProvider(); 1617 if (!isAllowedBySettingsLocked(provider)) { 1618 return; 1619 } 1620 1621 // Process the location fix if the screen is on or we're holding a wakelock 1622 if (mScreenOn || (mWakeLockAcquireTime != 0)) { 1623 handleLocationChangedLocked(location); 1624 } 1625 1626 if ((mWakeLockAcquireTime != 0) && 1627 (SystemClock.elapsedRealtime() - mWakeLockAcquireTime 1628 > MAX_TIME_FOR_WAKE_LOCK)) { 1629 1630 removeMessages(MESSAGE_ACQUIRE_WAKE_LOCK); 1631 removeMessages(MESSAGE_RELEASE_WAKE_LOCK); 1632 1633 log("LocationWorkerHandler: Exceeded max time for wake lock"); 1634 Message m = Message.obtain(this, MESSAGE_RELEASE_WAKE_LOCK); 1635 sendMessageAtFrontOfQueue(m); 1636 1637 } else if (mWakeLockAcquireTime != 0 && 1638 mWakeLockGpsReceived && mWakeLockNetworkReceived) { 1639 1640 removeMessages(MESSAGE_ACQUIRE_WAKE_LOCK); 1641 removeMessages(MESSAGE_RELEASE_WAKE_LOCK); 1642 1643 log("LocationWorkerHandler: Locations received."); 1644 mWakeLockAcquireTime = 0; 1645 Message m = Message.obtain(this, MESSAGE_RELEASE_WAKE_LOCK); 1646 sendMessageDelayed(m, TIME_AFTER_WAKE_LOCK); 1647 } 1648 } 1649 1650 } else if (msg.what == MESSAGE_ACQUIRE_WAKE_LOCK) { 1651 log("LocationWorkerHandler: Acquire"); 1652 synchronized (mLock) { 1653 acquireWakeLockLocked(); 1654 } 1655 } else if (msg.what == MESSAGE_RELEASE_WAKE_LOCK) { 1656 log("LocationWorkerHandler: Release"); 1657 1658 // Update wakelock status so the next alarm is set before releasing wakelock 1659 synchronized (mLock) { 1660 updateWakelockStatusLocked(mScreenOn); 1661 releaseWakeLockLocked(); 1662 } 1663 } 1664 } catch (Exception e) { 1665 // Log, don't crash! 1666 Log.e(TAG, "Exception in LocationWorkerHandler.handleMessage:", e); 1667 } 1668 } 1669 } 1670 1671 private class PowerStateBroadcastReceiver extends BroadcastReceiver { 1672 @Override public void onReceive(Context context, Intent intent) { 1673 String action = intent.getAction(); 1674 1675 if (action.equals(ALARM_INTENT)) { 1676 synchronized (mLock) { 1677 log("PowerStateBroadcastReceiver: Alarm received"); 1678 mLocationHandler.removeMessages(MESSAGE_ACQUIRE_WAKE_LOCK); 1679 // Have to do this immediately, rather than posting a 1680 // message, so we execute our code while the system 1681 // is holding a wake lock until the alarm broadcast 1682 // is finished. 1683 acquireWakeLockLocked(); 1684 } 1685 1686 } else if (action.equals(Intent.ACTION_SCREEN_OFF)) { 1687 log("PowerStateBroadcastReceiver: Screen off"); 1688 synchronized (mLock) { 1689 updateWakelockStatusLocked(false); 1690 } 1691 1692 } else if (action.equals(Intent.ACTION_SCREEN_ON)) { 1693 log("PowerStateBroadcastReceiver: Screen on"); 1694 synchronized (mLock) { 1695 updateWakelockStatusLocked(true); 1696 } 1697 } else if (action.equals(Intent.ACTION_PACKAGE_REMOVED) 1698 || action.equals(Intent.ACTION_PACKAGE_RESTARTED)) { 1699 synchronized (mLock) { 1700 int uid = intent.getIntExtra(Intent.EXTRA_UID, -1); 1701 if (uid >= 0) { 1702 ArrayList<Receiver> removedRecs = null; 1703 for (ArrayList<UpdateRecord> i : mRecordsByProvider.values()) { 1704 for (int j=i.size()-1; j>=0; j--) { 1705 UpdateRecord ur = i.get(j); 1706 if (ur.mReceiver.isPendingIntent() && ur.mUid == uid) { 1707 if (removedRecs == null) { 1708 removedRecs = new ArrayList<Receiver>(); 1709 } 1710 if (!removedRecs.contains(ur.mReceiver)) { 1711 removedRecs.add(ur.mReceiver); 1712 } 1713 } 1714 } 1715 } 1716 ArrayList<ProximityAlert> removedAlerts = null; 1717 for (ProximityAlert i : mProximityAlerts.values()) { 1718 if (i.mUid == uid) { 1719 if (removedAlerts == null) { 1720 removedAlerts = new ArrayList<ProximityAlert>(); 1721 } 1722 if (!removedAlerts.contains(i)) { 1723 removedAlerts.add(i); 1724 } 1725 } 1726 } 1727 if (removedRecs != null) { 1728 for (int i=removedRecs.size()-1; i>=0; i--) { 1729 removeUpdatesLocked(removedRecs.get(i)); 1730 } 1731 } 1732 if (removedAlerts != null) { 1733 for (int i=removedAlerts.size()-1; i>=0; i--) { 1734 removeProximityAlertLocked(removedAlerts.get(i).mIntent); 1735 } 1736 } 1737 } 1738 } 1739 } 1740 } 1741 } 1742 1743 private class NetworkStateBroadcastReceiver extends BroadcastReceiver { 1744 @Override public void onReceive(Context context, Intent intent) { 1745 String action = intent.getAction(); 1746 1747 if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) { 1748 boolean noConnectivity = 1749 intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false); 1750 if (!noConnectivity) { 1751 mNetworkState = LocationProvider.AVAILABLE; 1752 } else { 1753 mNetworkState = LocationProvider.TEMPORARILY_UNAVAILABLE; 1754 } 1755 1756 // Notify location providers of current network state 1757 synchronized (mLock) { 1758 List<LocationProviderImpl> providers = LocationProviderImpl.getProviders(); 1759 for (LocationProviderImpl provider : providers) { 1760 if (provider.requiresNetwork()) { 1761 provider.updateNetworkState(mNetworkState); 1762 } 1763 } 1764 } 1765 } else if (action.equals(GpsLocationProvider.GPS_ENABLED_CHANGE_ACTION)) { 1766 1767 final boolean enabled = intent.getBooleanExtra(GpsLocationProvider.EXTRA_ENABLED, 1768 false); 1769 1770 synchronized (mLock) { 1771 if (!enabled) { 1772 // When GPS is disabled, we are OK to release wake-lock 1773 mWakeLockGpsReceived = true; 1774 } 1775 } 1776 } 1777 1778 } 1779 } 1780 1781 // Wake locks 1782 1783 private void updateWakelockStatusLocked(boolean screenOn) { 1784 log("updateWakelockStatus(): " + screenOn); 1785 1786 long callerId = Binder.clearCallingIdentity(); 1787 1788 boolean needsLock = false; 1789 long minTime = Integer.MAX_VALUE; 1790 1791 if (mNetworkLocationProvider != null && mNetworkLocationProvider.isLocationTracking()) { 1792 needsLock = true; 1793 minTime = Math.min(mNetworkLocationProvider.getMinTime(), minTime); 1794 } 1795 1796 if (mGpsLocationProvider != null && mGpsLocationProvider.isLocationTracking()) { 1797 needsLock = true; 1798 minTime = Math.min(mGpsLocationProvider.getMinTime(), minTime); 1799 } 1800 1801 mScreenOn = screenOn; 1802 1803 PendingIntent sender = 1804 PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_INTENT), 0); 1805 1806 // Cancel existing alarm 1807 log("Cancelling existing alarm"); 1808 mAlarmManager.cancel(sender); 1809 1810 if (needsLock && !mScreenOn) { 1811 long now = SystemClock.elapsedRealtime(); 1812 mAlarmManager.set( 1813 AlarmManager.ELAPSED_REALTIME_WAKEUP, now + minTime, sender); 1814 mAlarmInterval = minTime; 1815 log("Creating a new wakelock alarm with minTime = " + minTime); 1816 } else { 1817 log("No need for alarm"); 1818 mAlarmInterval = -1; 1819 1820 // Clear out existing wakelocks 1821 mLocationHandler.removeMessages(MESSAGE_ACQUIRE_WAKE_LOCK); 1822 mLocationHandler.removeMessages(MESSAGE_RELEASE_WAKE_LOCK); 1823 releaseWakeLockLocked(); 1824 } 1825 Binder.restoreCallingIdentity(callerId); 1826 } 1827 1828 private void acquireWakeLockLocked() { 1829 try { 1830 acquireWakeLockXLocked(); 1831 } catch (Exception e) { 1832 // This is to catch a runtime exception thrown when we try to release an 1833 // already released lock. 1834 Log.e(TAG, "exception in acquireWakeLock()", e); 1835 } 1836 } 1837 1838 private void acquireWakeLockXLocked() { 1839 if (mWakeLock.isHeld()) { 1840 log("Must release wakelock before acquiring"); 1841 mWakeLockAcquireTime = 0; 1842 mWakeLock.release(); 1843 } 1844 1845 boolean networkActive = (mNetworkLocationProvider != null) 1846 && mNetworkLocationProvider.isLocationTracking(); 1847 boolean gpsActive = (mGpsLocationProvider != null) 1848 && mGpsLocationProvider.isLocationTracking(); 1849 1850 boolean needsLock = networkActive || gpsActive; 1851 if (!needsLock) { 1852 log("No need for Lock!"); 1853 return; 1854 } 1855 1856 mWakeLockGpsReceived = !gpsActive; 1857 mWakeLockNetworkReceived = !networkActive; 1858 1859 // Acquire wake lock 1860 mWakeLock.acquire(); 1861 mWakeLockAcquireTime = SystemClock.elapsedRealtime(); 1862 log("Acquired wakelock"); 1863 1864 // Acquire cell lock 1865 if (mCellWakeLockAcquired) { 1866 // Lock is already acquired 1867 } else if (!mWakeLockNetworkReceived) { 1868 mTelephonyManager.enableLocationUpdates(); 1869 mCellWakeLockAcquired = true; 1870 } else { 1871 mCellWakeLockAcquired = false; 1872 } 1873 1874 // Notify NetworkLocationProvider 1875 if (mNetworkLocationProvider != null) { 1876 mNetworkLocationProvider.updateCellLockStatus(mCellWakeLockAcquired); 1877 } 1878 1879 // Acquire wifi lock 1880 WifiManager.WifiLock wifiLock = getWifiWakelockLocked(); 1881 if (wifiLock != null) { 1882 if (mWifiWakeLockAcquired) { 1883 // Lock is already acquired 1884 } else if (mWifiManager.isWifiEnabled() && !mWakeLockNetworkReceived) { 1885 wifiLock.acquire(); 1886 mWifiWakeLockAcquired = true; 1887 } else { 1888 mWifiWakeLockAcquired = false; 1889 Log.w(TAG, "acquireWakeLock(): Unable to get WiFi lock"); 1890 } 1891 } 1892 } 1893 1894 private void releaseWakeLockLocked() { 1895 try { 1896 releaseWakeLockXLocked(); 1897 } catch (Exception e) { 1898 // This is to catch a runtime exception thrown when we try to release an 1899 // already released lock. 1900 Log.e(TAG, "exception in releaseWakeLock()", e); 1901 } 1902 } 1903 1904 private void releaseWakeLockXLocked() { 1905 // Release wifi lock 1906 WifiManager.WifiLock wifiLock = getWifiWakelockLocked(); 1907 if (wifiLock != null) { 1908 if (mWifiWakeLockAcquired) { 1909 wifiLock.release(); 1910 mWifiWakeLockAcquired = false; 1911 } 1912 } 1913 1914 // Release cell lock 1915 if (mCellWakeLockAcquired) { 1916 mTelephonyManager.disableLocationUpdates(); 1917 mCellWakeLockAcquired = false; 1918 } 1919 1920 // Notify NetworkLocationProvider 1921 if (mNetworkLocationProvider != null) { 1922 mNetworkLocationProvider.updateCellLockStatus(mCellWakeLockAcquired); 1923 } 1924 1925 // Release wake lock 1926 mWakeLockAcquireTime = 0; 1927 if (mWakeLock.isHeld()) { 1928 log("Released wakelock"); 1929 mWakeLock.release(); 1930 } else { 1931 log("Can't release wakelock again!"); 1932 } 1933 } 1934 1935 // Geocoder 1936 1937 public String getFromLocation(double latitude, double longitude, int maxResults, 1938 String language, String country, String variant, String appName, List<Address> addrs) { 1939 if (mGeocodeProvider != null) { 1940 try { 1941 return mGeocodeProvider.getFromLocation(latitude, longitude, maxResults, language, country, 1942 variant, appName, addrs); 1943 } catch (RemoteException e) { 1944 Log.e(TAG, "getFromLocation failed", e); 1945 } 1946 } 1947 return null; 1948 } 1949 1950 1951 public String getFromLocationName(String locationName, 1952 double lowerLeftLatitude, double lowerLeftLongitude, 1953 double upperRightLatitude, double upperRightLongitude, int maxResults, 1954 String language, String country, String variant, String appName, List<Address> addrs) { 1955 1956 if (mGeocodeProvider != null) { 1957 try { 1958 return mGeocodeProvider.getFromLocationName(locationName, lowerLeftLatitude, 1959 lowerLeftLongitude, upperRightLatitude, upperRightLongitude, 1960 maxResults, language, country, variant, appName, addrs); 1961 } catch (RemoteException e) { 1962 Log.e(TAG, "getFromLocationName failed", e); 1963 } 1964 } 1965 return null; 1966 } 1967 1968 // Mock Providers 1969 1970 private void checkMockPermissionsSafe() { 1971 boolean allowMocks = Settings.Secure.getInt(mContext.getContentResolver(), 1972 Settings.Secure.ALLOW_MOCK_LOCATION, 0) == 1; 1973 if (!allowMocks) { 1974 throw new SecurityException("Requires ACCESS_MOCK_LOCATION secure setting"); 1975 } 1976 1977 if (mContext.checkCallingPermission(ACCESS_MOCK_LOCATION) != 1978 PackageManager.PERMISSION_GRANTED) { 1979 throw new SecurityException("Requires ACCESS_MOCK_LOCATION permission"); 1980 } 1981 } 1982 1983 public void addTestProvider(String name, boolean requiresNetwork, boolean requiresSatellite, 1984 boolean requiresCell, boolean hasMonetaryCost, boolean supportsAltitude, 1985 boolean supportsSpeed, boolean supportsBearing, int powerRequirement, int accuracy) { 1986 checkMockPermissionsSafe(); 1987 1988 synchronized (mLock) { 1989 MockProvider provider = new MockProvider(name, this, 1990 requiresNetwork, requiresSatellite, 1991 requiresCell, hasMonetaryCost, supportsAltitude, 1992 supportsSpeed, supportsBearing, powerRequirement, accuracy); 1993 if (LocationProviderImpl.getProvider(name) != null) { 1994 throw new IllegalArgumentException("Provider \"" + name + "\" already exists"); 1995 } 1996 LocationProviderImpl.addProvider(provider); 1997 mMockProviders.put(name, provider); 1998 updateProvidersLocked(); 1999 } 2000 } 2001 2002 public void removeTestProvider(String provider) { 2003 checkMockPermissionsSafe(); 2004 synchronized (mLock) { 2005 MockProvider mockProvider = mMockProviders.get(provider); 2006 if (mockProvider == null) { 2007 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 2008 } 2009 LocationProviderImpl.removeProvider(mockProvider); 2010 mMockProviders.remove(mockProvider); 2011 updateProvidersLocked(); 2012 } 2013 } 2014 2015 public void setTestProviderLocation(String provider, Location loc) { 2016 checkMockPermissionsSafe(); 2017 synchronized (mLock) { 2018 MockProvider mockProvider = mMockProviders.get(provider); 2019 if (mockProvider == null) { 2020 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 2021 } 2022 mockProvider.setLocation(loc); 2023 } 2024 } 2025 2026 public void clearTestProviderLocation(String provider) { 2027 checkMockPermissionsSafe(); 2028 synchronized (mLock) { 2029 MockProvider mockProvider = mMockProviders.get(provider); 2030 if (mockProvider == null) { 2031 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 2032 } 2033 mockProvider.clearLocation(); 2034 } 2035 } 2036 2037 public void setTestProviderEnabled(String provider, boolean enabled) { 2038 checkMockPermissionsSafe(); 2039 synchronized (mLock) { 2040 MockProvider mockProvider = mMockProviders.get(provider); 2041 if (mockProvider == null) { 2042 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 2043 } 2044 if (enabled) { 2045 mockProvider.enable(); 2046 mEnabledProviders.add(provider); 2047 mDisabledProviders.remove(provider); 2048 } else { 2049 mockProvider.disable(); 2050 mEnabledProviders.remove(provider); 2051 mDisabledProviders.add(provider); 2052 } 2053 updateProvidersLocked(); 2054 } 2055 } 2056 2057 public void clearTestProviderEnabled(String provider) { 2058 checkMockPermissionsSafe(); 2059 synchronized (mLock) { 2060 MockProvider mockProvider = mMockProviders.get(provider); 2061 if (mockProvider == null) { 2062 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 2063 } 2064 mEnabledProviders.remove(provider); 2065 mDisabledProviders.remove(provider); 2066 updateProvidersLocked(); 2067 } 2068 } 2069 2070 public void setTestProviderStatus(String provider, int status, Bundle extras, long updateTime) { 2071 checkMockPermissionsSafe(); 2072 synchronized (mLock) { 2073 MockProvider mockProvider = mMockProviders.get(provider); 2074 if (mockProvider == null) { 2075 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 2076 } 2077 mockProvider.setStatus(status, extras, updateTime); 2078 } 2079 } 2080 2081 public void clearTestProviderStatus(String provider) { 2082 checkMockPermissionsSafe(); 2083 synchronized (mLock) { 2084 MockProvider mockProvider = mMockProviders.get(provider); 2085 if (mockProvider == null) { 2086 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 2087 } 2088 mockProvider.clearStatus(); 2089 } 2090 } 2091 2092 private void log(String log) { 2093 if (Log.isLoggable(TAG, Log.VERBOSE)) { 2094 Log.d(TAG, log); 2095 } 2096 } 2097 2098 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 2099 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 2100 != PackageManager.PERMISSION_GRANTED) { 2101 pw.println("Permission Denial: can't dump AlarmManager from from pid=" 2102 + Binder.getCallingPid() 2103 + ", uid=" + Binder.getCallingUid()); 2104 return; 2105 } 2106 2107 synchronized (mLock) { 2108 pw.println("Current Location Manager state:"); 2109 pw.println(" sProvidersLoaded=" + sProvidersLoaded); 2110 pw.println(" mGpsLocationProvider=" + mGpsLocationProvider); 2111 pw.println(" mNetworkLocationProvider=" + mNetworkLocationProvider); 2112 pw.println(" mCollector=" + mCollector); 2113 pw.println(" mAlarmInterval=" + mAlarmInterval 2114 + " mScreenOn=" + mScreenOn 2115 + " mWakeLockAcquireTime=" + mWakeLockAcquireTime); 2116 pw.println(" mWakeLockGpsReceived=" + mWakeLockGpsReceived 2117 + " mWakeLockNetworkReceived=" + mWakeLockNetworkReceived); 2118 pw.println(" mWifiWakeLockAcquired=" + mWifiWakeLockAcquired 2119 + " mCellWakeLockAcquired=" + mCellWakeLockAcquired); 2120 pw.println(" Listeners:"); 2121 int N = mReceivers.size(); 2122 for (int i=0; i<N; i++) { 2123 pw.println(" " + mReceivers.get(i)); 2124 } 2125 pw.println(" Location Listeners:"); 2126 for (Receiver i : mReceivers.values()) { 2127 pw.println(" " + i + ":"); 2128 for (Map.Entry<String,UpdateRecord> j : i.mUpdateRecords.entrySet()) { 2129 pw.println(" " + j.getKey() + ":"); 2130 j.getValue().dump(pw, " "); 2131 } 2132 } 2133 pw.println(" Records by Provider:"); 2134 for (Map.Entry<String, ArrayList<UpdateRecord>> i 2135 : mRecordsByProvider.entrySet()) { 2136 pw.println(" " + i.getKey() + ":"); 2137 for (UpdateRecord j : i.getValue()) { 2138 pw.println(" " + j + ":"); 2139 j.dump(pw, " "); 2140 } 2141 } 2142 pw.println(" Last Known Locations:"); 2143 for (Map.Entry<String, Location> i 2144 : mLastKnownLocation.entrySet()) { 2145 pw.println(" " + i.getKey() + ":"); 2146 i.getValue().dump(new PrintWriterPrinter(pw), " "); 2147 } 2148 if (mProximityAlerts.size() > 0) { 2149 pw.println(" Proximity Alerts:"); 2150 for (Map.Entry<PendingIntent, ProximityAlert> i 2151 : mProximityAlerts.entrySet()) { 2152 pw.println(" " + i.getKey() + ":"); 2153 i.getValue().dump(pw, " "); 2154 } 2155 } 2156 if (mProximitiesEntered.size() > 0) { 2157 pw.println(" Proximities Entered:"); 2158 for (ProximityAlert i : mProximitiesEntered) { 2159 pw.println(" " + i + ":"); 2160 i.dump(pw, " "); 2161 } 2162 } 2163 pw.println(" mProximityListener=" + mProximityListener); 2164 if (mEnabledProviders.size() > 0) { 2165 pw.println(" Enabled Providers:"); 2166 for (String i : mEnabledProviders) { 2167 pw.println(" " + i); 2168 } 2169 2170 } 2171 if (mDisabledProviders.size() > 0) { 2172 pw.println(" Disabled Providers:"); 2173 for (String i : mDisabledProviders) { 2174 pw.println(" " + i); 2175 } 2176 2177 } 2178 if (mMockProviders.size() > 0) { 2179 pw.println(" Mock Providers:"); 2180 for (Map.Entry<String, MockProvider> i : mMockProviders.entrySet()) { 2181 i.getValue().dump(pw, " "); 2182 } 2183 } 2184 } 2185 } 2186} 2187