4747import android .os .IBinder ;
4848import android .os .Looper ;
4949import android .os .Message ;
50- import android .os .Parcelable ;
5150import android .os .PowerManager ;
5251import android .os .Process ;
5352import android .os .RemoteException ;
6463import com .android .server .location .GeocoderProxy ;
6564import com .android .server .location .GeofenceManager ;
6665import com .android .server .location .GpsLocationProvider ;
66+ import com .android .server .location .LocationFudger ;
6767import com .android .server .location .LocationProviderInterface ;
6868import com .android .server .location .LocationProviderProxy ;
6969import 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