diff options
author | Nick Pelly <npelly@google.com> | 2012-07-31 09:17:54 -0700 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2012-07-31 09:17:54 -0700 |
commit | 1af5ac1b6801c4da2ef689449fd1fd2eba1ff48e (patch) | |
tree | 9904a0d9c1c4106857cef6461f8ceb526885e7c8 | |
parent | 28b452fddf85de27ad88b2b5de884c8428e74f1e (diff) | |
parent | 48c5eb018b1731bd47caccd43cda2cd36ebc271f (diff) | |
download | frameworks_base-1af5ac1b6801c4da2ef689449fd1fd2eba1ff48e.zip frameworks_base-1af5ac1b6801c4da2ef689449fd1fd2eba1ff48e.tar.gz frameworks_base-1af5ac1b6801c4da2ef689449fd1fd2eba1ff48e.tar.bz2 |
Merge "DO NOT MERGE. Add package-name-prefix blacklist for location updates." into jb-dev
-rw-r--r-- | core/java/android/app/ContextImpl.java | 6 | ||||
-rw-r--r-- | location/java/android/location/ILocationManager.aidl | 12 | ||||
-rw-r--r-- | location/java/android/location/LocationManager.java | 20 | ||||
-rw-r--r-- | services/java/com/android/server/LocationManagerService.java | 191 |
4 files changed, 190 insertions, 39 deletions
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index b902550..411f6d0 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -361,10 +361,10 @@ class ContextImpl extends Context { return PolicyManager.makeNewLayoutInflater(ctx.getOuterContext()); }}); - registerService(LOCATION_SERVICE, new StaticServiceFetcher() { - public Object createStaticService() { + registerService(LOCATION_SERVICE, new ServiceFetcher() { + public Object createService(ContextImpl ctx) { IBinder b = ServiceManager.getService(LOCATION_SERVICE); - return new LocationManager(ILocationManager.Stub.asInterface(b)); + return new LocationManager(ctx, ILocationManager.Stub.asInterface(b)); }}); registerService(NETWORK_POLICY_SERVICE, new ServiceFetcher() { diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl index 2255bf2..38a29d3 100644 --- a/location/java/android/location/ILocationManager.aidl +++ b/location/java/android/location/ILocationManager.aidl @@ -39,11 +39,11 @@ interface ILocationManager boolean providerMeetsCriteria(String provider, in Criteria criteria); void requestLocationUpdates(String provider, in Criteria criteria, long minTime, float minDistance, - boolean singleShot, in ILocationListener listener); + boolean singleShot, in ILocationListener listener, String packageName); void requestLocationUpdatesPI(String provider, in Criteria criteria, long minTime, float minDistance, - boolean singleShot, in PendingIntent intent); - void removeUpdates(in ILocationListener listener); - void removeUpdatesPI(in PendingIntent intent); + boolean singleShot, in PendingIntent intent, String packageName); + void removeUpdates(in ILocationListener listener, String packageName); + void removeUpdatesPI(in PendingIntent intent, String packageName); boolean addGpsStatusListener(IGpsStatusListener listener); void removeGpsStatusListener(IGpsStatusListener listener); @@ -54,13 +54,13 @@ interface ILocationManager boolean sendExtraCommand(String provider, String command, inout Bundle extras); void addProximityAlert(double latitude, double longitude, float distance, - long expiration, in PendingIntent intent); + long expiration, in PendingIntent intent, String packageName); void removeProximityAlert(in PendingIntent intent); Bundle getProviderInfo(String provider); boolean isProviderEnabled(String provider); - Location getLastKnownLocation(String provider); + Location getLastKnownLocation(String provider, String packageName); // Used by location providers to tell the location manager when it has a new location. // Passive is true if the location is coming from the passive provider, in which case diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java index 1299574..5c256a3 100644 --- a/location/java/android/location/LocationManager.java +++ b/location/java/android/location/LocationManager.java @@ -17,6 +17,7 @@ package android.location; import android.app.PendingIntent; +import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.os.Looper; @@ -160,6 +161,8 @@ public class LocationManager { */ public static final String EXTRA_GPS_ENABLED = "enabled"; + private final Context mContext; + // Map from LocationListeners to their associated ListenerTransport objects private HashMap<LocationListener,ListenerTransport> mListeners = new HashMap<LocationListener,ListenerTransport>(); @@ -260,8 +263,9 @@ public class LocationManager { * right way to create an instance of this class is using the * factory Context.getSystemService. */ - public LocationManager(ILocationManager service) { + public LocationManager(Context context, ILocationManager service) { mService = service; + mContext = context; } private LocationProvider createProvider(String name, Bundle info) { @@ -657,7 +661,8 @@ public class LocationManager { transport = new ListenerTransport(listener, looper); } mListeners.put(listener, transport); - mService.requestLocationUpdates(provider, criteria, minTime, minDistance, singleShot, transport); + mService.requestLocationUpdates(provider, criteria, minTime, minDistance, + singleShot, transport, mContext.getPackageName()); } } catch (RemoteException ex) { Log.e(TAG, "requestLocationUpdates: DeadObjectException", ex); @@ -837,7 +842,8 @@ public class LocationManager { } try { - mService.requestLocationUpdatesPI(provider, criteria, minTime, minDistance, singleShot, intent); + mService.requestLocationUpdatesPI(provider, criteria, minTime, minDistance, singleShot, + intent, mContext.getPackageName()); } catch (RemoteException ex) { Log.e(TAG, "requestLocationUpdates: RemoteException", ex); } @@ -1005,7 +1011,7 @@ public class LocationManager { try { ListenerTransport transport = mListeners.remove(listener); if (transport != null) { - mService.removeUpdates(transport); + mService.removeUpdates(transport, mContext.getPackageName()); } } catch (RemoteException ex) { Log.e(TAG, "removeUpdates: DeadObjectException", ex); @@ -1028,7 +1034,7 @@ public class LocationManager { Log.d(TAG, "removeUpdates: intent = " + intent); } try { - mService.removeUpdatesPI(intent); + mService.removeUpdatesPI(intent, mContext.getPackageName()); } catch (RemoteException ex) { Log.e(TAG, "removeUpdates: RemoteException", ex); } @@ -1087,7 +1093,7 @@ public class LocationManager { } try { mService.addProximityAlert(latitude, longitude, radius, - expiration, intent); + expiration, intent, mContext.getPackageName()); } catch (RemoteException ex) { Log.e(TAG, "addProximityAlert: RemoteException", ex); } @@ -1153,7 +1159,7 @@ public class LocationManager { throw new IllegalArgumentException("provider==null"); } try { - return mService.getLastKnownLocation(provider); + return mService.getLastKnownLocation(provider, mContext.getPackageName()); } catch (RemoteException ex) { Log.e(TAG, "getLastKnowLocation: RemoteException", ex); return null; diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java index 2918dbc..8c1581c 100644 --- a/services/java/com/android/server/LocationManagerService.java +++ b/services/java/com/android/server/LocationManagerService.java @@ -32,6 +32,7 @@ import android.content.pm.ResolveInfo; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.Signature; import android.content.res.Resources; +import android.database.ContentObserver; import android.database.Cursor; import android.location.Address; import android.location.Criteria; @@ -79,6 +80,8 @@ import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Observable; @@ -109,6 +112,9 @@ public class LocationManagerService extends ILocationManager.Stub implements Run private static final String INSTALL_LOCATION_PROVIDER = android.Manifest.permission.INSTALL_LOCATION_PROVIDER; + private static final String BLACKLIST_CONFIG_NAME = "locationPackagePrefixBlacklist"; + private static final String WHITELIST_CONFIG_NAME = "locationPackagePrefixWhitelist"; + // Location Providers may sometimes deliver location updates // slightly faster that requested - provide grace period so // we don't unnecessarily filter events that are otherwise on @@ -193,6 +199,10 @@ public class LocationManagerService extends ILocationManager.Stub implements Run private int mNetworkState = LocationProvider.TEMPORARILY_UNAVAILABLE; + // for prefix blacklist + private String[] mWhitelist = new String[0]; + private String[] mBlacklist = new String[0]; + // for Settings change notification private ContentQueryMap mSettings; @@ -205,20 +215,23 @@ public class LocationManagerService extends ILocationManager.Stub implements Run final PendingIntent mPendingIntent; final Object mKey; final HashMap<String,UpdateRecord> mUpdateRecords = new HashMap<String,UpdateRecord>(); + final String mPackageName; int mPendingBroadcasts; String mRequiredPermissions; - Receiver(ILocationListener listener) { + Receiver(ILocationListener listener, String packageName) { mListener = listener; mPendingIntent = null; mKey = listener.asBinder(); + mPackageName = packageName; } - Receiver(PendingIntent intent) { + Receiver(PendingIntent intent, String packageName) { mPendingIntent = intent; mListener = null; mKey = intent; + mPackageName = packageName; } @Override @@ -601,6 +614,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run // Load providers loadProviders(); + loadBlacklist(); // Register for Network (Wifi or Mobile) updates IntentFilter intentFilter = new IntentFilter(); @@ -1110,11 +1124,11 @@ public class LocationManagerService extends ILocationManager.Stub implements Run } } - private Receiver getReceiver(ILocationListener listener) { + private Receiver getReceiver(ILocationListener listener, String packageName) { IBinder binder = listener.asBinder(); Receiver receiver = mReceivers.get(binder); if (receiver == null) { - receiver = new Receiver(listener); + receiver = new Receiver(listener, packageName); mReceivers.put(binder, receiver); try { @@ -1129,10 +1143,10 @@ public class LocationManagerService extends ILocationManager.Stub implements Run return receiver; } - private Receiver getReceiver(PendingIntent intent) { + private Receiver getReceiver(PendingIntent intent, String packageName) { Receiver receiver = mReceivers.get(intent); if (receiver == null) { - receiver = new Receiver(intent); + receiver = new Receiver(intent, packageName); mReceivers.put(intent, receiver); } return receiver; @@ -1157,7 +1171,9 @@ public class LocationManagerService extends ILocationManager.Stub implements Run } public void requestLocationUpdates(String provider, Criteria criteria, - long minTime, float minDistance, boolean singleShot, ILocationListener listener) { + long minTime, float minDistance, boolean singleShot, ILocationListener listener, + String packageName) { + checkPackageName(Binder.getCallingUid(), packageName); if (criteria != null) { // FIXME - should we consider using multiple providers simultaneously // rather than only the best one? @@ -1170,7 +1186,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run try { synchronized (mLock) { requestLocationUpdatesLocked(provider, minTime, minDistance, singleShot, - getReceiver(listener)); + getReceiver(listener, packageName)); } } catch (SecurityException se) { throw se; @@ -1194,7 +1210,9 @@ public class LocationManagerService extends ILocationManager.Stub implements Run } public void requestLocationUpdatesPI(String provider, Criteria criteria, - long minTime, float minDistance, boolean singleShot, PendingIntent intent) { + long minTime, float minDistance, boolean singleShot, PendingIntent intent, + String packageName) { + checkPackageName(Binder.getCallingUid(), packageName); validatePendingIntent(intent); if (criteria != null) { // FIXME - should we consider using multiple providers simultaneously @@ -1208,7 +1226,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run try { synchronized (mLock) { requestLocationUpdatesLocked(provider, minTime, minDistance, singleShot, - getReceiver(intent)); + getReceiver(intent, packageName)); } } catch (SecurityException se) { throw se; @@ -1270,10 +1288,10 @@ public class LocationManagerService extends ILocationManager.Stub implements Run } } - public void removeUpdates(ILocationListener listener) { + public void removeUpdates(ILocationListener listener, String packageName) { try { synchronized (mLock) { - removeUpdatesLocked(getReceiver(listener)); + removeUpdatesLocked(getReceiver(listener, packageName)); } } catch (SecurityException se) { throw se; @@ -1284,10 +1302,10 @@ public class LocationManagerService extends ILocationManager.Stub implements Run } } - public void removeUpdatesPI(PendingIntent intent) { + public void removeUpdatesPI(PendingIntent intent, String packageName) { try { synchronized (mLock) { - removeUpdatesLocked(getReceiver(intent)); + removeUpdatesLocked(getReceiver(intent, packageName)); } } catch (SecurityException se) { throw se; @@ -1446,15 +1464,17 @@ public class LocationManagerService extends ILocationManager.Stub implements Run final long mExpiration; final PendingIntent mIntent; final Location mLocation; + final String mPackageName; public ProximityAlert(int uid, double latitude, double longitude, - float radius, long expiration, PendingIntent intent) { + float radius, long expiration, PendingIntent intent, String packageName) { mUid = uid; mLatitude = latitude; mLongitude = longitude; mRadius = radius; mExpiration = expiration; mIntent = intent; + mPackageName = packageName; mLocation = new Location(""); mLocation.setLatitude(latitude); @@ -1522,6 +1542,10 @@ public class LocationManagerService extends ILocationManager.Stub implements Run PendingIntent intent = alert.getIntent(); long expiration = alert.getExpiration(); + if (inBlacklist(alert.mPackageName)) { + continue; + } + if ((expiration == -1) || (now <= expiration)) { boolean entered = mProximitiesEntered.contains(alert); boolean inProximity = @@ -1632,11 +1656,12 @@ public class LocationManagerService extends ILocationManager.Stub implements Run } public void addProximityAlert(double latitude, double longitude, - float radius, long expiration, PendingIntent intent) { + float radius, long expiration, PendingIntent intent, String packageName) { validatePendingIntent(intent); try { synchronized (mLock) { - addProximityAlertLocked(latitude, longitude, radius, expiration, intent); + addProximityAlertLocked(latitude, longitude, radius, expiration, intent, + packageName); } } catch (SecurityException se) { throw se; @@ -1648,7 +1673,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run } private void addProximityAlertLocked(double latitude, double longitude, - float radius, long expiration, PendingIntent intent) { + float radius, long expiration, PendingIntent intent, String packageName) { if (LOCAL_LOGV) { Slog.v(TAG, "addProximityAlert: latitude = " + latitude + ", longitude = " + longitude + @@ -1656,6 +1681,8 @@ public class LocationManagerService extends ILocationManager.Stub implements Run ", intent = " + intent); } + checkPackageName(Binder.getCallingUid(), packageName); + // Require ability to access all providers for now if (!isAllowedProviderSafe(LocationManager.GPS_PROVIDER) || !isAllowedProviderSafe(LocationManager.NETWORK_PROVIDER)) { @@ -1666,12 +1693,12 @@ public class LocationManagerService extends ILocationManager.Stub implements Run expiration += System.currentTimeMillis(); } ProximityAlert alert = new ProximityAlert(Binder.getCallingUid(), - latitude, longitude, radius, expiration, intent); + latitude, longitude, radius, expiration, intent, packageName); mProximityAlerts.put(intent, alert); if (mProximityReceiver == null) { mProximityListener = new ProximityListener(); - mProximityReceiver = new Receiver(mProximityListener); + mProximityReceiver = new Receiver(mProximityListener, packageName); for (int i = mProviders.size() - 1; i >= 0; i--) { LocationProviderInterface provider = mProviders.get(i); @@ -1787,13 +1814,13 @@ public class LocationManagerService extends ILocationManager.Stub implements Run return isAllowedBySettingsLocked(provider); } - public Location getLastKnownLocation(String provider) { + public Location getLastKnownLocation(String provider, String packageName) { if (LOCAL_LOGV) { Slog.v(TAG, "getLastKnownLocation: " + provider); } try { synchronized (mLock) { - return _getLastKnownLocationLocked(provider); + return _getLastKnownLocationLocked(provider, packageName); } } catch (SecurityException se) { throw se; @@ -1803,8 +1830,9 @@ public class LocationManagerService extends ILocationManager.Stub implements Run } } - private Location _getLastKnownLocationLocked(String provider) { + private Location _getLastKnownLocationLocked(String provider, String packageName) { checkPermissionsSafe(provider, null); + checkPackageName(Binder.getCallingUid(), packageName); LocationProviderInterface p = mProvidersByName.get(provider); if (p == null) { @@ -1815,6 +1843,10 @@ public class LocationManagerService extends ILocationManager.Stub implements Run return null; } + if (inBlacklist(packageName)) { + return null; + } + return mLastKnownLocation.get(provider); } @@ -1877,6 +1909,10 @@ public class LocationManagerService extends ILocationManager.Stub implements Run Receiver receiver = r.mReceiver; boolean receiverDead = false; + if (inBlacklist(receiver.mPackageName)) { + continue; + } + Location lastLoc = r.mLastFixBroadcast; if ((lastLoc == null) || shouldBroadcastSafe(location, lastLoc, r)) { if (lastLoc == null) { @@ -2315,6 +2351,113 @@ public class LocationManagerService extends ILocationManager.Stub implements Run } } + public class BlacklistObserver extends ContentObserver { + public BlacklistObserver(Handler handler) { + super(handler); + } + @Override + public void onChange(boolean selfChange) { + reloadBlacklist(); + } + } + + private void loadBlacklist() { + // Register for changes + BlacklistObserver observer = new BlacklistObserver(mLocationHandler); + mContext.getContentResolver().registerContentObserver(Settings.Secure.getUriFor( + BLACKLIST_CONFIG_NAME), false, observer); + mContext.getContentResolver().registerContentObserver(Settings.Secure.getUriFor( + WHITELIST_CONFIG_NAME), false, observer); + reloadBlacklist(); + } + + private void reloadBlacklist() { + String blacklist[] = getStringArray(BLACKLIST_CONFIG_NAME); + String whitelist[] = getStringArray(WHITELIST_CONFIG_NAME); + synchronized (mLock) { + mWhitelist = whitelist; + Slog.i(TAG, "whitelist: " + arrayToString(mWhitelist)); + mBlacklist = blacklist; + Slog.i(TAG, "blacklist: " + arrayToString(mBlacklist)); + } + } + + private static String arrayToString(String[] array) { + StringBuilder s = new StringBuilder(); + s.append('['); + boolean first = true; + for (String a : array) { + if (!first) s.append(','); + first = false; + s.append(a); + } + s.append(']'); + return s.toString(); + } + + 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()]); + } + + /** + * Return true if in blacklist, and not in whitelist. + */ + private boolean inBlacklist(String packageName) { + synchronized (mLock) { + for (String black : mBlacklist) { + if (packageName.startsWith(black)) { + if (inWhitelist(packageName)) { + continue; + } else { + if (LOCAL_LOGV) 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; + } + + private void checkPackageName(int uid, String packageName) { + if (packageName == null) { + throw new SecurityException("packageName cannot be null"); + } + String[] packages = mPackageManager.getPackagesForUid(uid); + if (packages == null) { + throw new SecurityException("invalid UID " + uid); + } + for (String pkg : packages) { + if (packageName.equals(pkg)) return; + } + throw new SecurityException("invalid package name"); + } + private void log(String log) { if (Log.isLoggable(TAG, Log.VERBOSE)) { Slog.d(TAG, log); @@ -2346,6 +2489,8 @@ public class LocationManagerService extends ILocationManager.Stub implements Run j.getValue().dump(pw, " "); } } + pw.println(" Package blacklist:" + arrayToString(mBlacklist)); + pw.println(" Package whitelist:" + arrayToString(mWhitelist)); pw.println(" Records by Provider:"); for (Map.Entry<String, ArrayList<UpdateRecord>> i : mRecordsByProvider.entrySet()) { |