Skip to content

Commit 60020e2

Browse files
Nick PellyAndroid (Google) Code Review
authored andcommitted
Merge "Improve coarse locations." into jb-mr1-dev
2 parents 2421439 + 74fa7ea commit 60020e2

File tree

3 files changed

+335
-135
lines changed

3 files changed

+335
-135
lines changed

location/java/android/location/LocationRequest.java

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -195,20 +195,6 @@ public float getSmallestDisplacement() {
195195
return mSmallestDisplacement;
196196
}
197197

198-
/** @hide */
199-
public LocationRequest applyCoarsePermissionRestrictions() {
200-
switch (mQuality) {
201-
case ACCURACY_FINE:
202-
mQuality = ACCURACY_BLOCK;
203-
break;
204-
}
205-
// cap fastest interval to 6 seconds
206-
if (mFastestInterval < 6 * 1000) mFastestInterval = 6 * 1000;
207-
// cap requested interval to 1 minute
208-
if (mInterval < 60 * 1000) mInterval = 60 * 1000;
209-
return this;
210-
}
211-
212198
private static void checkInterval(long millis) {
213199
if (millis < 0) {
214200
throw new IllegalArgumentException("invalid interval: " + millis);

services/java/com/android/server/LocationManagerService.java

Lines changed: 25 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@
4747
import android.os.IBinder;
4848
import android.os.Looper;
4949
import android.os.Message;
50-
import android.os.Parcelable;
5150
import android.os.PowerManager;
5251
import android.os.Process;
5352
import android.os.RemoteException;
@@ -64,6 +63,7 @@
6463
import com.android.server.location.GeocoderProxy;
6564
import com.android.server.location.GeofenceManager;
6665
import com.android.server.location.GpsLocationProvider;
66+
import com.android.server.location.LocationFudger;
6767
import com.android.server.location.LocationProviderInterface;
6868
import com.android.server.location.LocationProviderProxy;
6969
import com.android.server.location.MockProvider;
@@ -110,19 +110,6 @@ public class LocationManagerService extends ILocationManager.Stub implements Obs
110110

111111
private static final int MSG_LOCATION_CHANGED = 1;
112112

113-
// Accuracy in meters above which a location is considered coarse
114-
private static final double COARSE_ACCURACY_M = 100.0;
115-
private static final String EXTRA_COARSE_LOCATION = "coarseLocation";
116-
117-
private static final int APPROXIMATE_METERS_PER_DEGREE_AT_EQUATOR = 111000;
118-
119-
/**
120-
* Maximum latitude of 1 meter from the pole.
121-
* This keeps cosine(MAX_LATITUDE) to a non-zero value;
122-
*/
123-
private static final double MAX_LATITUDE =
124-
90.0 - (1.0 / APPROXIMATE_METERS_PER_DEGREE_AT_EQUATOR);
125-
126113
// Location Providers may sometimes deliver location updates
127114
// slightly faster that requested - provide grace period so
128115
// we don't unnecessarily filter events that are otherwise on
@@ -137,6 +124,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Obs
137124
private final Object mLock = new Object();
138125

139126
// --- fields below are final after init() ---
127+
private LocationFudger mLocationFudger;
140128
private GeofenceManager mGeofenceManager;
141129
private PowerManager.WakeLock mWakeLock;
142130
private PackageManager mPackageManager;
@@ -221,6 +209,7 @@ private void init() {
221209
loadProvidersLocked();
222210
}
223211
mGeofenceManager = new GeofenceManager(mContext);
212+
mLocationFudger = new LocationFudger();
224213

225214
// Register for Network (Wifi or Mobile) updates
226215
IntentFilter filter = new IntentFilter();
@@ -907,7 +896,22 @@ private String checkPermissionAndRequest(LocationRequest request) {
907896
String perm = checkPermission();
908897

909898
if (ACCESS_COARSE_LOCATION.equals(perm)) {
910-
request.applyCoarsePermissionRestrictions();
899+
switch (request.getQuality()) {
900+
case LocationRequest.ACCURACY_FINE:
901+
request.setQuality(LocationRequest.ACCURACY_BLOCK);
902+
break;
903+
case LocationRequest.POWER_HIGH:
904+
request.setQuality(LocationRequest.POWER_LOW);
905+
break;
906+
}
907+
// throttle fastest interval
908+
if (request.getFastestInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
909+
request.setFastestInterval(LocationFudger.FASTEST_INTERVAL_MS);
910+
}
911+
}
912+
// throttle interval if its faster than the fastest interval
913+
if (request.getInterval () < request.getFastestInterval()) {
914+
request.setInterval(request.getFastestInterval());
911915
}
912916
return perm;
913917
}
@@ -1075,7 +1079,7 @@ public Location getLastLocation(LocationRequest request) {
10751079
if (ACCESS_FINE_LOCATION.equals(perm)) {
10761080
return location;
10771081
} else {
1078-
return getCoarseLocationExtra(location);
1082+
return mLocationFudger.getOrCreate(location);
10791083
}
10801084
}
10811085
}
@@ -1291,11 +1295,8 @@ private void handleLocationChangedLocked(Location location, boolean passive) {
12911295
LocationProviderInterface p = mProvidersByName.get(provider);
12921296
if (p == null) return;
12931297

1294-
// Add the coarse location as an extra, if not already present
1295-
Location coarse = getCoarseLocationExtra(location);
1296-
if (coarse == null) {
1297-
coarse = addCoarseLocationExtra(location);
1298-
}
1298+
// Add the coarse location as an extra
1299+
Location coarse = mLocationFudger.getOrCreate(location);
12991300

13001301
// Update last known locations
13011302
Location lastLocation = mLastLocation.get(provider);
@@ -1660,106 +1661,6 @@ public void clearTestProviderStatus(String provider) {
16601661
}
16611662
}
16621663

1663-
private static double wrapLatitude(double lat) {
1664-
if (lat > MAX_LATITUDE) lat = MAX_LATITUDE;
1665-
if (lat < -MAX_LATITUDE) lat = -MAX_LATITUDE;
1666-
return lat;
1667-
}
1668-
1669-
private static double wrapLongitude(double lon) {
1670-
if (lon >= 180.0) lon -= 360.0;
1671-
if (lon < -180.0) lon += 360.0;
1672-
return lon;
1673-
}
1674-
1675-
private static double distanceToDegreesLatitude(double distance) {
1676-
return distance / APPROXIMATE_METERS_PER_DEGREE_AT_EQUATOR;
1677-
}
1678-
1679-
/**
1680-
* Requires latitude since longitudinal distances change with distance from equator.
1681-
*/
1682-
private static double distanceToDegreesLongitude(double distance, double lat) {
1683-
return distance / APPROXIMATE_METERS_PER_DEGREE_AT_EQUATOR / Math.cos(lat);
1684-
}
1685-
1686-
/**
1687-
* Fudge a location into a coarse location.
1688-
* <p>Add a random offset, then quantize the result (snap-to-grid).
1689-
* Random offsets alone can be low-passed pretty easily.
1690-
* Snap-to-grid on its own is excellent unless you are sitting on a
1691-
* grid boundary and bouncing between quantizations.
1692-
* The combination is quite hard to reverse engineer.
1693-
* <p>The random offset used is smaller than the goal accuracy
1694-
* ({@link #COARSE_ACCURACY_M}), in order to give relatively stable
1695-
* results after quantization.
1696-
*/
1697-
private static Location createCoarse(Location fine) {
1698-
Location coarse = new Location(fine);
1699-
1700-
coarse.removeBearing();
1701-
coarse.removeSpeed();
1702-
coarse.removeAltitude();
1703-
1704-
double lat = coarse.getLatitude();
1705-
double lon = coarse.getLongitude();
1706-
1707-
// wrap
1708-
lat = wrapLatitude(lat);
1709-
lon = wrapLongitude(lon);
1710-
1711-
if (coarse.getAccuracy() < COARSE_ACCURACY_M / 2) {
1712-
// apply a random offset
1713-
double fudgeDistance = COARSE_ACCURACY_M / 2.0 - coarse.getAccuracy();
1714-
lat += (Math.random() - 0.5) * distanceToDegreesLatitude(fudgeDistance);
1715-
lon += (Math.random() - 0.5) * distanceToDegreesLongitude(fudgeDistance, lat);
1716-
}
1717-
1718-
// wrap
1719-
lat = wrapLatitude(lat);
1720-
lon = wrapLongitude(lon);
1721-
1722-
// quantize (snap-to-grid)
1723-
double latGranularity = distanceToDegreesLatitude(COARSE_ACCURACY_M);
1724-
double lonGranularity = distanceToDegreesLongitude(COARSE_ACCURACY_M, lat);
1725-
long latQuantized = Math.round(lat / latGranularity);
1726-
long lonQuantized = Math.round(lon / lonGranularity);
1727-
lat = latQuantized * latGranularity;
1728-
lon = lonQuantized * lonGranularity;
1729-
1730-
// wrap again
1731-
lat = wrapLatitude(lat);
1732-
lon = wrapLongitude(lon);
1733-
1734-
// apply
1735-
coarse.setLatitude(lat);
1736-
coarse.setLongitude(lon);
1737-
coarse.setAccuracy((float)COARSE_ACCURACY_M);
1738-
1739-
return coarse;
1740-
}
1741-
1742-
1743-
private static Location getCoarseLocationExtra(Location location) {
1744-
Bundle extras = location.getExtras();
1745-
if (extras == null) return null;
1746-
Parcelable parcel = extras.getParcelable(EXTRA_COARSE_LOCATION);
1747-
if (parcel == null) return null;
1748-
if (!(parcel instanceof Location)) return null;
1749-
Location coarse = (Location) parcel;
1750-
if (coarse.getAccuracy() < COARSE_ACCURACY_M) return null;
1751-
return coarse;
1752-
}
1753-
1754-
private static Location addCoarseLocationExtra(Location location) {
1755-
Bundle extras = location.getExtras();
1756-
if (extras == null) extras = new Bundle();
1757-
Location coarse = createCoarse(location);
1758-
extras.putParcelable(EXTRA_COARSE_LOCATION, coarse);
1759-
location.setExtras(extras);
1760-
return coarse;
1761-
}
1762-
17631664
private void log(String log) {
17641665
if (Log.isLoggable(TAG, Log.VERBOSE)) {
17651666
Slog.d(TAG, log);
@@ -1819,6 +1720,9 @@ protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
18191720
}
18201721
}
18211722

1723+
pw.append(" fudger: ");
1724+
mLocationFudger.dump(fd, pw, args);
1725+
18221726
if (args.length > 0 && "short".equals(args[0])) {
18231727
return;
18241728
}

0 commit comments

Comments
 (0)