Skip to content

Commit 4035f5a

Browse files
author
Nick Pelly
committed
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
1 parent 81c304b commit 4035f5a

File tree

5 files changed

+177
-10
lines changed

5 files changed

+177
-10
lines changed

location/java/android/location/ILocationManager.aidl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ interface ILocationManager
4545
in PendingIntent intent, String packageName);
4646
void removeGeofence(in Geofence fence, in PendingIntent intent, String packageName);
4747

48-
Location getLastLocation(in LocationRequest request);
48+
Location getLastLocation(in LocationRequest request, String packageName);
4949

5050
boolean addGpsStatusListener(IGpsStatusListener listener);
5151
void removeGpsStatusListener(IGpsStatusListener listener);

location/java/android/location/LocationManager.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1174,8 +1174,10 @@ public boolean isProviderEnabled(String provider) {
11741174
* @throws SecurityException if no suitable permission is present
11751175
*/
11761176
public Location getLastLocation() {
1177+
String packageName = mContext.getPackageName();
1178+
11771179
try {
1178-
return mService.getLastLocation(null);
1180+
return mService.getLastLocation(null, packageName);
11791181
} catch (RemoteException e) {
11801182
Log.e(TAG, "RemoteException", e);
11811183
return null;
@@ -1204,12 +1206,12 @@ public Location getLastLocation() {
12041206
@Deprecated
12051207
public Location getLastKnownLocation(String provider) {
12061208
checkProvider(provider);
1207-
1209+
String packageName = mContext.getPackageName();
12081210
LocationRequest request = LocationRequest.createFromDeprecatedProvider(
12091211
provider, 0, 0, true);
12101212

12111213
try {
1212-
return mService.getLastLocation(request);
1214+
return mService.getLastLocation(request, packageName);
12131215
} catch (RemoteException e) {
12141216
Log.e(TAG, "RemoteException", e);
12151217
return null;

services/java/com/android/server/LocationManagerService.java

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
import com.android.server.location.GeocoderProxy;
6464
import com.android.server.location.GeofenceManager;
6565
import com.android.server.location.GpsLocationProvider;
66+
import com.android.server.location.LocationBlacklist;
6667
import com.android.server.location.LocationFudger;
6768
import com.android.server.location.LocationProviderInterface;
6869
import com.android.server.location.LocationProviderProxy;
@@ -132,8 +133,8 @@ public class LocationManagerService extends ILocationManager.Stub implements Obs
132133
private IGpsStatusProvider mGpsStatusProvider;
133134
private INetInitiatedListener mNetInitiatedListener;
134135
private LocationWorkerHandler mLocationHandler;
135-
// track the passive provider for some special cases
136-
private PassiveProvider mPassiveProvider;
136+
private PassiveProvider mPassiveProvider; // track passive provider for special cases
137+
private LocationBlacklist mBlacklist;
137138

138139
// --- fields below are protected by mWakeLock ---
139140
private int mPendingBroadcasts;
@@ -208,7 +209,9 @@ private void init() {
208209
synchronized (mLock) {
209210
loadProvidersLocked();
210211
}
211-
mGeofenceManager = new GeofenceManager(mContext);
212+
mBlacklist = new LocationBlacklist(mContext, mLocationHandler);
213+
mBlacklist.init();
214+
mGeofenceManager = new GeofenceManager(mContext, mBlacklist);
212215
mLocationFudger = new LocationFudger();
213216

214217
// Register for Network (Wifi or Mobile) updates
@@ -1063,10 +1066,17 @@ private void removeUpdatesLocked(Receiver receiver) {
10631066
}
10641067

10651068
@Override
1066-
public Location getLastLocation(LocationRequest request) {
1069+
public Location getLastLocation(LocationRequest request, String packageName) {
10671070
if (D) Log.d(TAG, "getLastLocation: " + request);
10681071
if (request == null) request = DEFAULT_LOCATION_REQUEST;
10691072
String perm = checkPermissionAndRequest(request);
1073+
checkPackageName(packageName);
1074+
1075+
if (mBlacklist.isBlacklisted(packageName)) {
1076+
if (D) Log.d(TAG, "not returning last loc for blacklisted app: " +
1077+
packageName);
1078+
return null;
1079+
}
10701080

10711081
synchronized (mLock) {
10721082
// Figure out the provider. Either its explicitly request (deprecated API's),
@@ -1325,6 +1335,13 @@ private void handleLocationChangedLocked(Location location, boolean passive) {
13251335
for (UpdateRecord r : records) {
13261336
Receiver receiver = r.mReceiver;
13271337
boolean receiverDead = false;
1338+
1339+
if (mBlacklist.isBlacklisted(receiver.mPackageName)) {
1340+
if (D) Log.d(TAG, "skipping loc update for blacklisted app: " +
1341+
receiver.mPackageName);
1342+
continue;
1343+
}
1344+
13281345
if (ACCESS_FINE_LOCATION.equals(receiver.mPermission)) {
13291346
location = lastLocation; // use fine location
13301347
} else {
@@ -1716,8 +1733,9 @@ protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
17161733
for (String i : mDisabledProviders) {
17171734
pw.println(" " + i);
17181735
}
1719-
17201736
}
1737+
pw.append(" ");
1738+
mBlacklist.dump(pw);
17211739
if (mMockProviders.size() > 0) {
17221740
pw.println(" Mock Providers:");
17231741
for (Map.Entry<String, MockProvider> i : mMockProviders.entrySet()) {

services/java/com/android/server/location/GeofenceManager.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,13 @@
3434
import android.os.Looper;
3535
import android.os.PowerManager;
3636
import android.os.SystemClock;
37+
import android.util.Log;
38+
39+
import com.android.server.LocationManagerService;
3740

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

4145
/**
4246
* Assume a maximum land speed, as a heuristic to throttle location updates.
@@ -49,19 +53,21 @@ public class GeofenceManager implements LocationListener, PendingIntent.OnFinish
4953
private final LocationManager mLocationManager;
5054
private final PowerManager.WakeLock mWakeLock;
5155
private final Looper mLooper; // looper thread to take location updates on
56+
private final LocationBlacklist mBlacklist;
5257

5358
private Object mLock = new Object();
5459

5560
// access to members below is synchronized on mLock
5661
private Location mLastLocation;
5762
private List<GeofenceState> mFences = new LinkedList<GeofenceState>();
5863

59-
public GeofenceManager(Context context) {
64+
public GeofenceManager(Context context, LocationBlacklist blacklist) {
6065
mContext = context;
6166
mLocationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
6267
PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
6368
mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
6469
mLooper = Looper.myLooper();
70+
mBlacklist = blacklist;
6571

6672
LocationRequest request = new LocationRequest()
6773
.setQuality(LocationRequest.POWER_NONE)
@@ -145,6 +151,12 @@ private void processLocation(Location location) {
145151
removeExpiredFencesLocked();
146152

147153
for (GeofenceState state : mFences) {
154+
if (mBlacklist.isBlacklisted(state.mPackageName)) {
155+
if (D) Log.d(TAG, "skipping geofence processing for blacklisted app: " +
156+
state.mPackageName);
157+
continue;
158+
}
159+
148160
int event = state.processLocation(location);
149161
if ((event & GeofenceState.FLAG_ENTER) != 0) {
150162
enterIntents.add(state.mIntent);
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
/*
2+
* Copyright (C) 2012 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
18+
package com.android.server.location;
19+
20+
import android.content.Context;
21+
import android.database.ContentObserver;
22+
import android.os.Handler;
23+
import android.provider.Settings;
24+
import android.util.Log;
25+
import android.util.Slog;
26+
27+
import com.android.server.LocationManagerService;
28+
29+
import java.io.PrintWriter;
30+
import java.util.ArrayList;
31+
import java.util.Arrays;
32+
33+
/**
34+
* Allows applications to be blacklisted from location updates at run-time.
35+
*
36+
* This is a silent blacklist. Applications can still call Location Manager
37+
* API's, but they just won't receive any locations.
38+
*/
39+
public final class LocationBlacklist extends ContentObserver {
40+
private static final String TAG = "LocationBlacklist";
41+
private static final boolean D = LocationManagerService.D;
42+
private static final String BLACKLIST_CONFIG_NAME = "locationPackagePrefixBlacklist";
43+
private static final String WHITELIST_CONFIG_NAME = "locationPackagePrefixWhitelist";
44+
45+
private final Context mContext;
46+
private final Object mLock = new Object();
47+
48+
// all fields below synchronized on mLock
49+
private String[] mWhitelist = new String[0];
50+
private String[] mBlacklist = new String[0];
51+
52+
public LocationBlacklist(Context context, Handler handler) {
53+
super(handler);
54+
mContext = context;
55+
}
56+
57+
public void init() {
58+
mContext.getContentResolver().registerContentObserver(Settings.Secure.getUriFor(
59+
BLACKLIST_CONFIG_NAME), false, this);
60+
// mContext.getContentResolver().registerContentObserver(Settings.Secure.getUriFor(
61+
// WHITELIST_CONFIG_NAME), false, this);
62+
reloadBlacklist();
63+
}
64+
65+
private void reloadBlacklist() {
66+
String blacklist[] = getStringArray(BLACKLIST_CONFIG_NAME);
67+
String whitelist[] = getStringArray(WHITELIST_CONFIG_NAME);
68+
synchronized (mLock) {
69+
mWhitelist = whitelist;
70+
Slog.i(TAG, "whitelist: " + Arrays.toString(mWhitelist));
71+
mBlacklist = blacklist;
72+
Slog.i(TAG, "blacklist: " + Arrays.toString(mBlacklist));
73+
}
74+
}
75+
76+
/**
77+
* Return true if in blacklist
78+
* (package name matches blacklist, and does not match whitelist)
79+
*/
80+
public boolean isBlacklisted(String packageName) {
81+
synchronized (mLock) {
82+
for (String black : mBlacklist) {
83+
if (packageName.startsWith(black)) {
84+
if (inWhitelist(packageName)) {
85+
continue;
86+
} else {
87+
if (D) Log.d(TAG, "dropping location (blacklisted): "
88+
+ packageName + " matches " + black);
89+
return true;
90+
}
91+
}
92+
}
93+
}
94+
return false;
95+
}
96+
97+
/**
98+
* Return true if any of packages are in whitelist
99+
*/
100+
private boolean inWhitelist(String pkg) {
101+
synchronized (mLock) {
102+
for (String white : mWhitelist) {
103+
if (pkg.startsWith(white)) return true;
104+
}
105+
}
106+
return false;
107+
}
108+
109+
@Override
110+
public void onChange(boolean selfChange) {
111+
reloadBlacklist();
112+
}
113+
114+
private String[] getStringArray(String key) {
115+
String flatString = Settings.Secure.getString(mContext.getContentResolver(), key);
116+
if (flatString == null) {
117+
return new String[0];
118+
}
119+
String[] splitStrings = flatString.split(",");
120+
ArrayList<String> result = new ArrayList<String>();
121+
for (String pkg : splitStrings) {
122+
pkg = pkg.trim();
123+
if (pkg.isEmpty()) {
124+
continue;
125+
}
126+
result.add(pkg);
127+
}
128+
return result.toArray(new String[result.size()]);
129+
}
130+
131+
public void dump(PrintWriter pw) {
132+
pw.println("mWhitelist=" + Arrays.toString(mWhitelist) + " mBlacklist=" +
133+
Arrays.toString(mBlacklist));
134+
}
135+
}

0 commit comments

Comments
 (0)