Loading core/java/android/app/ContextImpl.java +3 −3 Original line number Diff line number Diff line Loading @@ -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() { Loading location/java/android/location/ILocationManager.aidl +6 −6 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -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 Loading location/java/android/location/LocationManager.java +13 −7 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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>(); Loading Loading @@ -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) { Loading Loading @@ -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); Loading Loading @@ -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); } Loading Loading @@ -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); Loading @@ -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); } Loading Loading @@ -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); } Loading Loading @@ -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; Loading services/java/com/android/server/LocationManagerService.java +168 −23 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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 Loading Loading @@ -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; Loading @@ -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 Loading Loading @@ -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(); Loading Loading @@ -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 { Loading @@ -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; Loading @@ -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? Loading @@ -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; Loading @@ -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 Loading @@ -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; Loading Loading @@ -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; Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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 = Loading Loading @@ -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; Loading @@ -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 + Loading @@ -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)) { Loading @@ -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); Loading Loading @@ -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; Loading @@ -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) { Loading @@ -1815,6 +1843,10 @@ public class LocationManagerService extends ILocationManager.Stub implements Run return null; } if (inBlacklist(packageName)) { return null; } return mLastKnownLocation.get(provider); } Loading Loading @@ -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) { Loading Loading @@ -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); Loading Loading @@ -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()) { Loading Loading
core/java/android/app/ContextImpl.java +3 −3 Original line number Diff line number Diff line Loading @@ -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() { Loading
location/java/android/location/ILocationManager.aidl +6 −6 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -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 Loading
location/java/android/location/LocationManager.java +13 −7 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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>(); Loading Loading @@ -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) { Loading Loading @@ -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); Loading Loading @@ -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); } Loading Loading @@ -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); Loading @@ -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); } Loading Loading @@ -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); } Loading Loading @@ -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; Loading
services/java/com/android/server/LocationManagerService.java +168 −23 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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 Loading Loading @@ -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; Loading @@ -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 Loading Loading @@ -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(); Loading Loading @@ -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 { Loading @@ -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; Loading @@ -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? Loading @@ -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; Loading @@ -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 Loading @@ -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; Loading Loading @@ -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; Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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 = Loading Loading @@ -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; Loading @@ -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 + Loading @@ -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)) { Loading @@ -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); Loading Loading @@ -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; Loading @@ -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) { Loading @@ -1815,6 +1843,10 @@ public class LocationManagerService extends ILocationManager.Stub implements Run return null; } if (inBlacklist(packageName)) { return null; } return mLastKnownLocation.get(provider); } Loading Loading @@ -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) { Loading Loading @@ -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); Loading Loading @@ -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()) { Loading