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:
@@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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)) {
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user