Merge "LocationManager permissions cleanup" into jb-mr1-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
588fb15d16
@@ -221,6 +221,18 @@ public final class LocationRequest implements Parcelable {
|
|||||||
/** @hide */
|
/** @hide */
|
||||||
public LocationRequest() { }
|
public LocationRequest() { }
|
||||||
|
|
||||||
|
/** @hide */
|
||||||
|
public LocationRequest(LocationRequest src) {
|
||||||
|
mQuality = src.mQuality;
|
||||||
|
mInterval = src.mInterval;
|
||||||
|
mFastestInterval = src.mFastestInterval;
|
||||||
|
mExplicitFastestInterval = src.mExplicitFastestInterval;
|
||||||
|
mExpireAt = src.mExpireAt;
|
||||||
|
mNumUpdates = src.mNumUpdates;
|
||||||
|
mSmallestDisplacement = src.mSmallestDisplacement;
|
||||||
|
mProvider = src.mProvider;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the quality of the request.
|
* Set the quality of the request.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -90,10 +90,13 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
|
|||||||
private static final String WAKELOCK_KEY = TAG;
|
private static final String WAKELOCK_KEY = TAG;
|
||||||
private static final String THREAD_NAME = TAG;
|
private static final String THREAD_NAME = TAG;
|
||||||
|
|
||||||
private static final String ACCESS_FINE_LOCATION =
|
// Location resolution level: no location data whatsoever
|
||||||
android.Manifest.permission.ACCESS_FINE_LOCATION;
|
private static final int RESOLUTION_LEVEL_NONE = 0;
|
||||||
private static final String ACCESS_COARSE_LOCATION =
|
// Location resolution level: coarse location data only
|
||||||
android.Manifest.permission.ACCESS_COARSE_LOCATION;
|
private static final int RESOLUTION_LEVEL_COARSE = 1;
|
||||||
|
// Location resolution level: fine location data
|
||||||
|
private static final int RESOLUTION_LEVEL_FINE = 2;
|
||||||
|
|
||||||
private static final String ACCESS_MOCK_LOCATION =
|
private static final String ACCESS_MOCK_LOCATION =
|
||||||
android.Manifest.permission.ACCESS_MOCK_LOCATION;
|
android.Manifest.permission.ACCESS_MOCK_LOCATION;
|
||||||
private static final String ACCESS_LOCATION_EXTRA_COMMANDS =
|
private static final String ACCESS_LOCATION_EXTRA_COMMANDS =
|
||||||
@@ -347,7 +350,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
|
|||||||
final int mUid; // uid of receiver
|
final int mUid; // uid of receiver
|
||||||
final int mPid; // pid of receiver
|
final int mPid; // pid of receiver
|
||||||
final String mPackageName; // package name of receiver
|
final String mPackageName; // package name of receiver
|
||||||
final String mPermission; // best permission that receiver has
|
final int mAllowedResolutionLevel; // resolution level allowed to receiver
|
||||||
|
|
||||||
final ILocationListener mListener;
|
final ILocationListener mListener;
|
||||||
final PendingIntent mPendingIntent;
|
final PendingIntent mPendingIntent;
|
||||||
@@ -366,7 +369,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
|
|||||||
} else {
|
} else {
|
||||||
mKey = intent;
|
mKey = intent;
|
||||||
}
|
}
|
||||||
mPermission = checkPermission();
|
mAllowedResolutionLevel = getAllowedResolutionLevel(pid, uid);
|
||||||
mUid = uid;
|
mUid = uid;
|
||||||
mPid = pid;
|
mPid = pid;
|
||||||
mPackageName = packageName;
|
mPackageName = packageName;
|
||||||
@@ -440,7 +443,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
|
|||||||
// synchronize to ensure incrementPendingBroadcastsLocked()
|
// synchronize to ensure incrementPendingBroadcastsLocked()
|
||||||
// is called before decrementPendingBroadcasts()
|
// is called before decrementPendingBroadcasts()
|
||||||
mPendingIntent.send(mContext, 0, statusChanged, this, mLocationHandler,
|
mPendingIntent.send(mContext, 0, statusChanged, this, mLocationHandler,
|
||||||
mPermission);
|
getResolutionPermission(mAllowedResolutionLevel));
|
||||||
// call this after broadcasting so we do not increment
|
// call this after broadcasting so we do not increment
|
||||||
// if we throw an exeption.
|
// if we throw an exeption.
|
||||||
incrementPendingBroadcastsLocked();
|
incrementPendingBroadcastsLocked();
|
||||||
@@ -474,7 +477,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
|
|||||||
// synchronize to ensure incrementPendingBroadcastsLocked()
|
// synchronize to ensure incrementPendingBroadcastsLocked()
|
||||||
// is called before decrementPendingBroadcasts()
|
// is called before decrementPendingBroadcasts()
|
||||||
mPendingIntent.send(mContext, 0, locationChanged, this, mLocationHandler,
|
mPendingIntent.send(mContext, 0, locationChanged, this, mLocationHandler,
|
||||||
mPermission);
|
getResolutionPermission(mAllowedResolutionLevel));
|
||||||
// call this after broadcasting so we do not increment
|
// call this after broadcasting so we do not increment
|
||||||
// if we throw an exeption.
|
// if we throw an exeption.
|
||||||
incrementPendingBroadcastsLocked();
|
incrementPendingBroadcastsLocked();
|
||||||
@@ -512,7 +515,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
|
|||||||
// synchronize to ensure incrementPendingBroadcastsLocked()
|
// synchronize to ensure incrementPendingBroadcastsLocked()
|
||||||
// is called before decrementPendingBroadcasts()
|
// is called before decrementPendingBroadcasts()
|
||||||
mPendingIntent.send(mContext, 0, providerIntent, this, mLocationHandler,
|
mPendingIntent.send(mContext, 0, providerIntent, this, mLocationHandler,
|
||||||
mPermission);
|
getResolutionPermission(mAllowedResolutionLevel));
|
||||||
// call this after broadcasting so we do not increment
|
// call this after broadcasting so we do not increment
|
||||||
// if we throw an exeption.
|
// if we throw an exeption.
|
||||||
incrementPendingBroadcastsLocked();
|
incrementPendingBroadcastsLocked();
|
||||||
@@ -609,51 +612,76 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the best permission available to the caller.
|
* Returns the permission string associated with the specified resolution level.
|
||||||
|
*
|
||||||
|
* @param resolutionLevel the resolution level
|
||||||
|
* @return the permission string
|
||||||
*/
|
*/
|
||||||
private String getBestCallingPermission() {
|
private String getResolutionPermission(int resolutionLevel) {
|
||||||
if (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION) ==
|
switch (resolutionLevel) {
|
||||||
PackageManager.PERMISSION_GRANTED) {
|
case RESOLUTION_LEVEL_FINE:
|
||||||
return ACCESS_FINE_LOCATION;
|
return android.Manifest.permission.ACCESS_FINE_LOCATION;
|
||||||
} else if (mContext.checkCallingOrSelfPermission(ACCESS_COARSE_LOCATION) ==
|
case RESOLUTION_LEVEL_COARSE:
|
||||||
PackageManager.PERMISSION_GRANTED) {
|
return android.Manifest.permission.ACCESS_COARSE_LOCATION;
|
||||||
return ACCESS_COARSE_LOCATION;
|
default:
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Throw SecurityException if caller has neither COARSE or FINE.
|
* Returns the resolution level allowed to the given PID/UID pair.
|
||||||
* Otherwise, return the best permission.
|
*
|
||||||
|
* @param pid the PID
|
||||||
|
* @param uid the UID
|
||||||
|
* @return resolution level allowed to the pid/uid pair
|
||||||
*/
|
*/
|
||||||
private String checkPermission() {
|
private int getAllowedResolutionLevel(int pid, int uid) {
|
||||||
String perm = getBestCallingPermission();
|
if (mContext.checkPermission(android.Manifest.permission.ACCESS_FINE_LOCATION,
|
||||||
if (perm == null) {
|
pid, uid) == PackageManager.PERMISSION_GRANTED) {
|
||||||
throw new SecurityException("Location requires either ACCESS_COARSE_LOCATION or" +
|
return RESOLUTION_LEVEL_FINE;
|
||||||
" ACCESS_FINE_LOCATION permission");
|
} else if (mContext.checkPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION,
|
||||||
|
pid, uid) == PackageManager.PERMISSION_GRANTED) {
|
||||||
|
return RESOLUTION_LEVEL_COARSE;
|
||||||
|
} else {
|
||||||
|
return RESOLUTION_LEVEL_NONE;
|
||||||
}
|
}
|
||||||
return perm;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Throw SecurityException if caller lacks permission to use Geofences.
|
* Returns the resolution level allowed to the caller
|
||||||
|
*
|
||||||
|
* @return resolution level allowed to caller
|
||||||
*/
|
*/
|
||||||
private void checkGeofencePermission() {
|
private int getCallerAllowedResolutionLevel() {
|
||||||
if (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION) !=
|
return getAllowedResolutionLevel(Binder.getCallingPid(), Binder.getCallingUid());
|
||||||
PackageManager.PERMISSION_GRANTED) {
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Throw SecurityException if specified resolution level is insufficient to use geofences.
|
||||||
|
*
|
||||||
|
* @param allowedResolutionLevel resolution level allowed to caller
|
||||||
|
*/
|
||||||
|
private void checkResolutionLevelIsSufficientForGeofenceUse(int allowedResolutionLevel) {
|
||||||
|
if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
|
||||||
throw new SecurityException("Geofence usage requires ACCESS_FINE_LOCATION permission");
|
throw new SecurityException("Geofence usage requires ACCESS_FINE_LOCATION permission");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getMinimumPermissionForProvider(String provider) {
|
/**
|
||||||
|
* Return the minimum resolution level required to use the specified location provider.
|
||||||
|
*
|
||||||
|
* @param provider the name of the location provider
|
||||||
|
* @return minimum resolution level required for provider
|
||||||
|
*/
|
||||||
|
private int getMinimumResolutionLevelForProviderUse(String provider) {
|
||||||
if (LocationManager.GPS_PROVIDER.equals(provider) ||
|
if (LocationManager.GPS_PROVIDER.equals(provider) ||
|
||||||
LocationManager.PASSIVE_PROVIDER.equals(provider)) {
|
LocationManager.PASSIVE_PROVIDER.equals(provider)) {
|
||||||
// gps and passive providers require FINE permission
|
// gps and passive providers require FINE permission
|
||||||
return ACCESS_FINE_LOCATION;
|
return RESOLUTION_LEVEL_FINE;
|
||||||
} else if (LocationManager.NETWORK_PROVIDER.equals(provider) ||
|
} else if (LocationManager.NETWORK_PROVIDER.equals(provider) ||
|
||||||
LocationManager.FUSED_PROVIDER.equals(provider)) {
|
LocationManager.FUSED_PROVIDER.equals(provider)) {
|
||||||
// network and fused providers are ok with COARSE or FINE
|
// network and fused providers are ok with COARSE or FINE
|
||||||
return ACCESS_COARSE_LOCATION;
|
return RESOLUTION_LEVEL_COARSE;
|
||||||
} else {
|
} else {
|
||||||
// mock providers
|
// mock providers
|
||||||
LocationProviderInterface lp = mMockProviders.get(provider);
|
LocationProviderInterface lp = mMockProviders.get(provider);
|
||||||
@@ -662,41 +690,38 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
|
|||||||
if (properties != null) {
|
if (properties != null) {
|
||||||
if (properties.mRequiresSatellite) {
|
if (properties.mRequiresSatellite) {
|
||||||
// provider requiring satellites require FINE permission
|
// provider requiring satellites require FINE permission
|
||||||
return ACCESS_FINE_LOCATION;
|
return RESOLUTION_LEVEL_FINE;
|
||||||
} else if (properties.mRequiresNetwork || properties.mRequiresCell) {
|
} else if (properties.mRequiresNetwork || properties.mRequiresCell) {
|
||||||
// provider requiring network and or cell require COARSE or FINE
|
// provider requiring network and or cell require COARSE or FINE
|
||||||
return ACCESS_COARSE_LOCATION;
|
return RESOLUTION_LEVEL_COARSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return RESOLUTION_LEVEL_FINE; // if in doubt, require FINE
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isPermissionSufficient(String perm, String minPerm) {
|
/**
|
||||||
if (ACCESS_FINE_LOCATION.equals(minPerm)) {
|
* Throw SecurityException if specified resolution level is insufficient to use the named
|
||||||
return ACCESS_FINE_LOCATION.equals(perm);
|
* location provider.
|
||||||
} else if (ACCESS_COARSE_LOCATION.equals(minPerm)) {
|
*
|
||||||
return ACCESS_FINE_LOCATION.equals(perm) ||
|
* @param allowedResolutionLevel resolution level allowed to caller
|
||||||
ACCESS_COARSE_LOCATION.equals(perm);
|
* @param providerName the name of the location provider
|
||||||
} else {
|
*/
|
||||||
return false;
|
private void checkResolutionLevelIsSufficientForProviderUse(int allowedResolutionLevel,
|
||||||
}
|
String providerName) {
|
||||||
}
|
int requiredResolutionLevel = getMinimumResolutionLevelForProviderUse(providerName);
|
||||||
|
if (allowedResolutionLevel < requiredResolutionLevel) {
|
||||||
private void checkPermissionForProvider(String perm, String provider) {
|
switch (requiredResolutionLevel) {
|
||||||
String minPerm = getMinimumPermissionForProvider(provider);
|
case RESOLUTION_LEVEL_FINE:
|
||||||
if (!isPermissionSufficient(perm, minPerm)) {
|
throw new SecurityException("\"" + providerName + "\" location provider " +
|
||||||
if (ACCESS_FINE_LOCATION.equals(minPerm)) {
|
"requires ACCESS_FINE_LOCATION permission.");
|
||||||
throw new SecurityException("Location provider \"" + provider +
|
case RESOLUTION_LEVEL_COARSE:
|
||||||
"\" requires ACCESS_FINE_LOCATION permission.");
|
throw new SecurityException("\"" + providerName + "\" location provider " +
|
||||||
} else if (ACCESS_COARSE_LOCATION.equals(minPerm)) {
|
"requires ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission.");
|
||||||
throw new SecurityException("Location provider \"" + provider +
|
default:
|
||||||
"\" requires ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission.");
|
throw new SecurityException("Insufficient permission for \"" + providerName +
|
||||||
} else {
|
"\" location provider.");
|
||||||
throw new SecurityException("Insufficient permission for location provider \"" +
|
|
||||||
provider + "\".");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -731,8 +756,8 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public List<String> getProviders(Criteria criteria, boolean enabledOnly) {
|
public List<String> getProviders(Criteria criteria, boolean enabledOnly) {
|
||||||
|
int allowedResolutionLevel = getCallerAllowedResolutionLevel();
|
||||||
ArrayList<String> out;
|
ArrayList<String> out;
|
||||||
String perm = getBestCallingPermission();
|
|
||||||
int callingUserId = UserHandle.getCallingUserId();
|
int callingUserId = UserHandle.getCallingUserId();
|
||||||
long identity = Binder.clearCallingIdentity();
|
long identity = Binder.clearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
@@ -743,7 +768,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
|
|||||||
if (LocationManager.FUSED_PROVIDER.equals(name)) {
|
if (LocationManager.FUSED_PROVIDER.equals(name)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (isPermissionSufficient(perm, getMinimumPermissionForProvider(name))) {
|
if (allowedResolutionLevel >= getMinimumResolutionLevelForProviderUse(name)) {
|
||||||
if (enabledOnly && !isAllowedBySettingsLocked(name, callingUserId)) {
|
if (enabledOnly && !isAllowedBySettingsLocked(name, callingUserId)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -803,8 +828,6 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean providerMeetsCriteria(String provider, Criteria criteria) {
|
public boolean providerMeetsCriteria(String provider, Criteria criteria) {
|
||||||
checkPermission();
|
|
||||||
|
|
||||||
LocationProviderInterface p = mProvidersByName.get(provider);
|
LocationProviderInterface p = mProvidersByName.get(provider);
|
||||||
if (p == null) {
|
if (p == null) {
|
||||||
throw new IllegalArgumentException("provider=" + provider);
|
throw new IllegalArgumentException("provider=" + provider);
|
||||||
@@ -1010,33 +1033,41 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
|
|||||||
return receiver;
|
return receiver;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String checkPermissionAndRequest(LocationRequest request) {
|
/**
|
||||||
String perm = getBestCallingPermission();
|
* Creates a LocationRequest based upon the supplied LocationRequest that to meets resolution
|
||||||
String provider = request.getProvider();
|
* and consistency requirements.
|
||||||
checkPermissionForProvider(perm, provider);
|
*
|
||||||
|
* @param request the LocationRequest from which to create a sanitized version
|
||||||
if (ACCESS_COARSE_LOCATION.equals(perm)) {
|
* @param shouldBeCoarse whether the sanitized version should be held to coarse resolution
|
||||||
switch (request.getQuality()) {
|
* constraints
|
||||||
|
* @param fastestCoarseIntervalMS minimum interval allowed for coarse resolution
|
||||||
|
* @return a version of request that meets the given resolution and consistency requirements
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
private LocationRequest createSanitizedRequest(LocationRequest request, int resolutionLevel) {
|
||||||
|
LocationRequest sanitizedRequest = new LocationRequest(request);
|
||||||
|
if (resolutionLevel < RESOLUTION_LEVEL_FINE) {
|
||||||
|
switch (sanitizedRequest.getQuality()) {
|
||||||
case LocationRequest.ACCURACY_FINE:
|
case LocationRequest.ACCURACY_FINE:
|
||||||
request.setQuality(LocationRequest.ACCURACY_BLOCK);
|
sanitizedRequest.setQuality(LocationRequest.ACCURACY_BLOCK);
|
||||||
break;
|
break;
|
||||||
case LocationRequest.POWER_HIGH:
|
case LocationRequest.POWER_HIGH:
|
||||||
request.setQuality(LocationRequest.POWER_LOW);
|
sanitizedRequest.setQuality(LocationRequest.POWER_LOW);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// throttle
|
// throttle
|
||||||
if (request.getInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
|
if (sanitizedRequest.getInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
|
||||||
request.setInterval(LocationFudger.FASTEST_INTERVAL_MS);
|
sanitizedRequest.setInterval(LocationFudger.FASTEST_INTERVAL_MS);
|
||||||
}
|
}
|
||||||
if (request.getFastestInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
|
if (sanitizedRequest.getFastestInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
|
||||||
request.setFastestInterval(LocationFudger.FASTEST_INTERVAL_MS);
|
sanitizedRequest.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 (sanitizedRequest.getFastestInterval() > sanitizedRequest.getInterval()) {
|
||||||
request.setFastestInterval(request.getInterval());
|
request.setFastestInterval(request.getInterval());
|
||||||
}
|
}
|
||||||
return perm;
|
return sanitizedRequest;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkPackageName(String packageName) {
|
private void checkPackageName(String packageName) {
|
||||||
@@ -1079,7 +1110,10 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
|
|||||||
PendingIntent intent, String packageName) {
|
PendingIntent intent, String packageName) {
|
||||||
if (request == null) request = DEFAULT_LOCATION_REQUEST;
|
if (request == null) request = DEFAULT_LOCATION_REQUEST;
|
||||||
checkPackageName(packageName);
|
checkPackageName(packageName);
|
||||||
checkPermissionAndRequest(request);
|
int allowedResolutionLevel = getCallerAllowedResolutionLevel();
|
||||||
|
checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
|
||||||
|
request.getProvider());
|
||||||
|
LocationRequest sanitizedRequest = createSanitizedRequest(request, allowedResolutionLevel);
|
||||||
|
|
||||||
final int pid = Binder.getCallingPid();
|
final int pid = Binder.getCallingPid();
|
||||||
final int uid = Binder.getCallingUid();
|
final int uid = Binder.getCallingUid();
|
||||||
@@ -1089,7 +1123,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
|
|||||||
long identity = Binder.clearCallingIdentity();
|
long identity = Binder.clearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
requestLocationUpdatesLocked(request, recevier, pid, uid, packageName);
|
requestLocationUpdatesLocked(sanitizedRequest, recevier, pid, uid, packageName);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
Binder.restoreCallingIdentity(identity);
|
Binder.restoreCallingIdentity(identity);
|
||||||
@@ -1132,7 +1166,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
|
|||||||
public void removeUpdates(ILocationListener listener, PendingIntent intent,
|
public void removeUpdates(ILocationListener listener, PendingIntent intent,
|
||||||
String packageName) {
|
String packageName) {
|
||||||
checkPackageName(packageName);
|
checkPackageName(packageName);
|
||||||
checkPermission();
|
|
||||||
final int pid = Binder.getCallingPid();
|
final int pid = Binder.getCallingPid();
|
||||||
final int uid = Binder.getCallingUid();
|
final int uid = Binder.getCallingUid();
|
||||||
Receiver receiver = checkListenerOrIntent(listener, intent, pid, uid, packageName);
|
Receiver receiver = checkListenerOrIntent(listener, intent, pid, uid, packageName);
|
||||||
@@ -1188,8 +1222,11 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
|
|||||||
public Location getLastLocation(LocationRequest request, String packageName) {
|
public Location getLastLocation(LocationRequest request, String packageName) {
|
||||||
if (D) Log.d(TAG, "getLastLocation: " + request);
|
if (D) Log.d(TAG, "getLastLocation: " + request);
|
||||||
if (request == null) request = DEFAULT_LOCATION_REQUEST;
|
if (request == null) request = DEFAULT_LOCATION_REQUEST;
|
||||||
String perm = checkPermissionAndRequest(request);
|
int allowedResolutionLevel = getCallerAllowedResolutionLevel();
|
||||||
checkPackageName(packageName);
|
checkPackageName(packageName);
|
||||||
|
checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
|
||||||
|
request.getProvider());
|
||||||
|
// no need to sanitize this request, as only the provider name is used
|
||||||
|
|
||||||
long identity = Binder.clearCallingIdentity();
|
long identity = Binder.clearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
@@ -1213,13 +1250,13 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
|
|||||||
if (location == null) {
|
if (location == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (ACCESS_FINE_LOCATION.equals(perm)) {
|
if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
|
||||||
return location;
|
|
||||||
} else {
|
|
||||||
Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
|
Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
|
||||||
if (noGPSLocation != null) {
|
if (noGPSLocation != null) {
|
||||||
return mLocationFudger.getOrCreate(noGPSLocation);
|
return mLocationFudger.getOrCreate(noGPSLocation);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
return location;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@@ -1232,18 +1269,21 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
|
|||||||
public void requestGeofence(LocationRequest request, Geofence geofence, PendingIntent intent,
|
public void requestGeofence(LocationRequest request, Geofence geofence, PendingIntent intent,
|
||||||
String packageName) {
|
String packageName) {
|
||||||
if (request == null) request = DEFAULT_LOCATION_REQUEST;
|
if (request == null) request = DEFAULT_LOCATION_REQUEST;
|
||||||
checkGeofencePermission();
|
int allowedResolutionLevel = getCallerAllowedResolutionLevel();
|
||||||
checkPermissionAndRequest(request);
|
checkResolutionLevelIsSufficientForGeofenceUse(allowedResolutionLevel);
|
||||||
checkPendingIntent(intent);
|
checkPendingIntent(intent);
|
||||||
checkPackageName(packageName);
|
checkPackageName(packageName);
|
||||||
|
checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
|
||||||
|
request.getProvider());
|
||||||
|
LocationRequest sanitizedRequest = createSanitizedRequest(request, allowedResolutionLevel);
|
||||||
|
|
||||||
if (D) Log.d(TAG, "requestGeofence: " + request + " " + geofence + " " + intent);
|
if (D) Log.d(TAG, "requestGeofence: " + sanitizedRequest + " " + geofence + " " + intent);
|
||||||
|
|
||||||
// geo-fence manager uses the public location API, need to clear identity
|
// geo-fence manager uses the public location API, need to clear identity
|
||||||
int uid = Binder.getCallingUid();
|
int uid = Binder.getCallingUid();
|
||||||
long identity = Binder.clearCallingIdentity();
|
long identity = Binder.clearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
mGeofenceManager.addFence(request, geofence, intent, uid, packageName);
|
mGeofenceManager.addFence(sanitizedRequest, geofence, intent, uid, packageName);
|
||||||
} finally {
|
} finally {
|
||||||
Binder.restoreCallingIdentity(identity);
|
Binder.restoreCallingIdentity(identity);
|
||||||
}
|
}
|
||||||
@@ -1251,7 +1291,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeGeofence(Geofence geofence, PendingIntent intent, String packageName) {
|
public void removeGeofence(Geofence geofence, PendingIntent intent, String packageName) {
|
||||||
checkGeofencePermission();
|
checkResolutionLevelIsSufficientForGeofenceUse(getCallerAllowedResolutionLevel());
|
||||||
checkPendingIntent(intent);
|
checkPendingIntent(intent);
|
||||||
checkPackageName(packageName);
|
checkPackageName(packageName);
|
||||||
|
|
||||||
@@ -1272,10 +1312,8 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
|
|||||||
if (mGpsStatusProvider == null) {
|
if (mGpsStatusProvider == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION) !=
|
checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(),
|
||||||
PackageManager.PERMISSION_GRANTED) {
|
LocationManager.GPS_PROVIDER);
|
||||||
throw new SecurityException("Requires ACCESS_FINE_LOCATION permission");
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
mGpsStatusProvider.addGpsStatusListener(listener);
|
mGpsStatusProvider.addGpsStatusListener(listener);
|
||||||
@@ -1303,8 +1341,9 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
|
|||||||
// throw NullPointerException to remain compatible with previous implementation
|
// throw NullPointerException to remain compatible with previous implementation
|
||||||
throw new NullPointerException();
|
throw new NullPointerException();
|
||||||
}
|
}
|
||||||
|
checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(),
|
||||||
|
provider);
|
||||||
|
|
||||||
checkPermission();
|
|
||||||
// and check for ACCESS_LOCATION_EXTRA_COMMANDS
|
// and check for ACCESS_LOCATION_EXTRA_COMMANDS
|
||||||
if ((mContext.checkCallingOrSelfPermission(ACCESS_LOCATION_EXTRA_COMMANDS)
|
if ((mContext.checkCallingOrSelfPermission(ACCESS_LOCATION_EXTRA_COMMANDS)
|
||||||
!= PackageManager.PERMISSION_GRANTED)) {
|
!= PackageManager.PERMISSION_GRANTED)) {
|
||||||
@@ -1344,7 +1383,8 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
checkPermissionForProvider(getBestCallingPermission(), provider);
|
checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(),
|
||||||
|
provider);
|
||||||
|
|
||||||
LocationProviderInterface p;
|
LocationProviderInterface p;
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
@@ -1357,7 +1397,8 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isProviderEnabled(String provider) {
|
public boolean isProviderEnabled(String provider) {
|
||||||
checkPermissionForProvider(getBestCallingPermission(), provider);
|
checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(),
|
||||||
|
provider);
|
||||||
if (LocationManager.FUSED_PROVIDER.equals(provider)) return false;
|
if (LocationManager.FUSED_PROVIDER.equals(provider)) return false;
|
||||||
|
|
||||||
long identity = Binder.clearCallingIdentity();
|
long identity = Binder.clearCallingIdentity();
|
||||||
@@ -1522,10 +1563,10 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
|
|||||||
}
|
}
|
||||||
|
|
||||||
Location notifyLocation = null;
|
Location notifyLocation = null;
|
||||||
if (ACCESS_FINE_LOCATION.equals(receiver.mPermission)) {
|
if (receiver.mAllowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
|
||||||
notifyLocation = lastLocation; // use fine location
|
notifyLocation = coarseLocation; // use coarse location
|
||||||
} else {
|
} else {
|
||||||
notifyLocation = coarseLocation; // use coarse location if available
|
notifyLocation = lastLocation; // use fine location
|
||||||
}
|
}
|
||||||
if (notifyLocation != null) {
|
if (notifyLocation != null) {
|
||||||
Location lastLoc = r.mLastFixBroadcast;
|
Location lastLoc = r.mLastFixBroadcast;
|
||||||
|
|||||||
Reference in New Issue
Block a user