diff options
Diffstat (limited to 'services/java/com/android/server/LocationManagerService.java')
-rw-r--r-- | services/java/com/android/server/LocationManagerService.java | 203 |
1 files changed, 72 insertions, 131 deletions
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java index e219e8d..23b2706 100644 --- a/services/java/com/android/server/LocationManagerService.java +++ b/services/java/com/android/server/LocationManagerService.java @@ -47,7 +47,6 @@ import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.Message; -import android.os.Parcelable; import android.os.PowerManager; import android.os.Process; import android.os.RemoteException; @@ -64,6 +63,8 @@ import com.android.internal.location.ProviderRequest; import com.android.server.location.GeocoderProxy; import com.android.server.location.GeofenceManager; import com.android.server.location.GpsLocationProvider; +import com.android.server.location.LocationBlacklist; +import com.android.server.location.LocationFudger; import com.android.server.location.LocationProviderInterface; import com.android.server.location.LocationProviderProxy; import com.android.server.location.MockProvider; @@ -110,19 +111,6 @@ public class LocationManagerService extends ILocationManager.Stub implements Obs private static final int MSG_LOCATION_CHANGED = 1; - // Accuracy in meters above which a location is considered coarse - private static final double COARSE_ACCURACY_M = 100.0; - private static final String EXTRA_COARSE_LOCATION = "coarseLocation"; - - private static final int APPROXIMATE_METERS_PER_DEGREE_AT_EQUATOR = 111000; - - /** - * Maximum latitude of 1 meter from the pole. - * This keeps cosine(MAX_LATITUDE) to a non-zero value; - */ - private static final double MAX_LATITUDE = - 90.0 - (1.0 / APPROXIMATE_METERS_PER_DEGREE_AT_EQUATOR); - // 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 @@ -137,6 +125,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Obs private final Object mLock = new Object(); // --- fields below are final after init() --- + private LocationFudger mLocationFudger; private GeofenceManager mGeofenceManager; private PowerManager.WakeLock mWakeLock; private PackageManager mPackageManager; @@ -144,8 +133,8 @@ public class LocationManagerService extends ILocationManager.Stub implements Obs private IGpsStatusProvider mGpsStatusProvider; private INetInitiatedListener mNetInitiatedListener; private LocationWorkerHandler mLocationHandler; - // track the passive provider for some special cases - private PassiveProvider mPassiveProvider; + private PassiveProvider mPassiveProvider; // track passive provider for special cases + private LocationBlacklist mBlacklist; // --- fields below are protected by mWakeLock --- private int mPendingBroadcasts; @@ -220,7 +209,10 @@ public class LocationManagerService extends ILocationManager.Stub implements Obs synchronized (mLock) { loadProvidersLocked(); } - mGeofenceManager = new GeofenceManager(mContext); + mBlacklist = new LocationBlacklist(mContext, mLocationHandler); + mBlacklist.init(); + mGeofenceManager = new GeofenceManager(mContext, mBlacklist); + mLocationFudger = new LocationFudger(); // Register for Network (Wifi or Mobile) updates IntentFilter filter = new IntentFilter(); @@ -907,7 +899,25 @@ public class LocationManagerService extends ILocationManager.Stub implements Obs String perm = checkPermission(); if (ACCESS_COARSE_LOCATION.equals(perm)) { - request.applyCoarsePermissionRestrictions(); + switch (request.getQuality()) { + case LocationRequest.ACCURACY_FINE: + request.setQuality(LocationRequest.ACCURACY_BLOCK); + break; + case LocationRequest.POWER_HIGH: + request.setQuality(LocationRequest.POWER_LOW); + break; + } + // throttle + if (request.getInterval() < LocationFudger.FASTEST_INTERVAL_MS) { + request.setInterval(LocationFudger.FASTEST_INTERVAL_MS); + } + if (request.getFastestInterval() < LocationFudger.FASTEST_INTERVAL_MS) { + request.setFastestInterval(LocationFudger.FASTEST_INTERVAL_MS); + } + } + // make getFastestInterval() the minimum of interval and fastest interval + if (request.getFastestInterval() > request.getInterval()) { + request.setFastestInterval(request.getInterval()); } return perm; } @@ -958,7 +968,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Obs final int uid = Binder.getCallingUid(); Receiver recevier = checkListenerOrIntent(listener, intent, pid, uid, packageName); - // so wakelock calls will succeed (not totally sure this is still needed) + // providers may use public location API's, need to clear identity long identity = Binder.clearCallingIdentity(); try { synchronized (mLock) { @@ -1008,7 +1018,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Obs final int uid = Binder.getCallingUid(); Receiver receiver = checkListenerOrIntent(listener, intent, pid, uid, packageName); - // so wakelock calls will succeed (not totally sure this is still needed) + // providers may use public location API's, need to clear identity long identity = Binder.clearCallingIdentity(); try { synchronized (mLock) { @@ -1056,10 +1066,17 @@ public class LocationManagerService extends ILocationManager.Stub implements Obs } @Override - public Location getLastLocation(LocationRequest request) { + public Location getLastLocation(LocationRequest request, String packageName) { if (D) Log.d(TAG, "getLastLocation: " + request); if (request == null) request = DEFAULT_LOCATION_REQUEST; String perm = checkPermissionAndRequest(request); + checkPackageName(packageName); + + if (mBlacklist.isBlacklisted(packageName)) { + if (D) Log.d(TAG, "not returning last loc for blacklisted app: " + + packageName); + return null; + } synchronized (mLock) { // Figure out the provider. Either its explicitly request (deprecated API's), @@ -1075,7 +1092,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Obs if (ACCESS_FINE_LOCATION.equals(perm)) { return location; } else { - return getCoarseLocationExtra(location); + return mLocationFudger.getOrCreate(location); } } } @@ -1090,7 +1107,14 @@ public class LocationManagerService extends ILocationManager.Stub implements Obs if (D) Log.d(TAG, "requestGeofence: " + request + " " + geofence + " " + intent); - mGeofenceManager.addFence(request, geofence, intent, Binder.getCallingUid(), packageName); + // geo-fence manager uses the public location API, need to clear identity + int uid = Binder.getCallingUid(); + long identity = Binder.clearCallingIdentity(); + try { + mGeofenceManager.addFence(request, geofence, intent, uid, packageName); + } finally { + Binder.restoreCallingIdentity(identity); + } } @Override @@ -1101,7 +1125,13 @@ public class LocationManagerService extends ILocationManager.Stub implements Obs if (D) Log.d(TAG, "removeGeofence: " + geofence + " " + intent); - mGeofenceManager.removeFence(geofence, intent); + // geo-fence manager uses the public location API, need to clear identity + long identity = Binder.clearCallingIdentity(); + try { + mGeofenceManager.removeFence(geofence, intent); + } finally { + Binder.restoreCallingIdentity(identity); + } } @@ -1283,6 +1313,8 @@ public class LocationManagerService extends ILocationManager.Stub implements Obs } private void handleLocationChangedLocked(Location location, boolean passive) { + if (D) Log.d(TAG, "incoming location: " + location); + long now = SystemClock.elapsedRealtime(); String provider = (passive ? LocationManager.PASSIVE_PROVIDER : location.getProvider()); ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider); @@ -1291,11 +1323,8 @@ public class LocationManagerService extends ILocationManager.Stub implements Obs LocationProviderInterface p = mProvidersByName.get(provider); if (p == null) return; - // Add the coarse location as an extra, if not already present - Location coarse = getCoarseLocationExtra(location); - if (coarse == null) { - coarse = addCoarseLocationExtra(location); - } + // Add the coarse location as an extra + Location coarse = mLocationFudger.getOrCreate(location); // Update last known locations Location lastLocation = mLastLocation.get(provider); @@ -1319,6 +1348,13 @@ public class LocationManagerService extends ILocationManager.Stub implements Obs for (UpdateRecord r : records) { Receiver receiver = r.mReceiver; boolean receiverDead = false; + + if (mBlacklist.isBlacklisted(receiver.mPackageName)) { + if (D) Log.d(TAG, "skipping loc update for blacklisted app: " + + receiver.mPackageName); + continue; + } + if (ACCESS_FINE_LOCATION.equals(receiver.mPermission)) { location = lastLocation; // use fine location } else { @@ -1530,7 +1566,8 @@ public class LocationManagerService extends ILocationManager.Stub implements Obs MockProvider provider = new MockProvider(name, this, properties); // remove the real provider if we are replacing GPS or network provider if (LocationManager.GPS_PROVIDER.equals(name) - || LocationManager.NETWORK_PROVIDER.equals(name)) { + || LocationManager.NETWORK_PROVIDER.equals(name) + || LocationManager.FUSED_PROVIDER.equals(name)) { LocationProviderInterface p = mProvidersByName.get(name); if (p != null) { removeProviderLocked(p); @@ -1660,106 +1697,6 @@ public class LocationManagerService extends ILocationManager.Stub implements Obs } } - private static double wrapLatitude(double lat) { - if (lat > MAX_LATITUDE) lat = MAX_LATITUDE; - if (lat < -MAX_LATITUDE) lat = -MAX_LATITUDE; - return lat; - } - - private static double wrapLongitude(double lon) { - if (lon >= 180.0) lon -= 360.0; - if (lon < -180.0) lon += 360.0; - return lon; - } - - private static double distanceToDegreesLatitude(double distance) { - return distance / APPROXIMATE_METERS_PER_DEGREE_AT_EQUATOR; - } - - /** - * Requires latitude since longitudinal distances change with distance from equator. - */ - private static double distanceToDegreesLongitude(double distance, double lat) { - return distance / APPROXIMATE_METERS_PER_DEGREE_AT_EQUATOR / Math.cos(lat); - } - - /** - * Fudge a location into a coarse location. - * <p>Add a random offset, then quantize the result (snap-to-grid). - * Random offsets alone can be low-passed pretty easily. - * Snap-to-grid on its own is excellent unless you are sitting on a - * grid boundary and bouncing between quantizations. - * The combination is quite hard to reverse engineer. - * <p>The random offset used is smaller than the goal accuracy - * ({@link #COARSE_ACCURACY_M}), in order to give relatively stable - * results after quantization. - */ - private static Location createCoarse(Location fine) { - Location coarse = new Location(fine); - - coarse.removeBearing(); - coarse.removeSpeed(); - coarse.removeAltitude(); - - double lat = coarse.getLatitude(); - double lon = coarse.getLongitude(); - - // wrap - lat = wrapLatitude(lat); - lon = wrapLongitude(lon); - - if (coarse.getAccuracy() < COARSE_ACCURACY_M / 2) { - // apply a random offset - double fudgeDistance = COARSE_ACCURACY_M / 2.0 - coarse.getAccuracy(); - lat += (Math.random() - 0.5) * distanceToDegreesLatitude(fudgeDistance); - lon += (Math.random() - 0.5) * distanceToDegreesLongitude(fudgeDistance, lat); - } - - // wrap - lat = wrapLatitude(lat); - lon = wrapLongitude(lon); - - // quantize (snap-to-grid) - double latGranularity = distanceToDegreesLatitude(COARSE_ACCURACY_M); - double lonGranularity = distanceToDegreesLongitude(COARSE_ACCURACY_M, lat); - long latQuantized = Math.round(lat / latGranularity); - long lonQuantized = Math.round(lon / lonGranularity); - lat = latQuantized * latGranularity; - lon = lonQuantized * lonGranularity; - - // wrap again - lat = wrapLatitude(lat); - lon = wrapLongitude(lon); - - // apply - coarse.setLatitude(lat); - coarse.setLongitude(lon); - coarse.setAccuracy((float)COARSE_ACCURACY_M); - - return coarse; - } - - - private static Location getCoarseLocationExtra(Location location) { - Bundle extras = location.getExtras(); - if (extras == null) return null; - Parcelable parcel = extras.getParcelable(EXTRA_COARSE_LOCATION); - if (parcel == null) return null; - if (!(parcel instanceof Location)) return null; - Location coarse = (Location) parcel; - if (coarse.getAccuracy() < COARSE_ACCURACY_M) return null; - return coarse; - } - - private static Location addCoarseLocationExtra(Location location) { - Bundle extras = location.getExtras(); - if (extras == null) extras = new Bundle(); - Location coarse = createCoarse(location); - extras.putParcelable(EXTRA_COARSE_LOCATION, coarse); - location.setExtras(extras); - return coarse; - } - private void log(String log) { if (Log.isLoggable(TAG, Log.VERBOSE)) { Slog.d(TAG, log); @@ -1810,8 +1747,9 @@ public class LocationManagerService extends ILocationManager.Stub implements Obs for (String i : mDisabledProviders) { pw.println(" " + i); } - } + pw.append(" "); + mBlacklist.dump(pw); if (mMockProviders.size() > 0) { pw.println(" Mock Providers:"); for (Map.Entry<String, MockProvider> i : mMockProviders.entrySet()) { @@ -1819,6 +1757,9 @@ public class LocationManagerService extends ILocationManager.Stub implements Obs } } + pw.append(" fudger: "); + mLocationFudger.dump(fd, pw, args); + if (args.length > 0 && "short".equals(args[0])) { return; } |