am de07d41f: Merge "Annotate Locations coming from mock providers"

# Via Android (Google) Code Review (1) and Victoria Lease (1)
* commit 'de07d41f6396f9f040fed2b6780932d8e5dbb482':
  Annotate Locations coming from mock providers
diff --git a/api/current.txt b/api/current.txt
index 0c9e16a..fc60f94 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -10701,6 +10701,7 @@
     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 9b32667..f70110c 100644
--- a/location/java/android/location/Location.java
+++ b/location/java/android/location/Location.java
@@ -91,6 +91,7 @@
     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 @@
         mHasAccuracy = l.mHasAccuracy;
         mAccuracy = l.mAccuracy;
         mExtras = (l.mExtras == null) ? null : new Bundle(l.mExtras);
+        mIsFromMockProvider = l.mIsFromMockProvider;
     }
 
     /**
@@ -160,6 +162,7 @@
         mHasAccuracy = false;
         mAccuracy = 0;
         mExtras = null;
+        mIsFromMockProvider = false;
     }
 
     /**
@@ -840,6 +843,7 @@
         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 @@
             l.mHasAccuracy = in.readInt() != 0;
             l.mAccuracy = in.readFloat();
             l.mExtras = in.readBundle();
+            l.mIsFromMockProvider = in.readInt() != 0;
             return l;
         }
 
@@ -901,6 +906,7 @@
         parcel.writeInt(mHasAccuracy ? 1 : 0);
         parcel.writeFloat(mAccuracy);
         parcel.writeBundle(mExtras);
+        parcel.writeInt(mIsFromMockProvider? 1 : 0);
     }
 
     /**
@@ -934,4 +940,23 @@
         }
         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 0b9286e..989178a 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -1549,9 +1549,9 @@
     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 f63719e..9606cf1 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -1792,17 +1792,33 @@
         }
     }
 
+    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);
             }
         }
     }