diff --git a/api/current.xml b/api/current.xml
index 5080ca3e59061..ceaaf7992ad4a 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -529,6 +529,28 @@
visibility="public"
>
+
+
+
+
+
+
+
+
+
+
@@ -921,7 +933,7 @@
+ android:protectionLevel="signatureOrSystem" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index c35676cac1889..6e2da4b84cf8e 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -752,6 +752,19 @@
Malicious applications could use this to interfere with the operation of the GPS
or other location sources.
+
+ permission to install a location provider
+
+ Create mock location sources for testing.
+ Malicious applications can use this to override the location and/or status returned by real
+ location sources such as GPS or Network providers.
+
+
+ permission to install a location collector
+
+ Create mock location sources for testing.
+ Malicious applications can use this to monitor and report your location to an external source.
+
fine (GPS) location
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl
index 096622a1e3cf8..2c214c9ef3b64 100644
--- a/location/java/android/location/ILocationManager.aidl
+++ b/location/java/android/location/ILocationManager.aidl
@@ -59,9 +59,9 @@ interface ILocationManager
boolean isProviderEnabled(String provider);
Location getLastKnownLocation(String provider);
-
+
/* used by location providers to tell the location manager when it has a new location */
- void setLocation(in Location location);
+ void reportLocation(in Location location);
String getFromLocation(double latitude, double longitude, int maxResults,
String language, String country, String variant, String appName, out List
addrs);
@@ -82,7 +82,7 @@ interface ILocationManager
void clearTestProviderStatus(String provider);
/* for installing external Location Providers */
- void setNetworkLocationProvider(ILocationProvider provider);
- void setLocationCollector(ILocationCollector collector);
- void setGeocodeProvider(IGeocodeProvider provider);
+ void installLocationProvider(String name, ILocationProvider provider);
+ void installLocationCollector(ILocationCollector collector);
+ void installGeocodeProvider(IGeocodeProvider provider);
}
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index dacfeb9cee6c0..aef89850169bd 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -1255,4 +1255,85 @@ public class LocationManager {
return false;
}
}
+
+ /**
+ * Installs a network location provider.
+ *
+ * @param name of the location provider
+ * @param provider Binder interface for the location provider
+ *
+ * @return true if the command succeeds.
+ *
+ * Requires the android.permission.INSTALL_LOCATION_PROVIDER permission.
+ *
+ * {@hide}
+ */
+ public boolean installLocationProvider(String name, ILocationProvider provider) {
+ try {
+ mService.installLocationProvider(name, provider);
+ return true;
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException in installLocationProvider: ", e);
+ return false;
+ }
+ }
+
+ /**
+ * Installs a location collector.
+ *
+ * @param provider Binder interface for the location collector
+ *
+ * @return true if the command succeeds.
+ *
+ * Requires the android.permission.INSTALL_LOCATION_COLLECTOR permission.
+ *
+ * {@hide}
+ */
+ public boolean installLocationCollector(ILocationCollector collector) {
+ try {
+ mService.installLocationCollector(collector);
+ return true;
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException in setLocationCollector: ", e);
+ return false;
+ }
+ }
+
+ /**
+ * Installs a geocoder server.
+ *
+ * @param provider Binder interface for the geocoder provider
+ *
+ * @return true if the command succeeds.
+ *
+ * Requires the android.permission.INSTALL_LOCATION_PROVIDER permission.
+ *
+ * {@hide}
+ */
+ public boolean installGeocodeProvider(IGeocodeProvider provider) {
+ try {
+ mService.installGeocodeProvider(provider);
+ return true;
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException in setGeocodeProvider: ", e);
+ return false;
+ }
+ }
+
+ /**
+ * Used by location providers to report new locations.
+ *
+ * @param location new Location to report
+ *
+ * Requires the android.permission.INSTALL_LOCATION_PROVIDER permission.
+ *
+ * {@hide}
+ */
+ public void reportLocation(Location location) {
+ try {
+ mService.reportLocation(location);
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException in reportLocation: ", e);
+ }
+ }
}
diff --git a/location/java/com/android/internal/location/GpsLocationProvider.java b/location/java/com/android/internal/location/GpsLocationProvider.java
index 693848b8adc54..5877dd115899b 100644
--- a/location/java/com/android/internal/location/GpsLocationProvider.java
+++ b/location/java/com/android/internal/location/GpsLocationProvider.java
@@ -708,7 +708,7 @@ public class GpsLocationProvider extends ILocationProvider.Stub {
}
try {
- mLocationManager.setLocation(mLocation);
+ mLocationManager.reportLocation(mLocation);
} catch (RemoteException e) {
Log.e(TAG, "RemoteException calling reportLocation");
}
diff --git a/location/java/com/android/internal/location/MockProvider.java b/location/java/com/android/internal/location/MockProvider.java
index 6fa2c29278ccd..d81d0ab09fd64 100644
--- a/location/java/com/android/internal/location/MockProvider.java
+++ b/location/java/com/android/internal/location/MockProvider.java
@@ -138,7 +138,7 @@ public class MockProvider extends ILocationProvider.Stub {
mLocation.set(l);
mHasLocation = true;
try {
- mLocationManager.setLocation(mLocation);
+ mLocationManager.reportLocation(mLocation);
} catch (RemoteException e) {
Log.e(TAG, "RemoteException calling reportLocation");
}
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index d44abaaac472b..9af729efd3c19 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -106,6 +106,10 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
android.Manifest.permission.ACCESS_MOCK_LOCATION;
private static final String ACCESS_LOCATION_EXTRA_COMMANDS =
android.Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS;
+ private static final String INSTALL_LOCATION_PROVIDER =
+ android.Manifest.permission.INSTALL_LOCATION_PROVIDER;
+ private static final String INSTALL_LOCATION_COLLECTOR =
+ android.Manifest.permission.INSTALL_LOCATION_COLLECTOR;
// Set of providers that are explicitly enabled
private final Set mEnabledProviders = new HashSet();
@@ -626,36 +630,39 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
Looper.loop();
}
- public void setNetworkLocationProvider(ILocationProvider provider) {
- if (Binder.getCallingUid() != Process.SYSTEM_UID) {
- throw new SecurityException(
- "Installing location providers outside of the system is not supported");
+ public void installLocationProvider(String name, ILocationProvider provider) {
+ if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_PROVIDER)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Requires INSTALL_LOCATION_PROVIDER permission");
}
synchronized (mLock) {
- mNetworkLocationProvider =
- new LocationProviderProxy(LocationManager.NETWORK_PROVIDER, provider);
- addProvider(mNetworkLocationProvider);
- updateProvidersLocked();
-
- // notify NetworkLocationProvider of any events it might have missed
- mNetworkLocationProvider.updateNetworkState(mNetworkState);
+ // FIXME - only network location provider supported for now
+ if (LocationManager.NETWORK_PROVIDER.equals(name)) {
+ mNetworkLocationProvider = new LocationProviderProxy(name, provider);
+ addProvider(mNetworkLocationProvider);
+ updateProvidersLocked();
+
+ // notify NetworkLocationProvider of any events it might have missed
+ mNetworkLocationProvider.updateNetworkState(mNetworkState);
+ }
}
}
- public void setLocationCollector(ILocationCollector collector) {
- if (Binder.getCallingUid() != Process.SYSTEM_UID) {
- throw new SecurityException(
- "Installing location collectors outside of the system is not supported");
+ public void installLocationCollector(ILocationCollector collector) {
+ if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_COLLECTOR)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Requires INSTALL_LOCATION_COLLECTOR permission");
}
+ // FIXME - only support one collector
mCollector = collector;
}
- public void setGeocodeProvider(IGeocodeProvider provider) {
- if (Binder.getCallingUid() != Process.SYSTEM_UID) {
- throw new SecurityException(
- "Installing location providers outside of the system is not supported");
+ public void installGeocodeProvider(IGeocodeProvider provider) {
+ if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_PROVIDER)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Requires INSTALL_LOCATION_PROVIDER permission");
}
mGeocodeProvider = provider;
@@ -1472,7 +1479,12 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
}
}
- public void setLocation(Location location) {
+ public void reportLocation(Location location) {
+ if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_PROVIDER)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Requires INSTALL_LOCATION_PROVIDER permission");
+ }
+
mLocationHandler.removeMessages(MESSAGE_LOCATION_CHANGED, location);
Message m = Message.obtain(mLocationHandler, MESSAGE_LOCATION_CHANGED, location);
mLocationHandler.sendMessageAtFrontOfQueue(m);
diff --git a/test-runner/android/test/TestLocationProvider.java b/test-runner/android/test/TestLocationProvider.java
index 500786dee7b90..08603e39a9d25 100644
--- a/test-runner/android/test/TestLocationProvider.java
+++ b/test-runner/android/test/TestLocationProvider.java
@@ -189,7 +189,7 @@ public class TestLocationProvider extends ILocationProvider.Stub {
mLocation.setExtras(extras);
mLocation.setTime(time);
try {
- mLocationManager.setLocation(mLocation);
+ mLocationManager.reportLocation(mLocation);
} catch (RemoteException e) {
Log.e(TAG, "RemoteException calling updateLocation");
}