Port location blacklist code to MR1.

I had to re-do this change for MR1 because LocationManagerService changed
so much. Here is the original change description:

Add package-name-prefix blacklist for location updates.

The Settings.Secure value locationPackagePrefixBlacklist and
locationPackagePrefixWhitelist contains comma seperated package-name
prefixes.

Location & geo-fence updates are silently dropped if the receiving
package name has a prefix on the blacklist. Status updates are
not affected. All other API's work as before.

A content observer is used so run-time updates to the blacklist
apply immediately. There is both a blacklist and a whitelist.
The blacklist applies first, and then exemptions are allowed
from the whitelist. In other words, if your package name prefix
matches both the black AND white list, then it is allowed.

Bug: 6986553
Change-Id: I1e151e08bd7143e47db005bc3fe9795076398df7
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index bb005d9..69ae833 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -63,6 +63,7 @@
 import com.android.server.location.GeocoderProxy;
 import com.android.server.location.GeofenceManager;
 import com.android.server.location.GpsLocationProvider;
+import com.android.server.location.LocationBlacklist;
 import com.android.server.location.LocationFudger;
 import com.android.server.location.LocationProviderInterface;
 import com.android.server.location.LocationProviderProxy;
@@ -132,8 +133,8 @@
     private IGpsStatusProvider mGpsStatusProvider;
     private INetInitiatedListener mNetInitiatedListener;
     private LocationWorkerHandler mLocationHandler;
-    // track the passive provider for some special cases
-    private PassiveProvider mPassiveProvider;
+    private PassiveProvider mPassiveProvider;  // track passive provider for special cases
+    private LocationBlacklist mBlacklist;
 
     // --- fields below are protected by mWakeLock ---
     private int mPendingBroadcasts;
@@ -208,7 +209,9 @@
         synchronized (mLock) {
             loadProvidersLocked();
         }
-        mGeofenceManager = new GeofenceManager(mContext);
+        mBlacklist = new LocationBlacklist(mContext, mLocationHandler);
+        mBlacklist.init();
+        mGeofenceManager = new GeofenceManager(mContext, mBlacklist);
         mLocationFudger = new LocationFudger();
 
         // Register for Network (Wifi or Mobile) updates
@@ -1063,10 +1066,17 @@
     }
 
     @Override
-    public Location getLastLocation(LocationRequest request) {
+    public Location getLastLocation(LocationRequest request, String packageName) {
         if (D) Log.d(TAG, "getLastLocation: " + request);
         if (request == null) request = DEFAULT_LOCATION_REQUEST;
         String perm = checkPermissionAndRequest(request);
+        checkPackageName(packageName);
+
+        if (mBlacklist.isBlacklisted(packageName)) {
+            if (D) Log.d(TAG, "not returning last loc for blacklisted app: " +
+                    packageName);
+            return null;
+        }
 
         synchronized (mLock) {
             // Figure out the provider. Either its explicitly request (deprecated API's),
@@ -1325,6 +1335,13 @@
         for (UpdateRecord r : records) {
             Receiver receiver = r.mReceiver;
             boolean receiverDead = false;
+
+            if (mBlacklist.isBlacklisted(receiver.mPackageName)) {
+                if (D) Log.d(TAG, "skipping loc update for blacklisted app: " +
+                        receiver.mPackageName);
+                continue;
+            }
+
             if (ACCESS_FINE_LOCATION.equals(receiver.mPermission)) {
                 location = lastLocation;  // use fine location
             } else {
@@ -1716,8 +1733,9 @@
                 for (String i : mDisabledProviders) {
                     pw.println("    " + i);
                 }
-
             }
+            pw.append("  ");
+            mBlacklist.dump(pw);
             if (mMockProviders.size() > 0) {
                 pw.println("  Mock Providers:");
                 for (Map.Entry<String, MockProvider> i : mMockProviders.entrySet()) {