diff options
Diffstat (limited to 'services/java/com/android/server/LocationManagerService.java')
-rw-r--r-- | services/java/com/android/server/LocationManagerService.java | 66 |
1 files changed, 57 insertions, 9 deletions
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java index bcb7cb7..b47e8a0 100644 --- a/services/java/com/android/server/LocationManagerService.java +++ b/services/java/com/android/server/LocationManagerService.java @@ -54,19 +54,17 @@ import android.os.Message; import android.os.PowerManager; import android.os.Process; import android.os.RemoteException; -import android.os.ServiceManager; import android.os.SystemClock; import android.os.UserHandle; import android.os.WorkSource; import android.provider.Settings; import android.util.Log; import android.util.Slog; - -import com.android.internal.app.IAppOpsService; import com.android.internal.content.PackageMonitor; import com.android.internal.location.ProviderProperties; import com.android.internal.location.ProviderRequest; import com.android.server.location.GeocoderProxy; +import com.android.server.location.GeofenceProxy; import com.android.server.location.GeofenceManager; import com.android.server.location.GpsLocationProvider; import com.android.server.location.LocationBlacklist; @@ -118,6 +116,8 @@ public class LocationManagerService extends ILocationManager.Stub { private static final int MSG_LOCATION_CHANGED = 1; + private static final long NANOS_PER_MILLI = 1000000L; + // Location Providers may sometimes deliver location updates // slightly faster that requested - provide grace period so // we don't unnecessarily filter events that are otherwise on @@ -181,6 +181,11 @@ public class LocationManagerService extends ILocationManager.Stub { // mapping from provider name to last known location private final HashMap<String, Location> mLastLocation = new HashMap<String, Location>(); + // same as mLastLocation, but is not updated faster than LocationFudger.FASTEST_INTERVAL_MS. + // locations stored here are not fudged for coarse permissions. + private final HashMap<String, Location> mLastLocationCoarseInterval = + new HashMap<String, Location>(); + // all providers that operate over proxy, for authorizing incoming location private final ArrayList<LocationProviderProxy> mProxyProviders = new ArrayList<LocationProviderProxy>(); @@ -338,11 +343,11 @@ public class LocationManagerService extends ILocationManager.Stub { addProviderLocked(passiveProvider); mEnabledProviders.add(passiveProvider.getName()); mPassiveProvider = passiveProvider; + // Create a gps location provider + GpsLocationProvider gpsProvider = new GpsLocationProvider(mContext, this, + mLocationHandler.getLooper()); if (GpsLocationProvider.isSupported()) { - // Create a gps location provider - GpsLocationProvider gpsProvider = new GpsLocationProvider(mContext, this, - mLocationHandler.getLooper()); mGpsStatusProvider = gpsProvider.getGpsStatusProvider(); mNetInitiatedListener = gpsProvider.getNetInitiatedListener(); addProviderLocked(gpsProvider); @@ -406,6 +411,14 @@ public class LocationManagerService extends ILocationManager.Stub { if (mGeocodeProvider == null) { Slog.e(TAG, "no geocoder provider found"); } + + // bind to geofence provider + GeofenceProxy provider = GeofenceProxy.createAndBind(mContext, providerPackageNames, + mLocationHandler, gpsProvider.getGpsGeofenceProxy()); + if (provider == null) { + Slog.e(TAG, "no geofence provider found"); + } + } /** @@ -417,6 +430,7 @@ public class LocationManagerService extends ILocationManager.Stub { mLocationHandler.removeMessages(MSG_LOCATION_CHANGED); synchronized (mLock) { mLastLocation.clear(); + mLastLocationCoarseInterval.clear(); for (LocationProviderInterface p : mProviders) { updateProviderListenersLocked(p.getName(), false, mCurrentUserId); } @@ -1401,7 +1415,14 @@ public class LocationManagerService extends ILocationManager.Stub { if (!isAllowedByUserSettingsLocked(name, uid)) return null; - Location location = mLastLocation.get(name); + Location location; + if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) { + // Make sure that an app with coarse permissions can't get frequent location + // updates by calling LocationManager.getLastKnownLocation repeatedly. + location = mLastLocationCoarseInterval.get(name); + } else { + location = mLastLocation.get(name); + } if (location == null) { return null; } @@ -1667,7 +1688,8 @@ public class LocationManagerService extends ILocationManager.Stub { // Check whether sufficient time has passed long minTime = record.mRequest.getFastestInterval(); - long delta = (loc.getElapsedRealtimeNanos() - lastLoc.getElapsedRealtimeNanos()) / 1000000L; + long delta = (loc.getElapsedRealtimeNanos() - lastLoc.getElapsedRealtimeNanos()) + / NANOS_PER_MILLI; if (delta < minTime - MAX_PROVIDER_SCHEDULING_JITTER_MS) { return false; } @@ -1720,13 +1742,30 @@ public class LocationManagerService extends ILocationManager.Stub { } lastLocation.set(location); + // Update last known coarse interval location if enough time has passed. + Location lastLocationCoarseInterval = mLastLocationCoarseInterval.get(provider); + if (lastLocationCoarseInterval == null) { + lastLocationCoarseInterval = new Location(location); + mLastLocationCoarseInterval.put(provider, lastLocationCoarseInterval); + } + long timeDiffNanos = location.getElapsedRealtimeNanos() + - lastLocationCoarseInterval.getElapsedRealtimeNanos(); + if (timeDiffNanos > LocationFudger.FASTEST_INTERVAL_MS * NANOS_PER_MILLI) { + lastLocationCoarseInterval.set(location); + } + // Don't ever return a coarse location that is more recent than the allowed update + // interval (i.e. don't allow an app to keep registering and unregistering for + // location updates to overcome the minimum interval). + noGPSLocation = + lastLocationCoarseInterval.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION); + // Skip if there are no UpdateRecords for this provider. ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider); if (records == null || records.size() == 0) return; // Fetch coarse location Location coarseLocation = null; - if (noGPSLocation != null && !noGPSLocation.equals(lastNoGPSLocation)) { + if (noGPSLocation != null) { coarseLocation = mLocationFudger.getOrCreate(noGPSLocation); } @@ -2015,6 +2054,7 @@ public class LocationManagerService extends ILocationManager.Stub { addProviderLocked(provider); mMockProviders.put(name, provider); mLastLocation.put(name, null); + mLastLocationCoarseInterval.put(name, null); updateProvidersLocked(); } Binder.restoreCallingIdentity(identity); @@ -2037,6 +2077,7 @@ public class LocationManagerService extends ILocationManager.Stub { addProviderLocked(realProvider); } mLastLocation.put(provider, null); + mLastLocationCoarseInterval.put(provider, null); updateProvidersLocked(); Binder.restoreCallingIdentity(identity); } @@ -2168,6 +2209,13 @@ public class LocationManagerService extends ILocationManager.Stub { pw.println(" " + provider + ": " + location); } + pw.println(" Last Known Locations Coarse Intervals:"); + for (Map.Entry<String, Location> entry : mLastLocationCoarseInterval.entrySet()) { + String provider = entry.getKey(); + Location location = entry.getValue(); + pw.println(" " + provider + ": " + location); + } + mGeofenceManager.dump(pw); if (mEnabledProviders.size() > 0) { |