diff --git a/api/current.txt b/api/current.txt index 0c9e16a132278..fc60f944fbaf4 100644 --- a/api/current.txt +++ b/api/current.txt @@ -10701,6 +10701,7 @@ package android.location { method public boolean hasAltitude(); method public boolean hasBearing(); method public boolean hasSpeed(); + method public boolean isFromMockProvider(); method public void removeAccuracy(); method public void removeAltitude(); method public void removeBearing(); diff --git a/location/java/android/location/Location.java b/location/java/android/location/Location.java index 9b3266739f7c0..f70110cd59105 100644 --- a/location/java/android/location/Location.java +++ b/location/java/android/location/Location.java @@ -91,6 +91,7 @@ public class Location implements Parcelable { private boolean mHasAccuracy = false; private float mAccuracy = 0.0f; private Bundle mExtras = null; + private boolean mIsFromMockProvider = false; // Cache the inputs and outputs of computeDistanceAndBearing // so calls to distanceTo() and bearingTo() can share work @@ -140,6 +141,7 @@ public class Location implements Parcelable { mHasAccuracy = l.mHasAccuracy; mAccuracy = l.mAccuracy; mExtras = (l.mExtras == null) ? null : new Bundle(l.mExtras); + mIsFromMockProvider = l.mIsFromMockProvider; } /** @@ -160,6 +162,7 @@ public class Location implements Parcelable { mHasAccuracy = false; mAccuracy = 0; mExtras = null; + mIsFromMockProvider = false; } /** @@ -840,6 +843,7 @@ public class Location implements Parcelable { if (mHasAltitude) s.append(" alt=").append(mAltitude); if (mHasSpeed) s.append(" vel=").append(mSpeed); if (mHasBearing) s.append(" bear=").append(mBearing); + if (mIsFromMockProvider) s.append(" mock"); if (mExtras != null) { s.append(" {").append(mExtras).append('}'); @@ -871,6 +875,7 @@ public class Location implements Parcelable { l.mHasAccuracy = in.readInt() != 0; l.mAccuracy = in.readFloat(); l.mExtras = in.readBundle(); + l.mIsFromMockProvider = in.readInt() != 0; return l; } @@ -901,6 +906,7 @@ public class Location implements Parcelable { parcel.writeInt(mHasAccuracy ? 1 : 0); parcel.writeFloat(mAccuracy); parcel.writeBundle(mExtras); + parcel.writeInt(mIsFromMockProvider? 1 : 0); } /** @@ -934,4 +940,23 @@ public class Location implements Parcelable { } mExtras.putParcelable(key, value); } + + /** + * Returns true if the Location came from a mock provider. + * + * @return true if this Location came from a mock provider, false otherwise + */ + public boolean isFromMockProvider() { + return mIsFromMockProvider; + } + + /** + * Flag this Location as having come from a mock provider or not. + * + * @param isFromMockProvider true if this Location came from a mock provider, false otherwise + * @hide + */ + public void setIsFromMockProvider(boolean isFromMockProvider) { + mIsFromMockProvider = isFromMockProvider; + } } diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java index 0b9286ed62d59..989178a86f7a3 100644 --- a/location/java/android/location/LocationManager.java +++ b/location/java/android/location/LocationManager.java @@ -1549,9 +1549,9 @@ public class LocationManager { public GpsStatus getGpsStatus(GpsStatus status) { if (status == null) { status = new GpsStatus(); - } - status.setStatus(mGpsStatus); - return status; + } + status.setStatus(mGpsStatus); + return status; } /** diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java index f63719e56eda4..9606cf1b83a7d 100644 --- a/services/java/com/android/server/LocationManagerService.java +++ b/services/java/com/android/server/LocationManagerService.java @@ -1792,17 +1792,33 @@ public class LocationManagerService extends ILocationManager.Stub { } } + private boolean isMockProvider(String provider) { + synchronized (mLock) { + return mMockProviders.containsKey(provider); + } + } + private void handleLocationChanged(Location location, boolean passive) { - String provider = location.getProvider(); + // create a working copy of the incoming Location so that the service can modify it without + // disturbing the caller's copy + Location myLocation = new Location(location); + String provider = myLocation.getProvider(); + + // set "isFromMockProvider" bit if location came from a mock provider. we do not clear this + // bit if location did not come from a mock provider because passive/fused providers can + // forward locations from mock providers, and should not grant them legitimacy in doing so. + if (!myLocation.isFromMockProvider() && isMockProvider(provider)) { + myLocation.setIsFromMockProvider(true); + } if (!passive) { // notify passive provider of the new location - mPassiveProvider.updateLocation(location); + mPassiveProvider.updateLocation(myLocation); } synchronized (mLock) { if (isAllowedBySettingsLocked(provider, mCurrentUserId)) { - handleLocationChangedLocked(location, passive); + handleLocationChangedLocked(myLocation, passive); } } }