am 17e3e9e5: Merge "Do not use passive GPS data for COARSE only apps." into jb-mr1-dev

* commit '17e3e9e53c5fb9c92c8972a8d92659c6bef85831':
  Do not use passive GPS data for COARSE only apps.
This commit is contained in:
Victoria Lease
2012-09-24 09:28:41 -07:00
committed by Android Git Automerger
6 changed files with 126 additions and 53 deletions

View File

@@ -59,6 +59,16 @@ public class Location implements Parcelable {
*/ */
public static final int FORMAT_SECONDS = 2; public static final int FORMAT_SECONDS = 2;
/**
* @hide
*/
public static final String EXTRA_COARSE_LOCATION = "coarseLocation";
/**
* @hide
*/
public static final String EXTRA_NO_GPS_LOCATION = "noGPSLocation";
private String mProvider; private String mProvider;
private long mTime = 0; private long mTime = 0;
private long mElapsedRealtimeNano = 0; private long mElapsedRealtimeNano = 0;
@@ -893,4 +903,36 @@ public class Location implements Parcelable {
parcel.writeFloat(mAccuracy); parcel.writeFloat(mAccuracy);
parcel.writeBundle(mExtras); parcel.writeBundle(mExtras);
} }
/**
* Returns one of the optional extra {@link Location}s that can be attached
* to this Location.
*
* @param key the key associated with the desired extra Location
* @return the extra Location, or null if unavailable
* @hide
*/
public Location getExtraLocation(String key) {
if (mExtras != null) {
Parcelable value = mExtras.getParcelable(key);
if (value instanceof Location) {
return (Location) value;
}
}
return null;
}
/**
* Attaches an extra {@link Location} to this Location.
*
* @param key the key associated with the Location extra
* @param location the Location to attach
* @hide
*/
public void setExtraLocation(String key, Location value) {
if (mExtras == null) {
mExtras = new Bundle();
}
mExtras.putParcelable(key, value);
}
} }

View File

@@ -144,7 +144,7 @@ public final class LocationRequest implements Parcelable {
private int mNumUpdates = Integer.MAX_VALUE; // no expiry private int mNumUpdates = Integer.MAX_VALUE; // no expiry
private float mSmallestDisplacement = 0.0f; // meters private float mSmallestDisplacement = 0.0f; // meters
private String mProvider = null; // for deprecated API's that explicitly request a provider private String mProvider = LocationManager.FUSED_PROVIDER; // for deprecated APIs that explicitly request a provider
/** /**
* Create a location request with default parameters. * Create a location request with default parameters.

View File

@@ -302,6 +302,10 @@ public class FusionEngine implements LocationListener {
0.0, 360.0)); 0.0, 360.0));
} }
if (mNetworkLocation != null) {
fused.setExtraLocation(Location.EXTRA_NO_GPS_LOCATION, mNetworkLocation);
}
mFusedLocation = fused; mFusedLocation = fused;
mCallback.reportLocation(mFusedLocation); mCallback.reportLocation(mFusedLocation);

View File

@@ -900,25 +900,41 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
return receiver; return receiver;
} }
private boolean isProviderAllowedByCoarsePermission(String provider) {
if (LocationManager.FUSED_PROVIDER.equals(provider)) {
return true;
}
if (LocationManager.PASSIVE_PROVIDER.equals(provider)) {
return true;
}
if (LocationManager.NETWORK_PROVIDER.equals(provider)) {
return true;
}
return false;
}
private String checkPermissionAndRequest(LocationRequest request) { private String checkPermissionAndRequest(LocationRequest request) {
String perm = checkPermission(); String perm = checkPermission();
if (ACCESS_COARSE_LOCATION.equals(perm)) { if (ACCESS_COARSE_LOCATION.equals(perm)) {
switch (request.getQuality()) { if (!isProviderAllowedByCoarsePermission(request.getProvider())) {
case LocationRequest.ACCURACY_FINE: throw new SecurityException("Requires ACCESS_FINE_LOCATION permission");
request.setQuality(LocationRequest.ACCURACY_BLOCK); }
break; switch (request.getQuality()) {
case LocationRequest.POWER_HIGH: case LocationRequest.ACCURACY_FINE:
request.setQuality(LocationRequest.POWER_LOW); request.setQuality(LocationRequest.ACCURACY_BLOCK);
break; break;
} case LocationRequest.POWER_HIGH:
// throttle request.setQuality(LocationRequest.POWER_LOW);
if (request.getInterval() < LocationFudger.FASTEST_INTERVAL_MS) { break;
request.setInterval(LocationFudger.FASTEST_INTERVAL_MS); }
} // throttle
if (request.getFastestInterval() < LocationFudger.FASTEST_INTERVAL_MS) { if (request.getInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
request.setFastestInterval(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 // make getFastestInterval() the minimum of interval and fastest interval
if (request.getFastestInterval() > request.getInterval()) { if (request.getFastestInterval() > request.getInterval()) {
@@ -990,7 +1006,9 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
// use the fused provider // use the fused provider
if (request == null) request = DEFAULT_LOCATION_REQUEST; if (request == null) request = DEFAULT_LOCATION_REQUEST;
String name = request.getProvider(); String name = request.getProvider();
if (name == null) name = LocationManager.FUSED_PROVIDER; if (name == null) {
throw new IllegalArgumentException("provider name must not be null");
}
LocationProviderInterface provider = mProvidersByName.get(name); LocationProviderInterface provider = mProvidersByName.get(name);
if (provider == null) { if (provider == null) {
throw new IllegalArgumentException("provider doesn't exisit: " + provider); throw new IllegalArgumentException("provider doesn't exisit: " + provider);
@@ -1094,12 +1112,19 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
if (!isAllowedBySettingsLocked(name)) return null; if (!isAllowedBySettingsLocked(name)) return null;
Location location = mLastLocation.get(name); Location location = mLastLocation.get(name);
if (location == null) {
return null;
}
if (ACCESS_FINE_LOCATION.equals(perm)) { if (ACCESS_FINE_LOCATION.equals(perm)) {
return location; return location;
} else { } else {
return mLocationFudger.getOrCreate(location); Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
if (noGPSLocation != null) {
return mLocationFudger.getOrCreate(noGPSLocation);
}
} }
} }
return null;
} }
@Override @Override
@@ -1329,17 +1354,29 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
LocationProviderInterface p = mProvidersByName.get(provider); LocationProviderInterface p = mProvidersByName.get(provider);
if (p == null) return; if (p == null) return;
// Add the coarse location as an extra
Location coarse = mLocationFudger.getOrCreate(location);
// Update last known locations // Update last known locations
Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
Location lastNoGPSLocation = null;
Location lastLocation = mLastLocation.get(provider); Location lastLocation = mLastLocation.get(provider);
if (lastLocation == null) { if (lastLocation == null) {
lastLocation = new Location(provider); lastLocation = new Location(provider);
mLastLocation.put(provider, lastLocation); mLastLocation.put(provider, lastLocation);
} else {
lastNoGPSLocation = lastLocation.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
if (noGPSLocation == null && lastNoGPSLocation != null) {
// New location has no no-GPS location: adopt last no-GPS location. This is set
// directly into location because we do not want to notify COARSE clients.
location.setExtraLocation(Location.EXTRA_NO_GPS_LOCATION, lastNoGPSLocation);
}
} }
lastLocation.set(location); lastLocation.set(location);
// Fetch coarse location
Location coarseLocation = null;
if (noGPSLocation != null && !noGPSLocation.equals(lastNoGPSLocation)) {
coarseLocation = mLocationFudger.getOrCreate(noGPSLocation);
}
// Fetch latest status update time // Fetch latest status update time
long newStatusUpdateTime = p.getStatusUpdateTime(); long newStatusUpdateTime = p.getStatusUpdateTime();
@@ -1361,29 +1398,31 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
continue; continue;
} }
Location notifyLocation = null;
if (ACCESS_FINE_LOCATION.equals(receiver.mPermission)) { if (ACCESS_FINE_LOCATION.equals(receiver.mPermission)) {
location = lastLocation; // use fine location notifyLocation = lastLocation; // use fine location
} else { } else {
location = coarse; // use coarse location notifyLocation = coarseLocation; // use coarse location if available
} }
if (notifyLocation != null) {
Location lastLoc = r.mLastFixBroadcast; Location lastLoc = r.mLastFixBroadcast;
if ((lastLoc == null) || shouldBroadcastSafe(location, lastLoc, r)) { if ((lastLoc == null) || shouldBroadcastSafe(notifyLocation, lastLoc, r)) {
if (lastLoc == null) { if (lastLoc == null) {
lastLoc = new Location(location); lastLoc = new Location(notifyLocation);
r.mLastFixBroadcast = lastLoc; r.mLastFixBroadcast = lastLoc;
} else { } else {
lastLoc.set(location); lastLoc.set(notifyLocation);
} }
if (!receiver.callLocationChangedLocked(location)) { if (!receiver.callLocationChangedLocked(notifyLocation)) {
Slog.w(TAG, "RemoteException calling onLocationChanged on " + receiver); Slog.w(TAG, "RemoteException calling onLocationChanged on " + receiver);
receiverDead = true; receiverDead = true;
}
} }
} }
long prevStatusUpdateTime = r.mLastStatusBroadcast; long prevStatusUpdateTime = r.mLastStatusBroadcast;
if ((newStatusUpdateTime > prevStatusUpdateTime) && if ((newStatusUpdateTime > prevStatusUpdateTime) &&
(prevStatusUpdateTime != 0 || status != LocationProvider.AVAILABLE)) { (prevStatusUpdateTime != 0 || status != LocationProvider.AVAILABLE)) {
r.mLastStatusBroadcast = newStatusUpdateTime; r.mLastStatusBroadcast = newStatusUpdateTime;
if (!receiver.callStatusChangedLocked(provider, status, extras)) { if (!receiver.callStatusChangedLocked(provider, status, extras)) {

View File

@@ -22,6 +22,7 @@ import java.security.SecureRandom;
import android.content.Context; import android.content.Context;
import android.database.ContentObserver; import android.database.ContentObserver;
import android.location.Location; import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.Parcelable; import android.os.Parcelable;
@@ -40,8 +41,6 @@ public class LocationFudger {
private static final boolean D = false; private static final boolean D = false;
private static final String TAG = "LocationFudge"; private static final String TAG = "LocationFudge";
private static final String EXTRA_COARSE_LOCATION = "coarseLocation";
/** /**
* Default coarse accuracy in meters. * Default coarse accuracy in meters.
*/ */
@@ -168,18 +167,10 @@ public class LocationFudger {
*/ */
public Location getOrCreate(Location location) { public Location getOrCreate(Location location) {
synchronized (mLock) { synchronized (mLock) {
Bundle extras = location.getExtras(); Location coarse = location.getExtraLocation(Location.EXTRA_COARSE_LOCATION);
if (extras == null) { if (coarse == null) {
return addCoarseLocationExtraLocked(location); return addCoarseLocationExtraLocked(location);
} }
Parcelable parcel = extras.getParcelable(EXTRA_COARSE_LOCATION);
if (parcel == null) {
return addCoarseLocationExtraLocked(location);
}
if (!(parcel instanceof Location)) {
return addCoarseLocationExtraLocked(location);
}
Location coarse = (Location) parcel;
if (coarse.getAccuracy() < mAccuracyInMeters) { if (coarse.getAccuracy() < mAccuracyInMeters) {
return addCoarseLocationExtraLocked(location); return addCoarseLocationExtraLocked(location);
} }
@@ -188,11 +179,8 @@ public class LocationFudger {
} }
private Location addCoarseLocationExtraLocked(Location location) { private Location addCoarseLocationExtraLocked(Location location) {
Bundle extras = location.getExtras();
if (extras == null) extras = new Bundle();
Location coarse = createCoarseLocked(location); Location coarse = createCoarseLocked(location);
extras.putParcelable(EXTRA_COARSE_LOCATION, coarse); location.setExtraLocation(Location.EXTRA_COARSE_LOCATION, coarse);
location.setExtras(extras);
return coarse; return coarse;
} }

View File

@@ -114,6 +114,6 @@ public class PassiveProvider implements LocationProviderInterface {
@Override @Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("mReportLocaiton=" + mReportLocation); pw.println("mReportLocation=" + mReportLocation);
} }
} }