summaryrefslogtreecommitdiffstats
path: root/services/java/com/android/server/LocationManagerService.java
diff options
context:
space:
mode:
Diffstat (limited to 'services/java/com/android/server/LocationManagerService.java')
-rw-r--r--services/java/com/android/server/LocationManagerService.java203
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;
}