Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a44590f3 authored by Nick Pelly's avatar Nick Pelly Committed by Android Git Automerger
Browse files

am 4035f5a7: Port location blacklist code to MR1.

* commit '4035f5a7':
  Port location blacklist code to MR1.
parents 2bb9b562 4035f5a7
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -45,7 +45,7 @@ interface ILocationManager
            in PendingIntent intent, String packageName);
    void removeGeofence(in Geofence fence, in PendingIntent intent, String packageName);

    Location getLastLocation(in LocationRequest request);
    Location getLastLocation(in LocationRequest request, String packageName);

    boolean addGpsStatusListener(IGpsStatusListener listener);
    void removeGpsStatusListener(IGpsStatusListener listener);
+5 −3
Original line number Diff line number Diff line
@@ -1174,8 +1174,10 @@ public class LocationManager {
     * @throws SecurityException if no suitable permission is present
     */
    public Location getLastLocation() {
        String packageName = mContext.getPackageName();

        try {
            return mService.getLastLocation(null);
            return mService.getLastLocation(null, packageName);
        } catch (RemoteException e) {
            Log.e(TAG, "RemoteException", e);
            return null;
@@ -1204,12 +1206,12 @@ public class LocationManager {
    @Deprecated
    public Location getLastKnownLocation(String provider) {
        checkProvider(provider);

        String packageName = mContext.getPackageName();
        LocationRequest request = LocationRequest.createFromDeprecatedProvider(
                provider, 0, 0, true);

        try {
            return mService.getLastLocation(request);
            return mService.getLastLocation(request, packageName);
        } catch (RemoteException e) {
            Log.e(TAG, "RemoteException", e);
            return null;
+23 −5
Original line number Diff line number Diff line
@@ -63,6 +63,7 @@ import com.android.internal.location.ProviderRequest;
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 @@ public class LocationManagerService extends ILocationManager.Stub implements Obs
    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 @@ public class LocationManagerService extends ILocationManager.Stub implements Obs
        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 @@ public class LocationManagerService extends ILocationManager.Stub implements Obs
    }

    @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 @@ public class LocationManagerService extends ILocationManager.Stub implements Obs
        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 @@ public class LocationManagerService extends ILocationManager.Stub implements Obs
                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()) {
+13 −1
Original line number Diff line number Diff line
@@ -34,9 +34,13 @@ import android.os.Bundle;
import android.os.Looper;
import android.os.PowerManager;
import android.os.SystemClock;
import android.util.Log;

import com.android.server.LocationManagerService;

public class GeofenceManager implements LocationListener, PendingIntent.OnFinished {
    private static final String TAG = "GeofenceManager";
    private static final boolean D = LocationManagerService.D;

    /**
     * Assume a maximum land speed, as a heuristic to throttle location updates.
@@ -49,6 +53,7 @@ public class GeofenceManager implements LocationListener, PendingIntent.OnFinish
    private final LocationManager mLocationManager;
    private final PowerManager.WakeLock mWakeLock;
    private final Looper mLooper;  // looper thread to take location updates on
    private final LocationBlacklist mBlacklist;

    private Object mLock = new Object();

@@ -56,12 +61,13 @@ public class GeofenceManager implements LocationListener, PendingIntent.OnFinish
    private Location mLastLocation;
    private List<GeofenceState> mFences = new LinkedList<GeofenceState>();

    public GeofenceManager(Context context) {
    public GeofenceManager(Context context, LocationBlacklist blacklist) {
        mContext = context;
        mLocationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
        PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
        mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
        mLooper = Looper.myLooper();
        mBlacklist = blacklist;

        LocationRequest request = new LocationRequest()
                .setQuality(LocationRequest.POWER_NONE)
@@ -145,6 +151,12 @@ public class GeofenceManager implements LocationListener, PendingIntent.OnFinish
            removeExpiredFencesLocked();

            for (GeofenceState state : mFences) {
                if (mBlacklist.isBlacklisted(state.mPackageName)) {
                    if (D) Log.d(TAG, "skipping geofence processing for blacklisted app: " +
                            state.mPackageName);
                    continue;
                }

                int event = state.processLocation(location);
                if ((event & GeofenceState.FLAG_ENTER) != 0) {
                    enterIntents.add(state.mIntent);
+135 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


package com.android.server.location;

import android.content.Context;
import android.database.ContentObserver;
import android.os.Handler;
import android.provider.Settings;
import android.util.Log;
import android.util.Slog;

import com.android.server.LocationManagerService;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;

/**
 * Allows applications to be blacklisted from location updates at run-time.
 *
 * This is a silent blacklist. Applications can still call Location Manager
 * API's, but they just won't receive any locations.
 */
public final class LocationBlacklist extends ContentObserver {
    private static final String TAG = "LocationBlacklist";
    private static final boolean D = LocationManagerService.D;
    private static final String BLACKLIST_CONFIG_NAME = "locationPackagePrefixBlacklist";
    private static final String WHITELIST_CONFIG_NAME = "locationPackagePrefixWhitelist";

    private final Context mContext;
    private final Object mLock = new Object();

    // all fields below synchronized on mLock
    private String[] mWhitelist = new String[0];
    private String[] mBlacklist = new String[0];
    
    public LocationBlacklist(Context context, Handler handler) {
        super(handler);
        mContext = context;
    }

    public void init() {
        mContext.getContentResolver().registerContentObserver(Settings.Secure.getUriFor(
                BLACKLIST_CONFIG_NAME), false, this);
//        mContext.getContentResolver().registerContentObserver(Settings.Secure.getUriFor(
//                WHITELIST_CONFIG_NAME), false, this);
        reloadBlacklist();
    }

    private void reloadBlacklist() {
        String blacklist[] = getStringArray(BLACKLIST_CONFIG_NAME);
        String whitelist[] = getStringArray(WHITELIST_CONFIG_NAME);
        synchronized (mLock) {
            mWhitelist = whitelist;
            Slog.i(TAG, "whitelist: " + Arrays.toString(mWhitelist));
            mBlacklist = blacklist;
            Slog.i(TAG, "blacklist: " + Arrays.toString(mBlacklist));
        }
    }

    /**
     * Return true if in blacklist
     * (package name matches blacklist, and does not match whitelist)
     */
    public boolean isBlacklisted(String packageName) {
        synchronized (mLock) {
            for (String black : mBlacklist) {
                if (packageName.startsWith(black)) {
                    if (inWhitelist(packageName)) {
                        continue;
                    } else {
                        if (D) Log.d(TAG, "dropping location (blacklisted): "
                                + packageName + " matches " + black);
                        return true;
                    }
                }
            }
        }
        return false;
    }

    /**
     * Return true if any of packages are in whitelist
     */
    private boolean inWhitelist(String pkg) {
        synchronized (mLock) {
            for (String white : mWhitelist) {
                if (pkg.startsWith(white)) return true;
            }
        }
        return false;
    }

    @Override
    public void onChange(boolean selfChange) {
        reloadBlacklist();
    }

    private String[] getStringArray(String key) {
        String flatString = Settings.Secure.getString(mContext.getContentResolver(), key);
        if (flatString == null) {
            return new String[0];
        }
        String[] splitStrings = flatString.split(",");
        ArrayList<String> result = new ArrayList<String>();
        for (String pkg : splitStrings) {
            pkg = pkg.trim();
            if (pkg.isEmpty()) {
                continue;
            }
            result.add(pkg);
        }
        return result.toArray(new String[result.size()]);
    }

    public void dump(PrintWriter pw) {
        pw.println("mWhitelist=" + Arrays.toString(mWhitelist) + " mBlacklist=" +
                Arrays.toString(mBlacklist));
    }
}