diff --git a/api/current.txt b/api/current.txt
index d7b598239a97f..1f31221c0cc7e 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -3883,6 +3883,7 @@ package android.app {
field public static final java.lang.String OPSTR_COARSE_LOCATION = "android:coarse_location";
field public static final java.lang.String OPSTR_FINE_LOCATION = "android:fine_location";
field public static final java.lang.String OPSTR_GET_USAGE_STATS = "android:get_usage_stats";
+ field public static final java.lang.String OPSTR_MOCK_LOCATION = "android:mock_location";
field public static final java.lang.String OPSTR_MONITOR_HIGH_POWER_LOCATION = "android:monitor_location_high_power";
field public static final java.lang.String OPSTR_MONITOR_LOCATION = "android:monitor_location";
}
@@ -26602,7 +26603,7 @@ package android.provider {
field public static final java.lang.String ACCESSIBILITY_SPEAK_PASSWORD = "speak_password";
field public static final deprecated java.lang.String ADB_ENABLED = "adb_enabled";
field public static final java.lang.String ALLOWED_GEOLOCATION_ORIGINS = "allowed_geolocation_origins";
- field public static final java.lang.String ALLOW_MOCK_LOCATION = "mock_location";
+ field public static final deprecated java.lang.String ALLOW_MOCK_LOCATION = "mock_location";
field public static final java.lang.String ANDROID_ID = "android_id";
field public static final deprecated java.lang.String BACKGROUND_DATA = "background_data";
field public static final deprecated java.lang.String BLUETOOTH_ON = "bluetooth_on";
diff --git a/api/system-current.txt b/api/system-current.txt
index 832895cc1c5b9..eef35c4205bdb 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -3975,6 +3975,7 @@ package android.app {
field public static final java.lang.String OPSTR_COARSE_LOCATION = "android:coarse_location";
field public static final java.lang.String OPSTR_FINE_LOCATION = "android:fine_location";
field public static final java.lang.String OPSTR_GET_USAGE_STATS = "android:get_usage_stats";
+ field public static final java.lang.String OPSTR_MOCK_LOCATION = "android:mock_location";
field public static final java.lang.String OPSTR_MONITOR_HIGH_POWER_LOCATION = "android:monitor_location_high_power";
field public static final java.lang.String OPSTR_MONITOR_LOCATION = "android:monitor_location";
}
@@ -28627,7 +28628,7 @@ package android.provider {
field public static final java.lang.String ACCESSIBILITY_SPEAK_PASSWORD = "speak_password";
field public static final deprecated java.lang.String ADB_ENABLED = "adb_enabled";
field public static final java.lang.String ALLOWED_GEOLOCATION_ORIGINS = "allowed_geolocation_origins";
- field public static final java.lang.String ALLOW_MOCK_LOCATION = "mock_location";
+ field public static final deprecated java.lang.String ALLOW_MOCK_LOCATION = "mock_location";
field public static final java.lang.String ANDROID_ID = "android_id";
field public static final deprecated java.lang.String BACKGROUND_DATA = "background_data";
field public static final deprecated java.lang.String BLUETOOTH_ON = "bluetooth_on";
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 7104185bcc50d..e728971b7f667 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -227,8 +227,10 @@ public class AppOpsManager {
public static final int OP_BODY_SENSORS = 56;
/** @hide Read previously received cell broadcast messages. */
public static final int OP_READ_CELL_BROADCASTS = 57;
+ /** @hide Inject mock location into the system. */
+ public static final int OP_MOCK_LOCATION = 58;
/** @hide */
- public static final int _NUM_OP = 58;
+ public static final int _NUM_OP = 59;
/** Access to coarse location information. */
public static final String OPSTR_COARSE_LOCATION = "android:coarse_location";
@@ -308,6 +310,9 @@ public class AppOpsManager {
/** @hide Read previously received cell broadcast messages. */
public static final String OPSTR_READ_CELL_BROADCASTS
= "android:read_cell_broadcasts";
+ /** Inject mock location into the system. */
+ public static final String OPSTR_MOCK_LOCATION
+ = "android:mock_location";
/**
* This maps each operation to the operation that serves as the
@@ -375,7 +380,8 @@ public class AppOpsManager {
OP_PROCESS_OUTGOING_CALLS,
OP_USE_FINGERPRINT,
OP_BODY_SENSORS,
- OP_READ_CELL_BROADCASTS
+ OP_READ_CELL_BROADCASTS,
+ OP_MOCK_LOCATION
};
/**
@@ -440,7 +446,8 @@ public class AppOpsManager {
null,
OPSTR_USE_FINGERPRINT,
OPSTR_BODY_SENSORS,
- OPSTR_READ_CELL_BROADCASTS
+ OPSTR_READ_CELL_BROADCASTS,
+ OPSTR_MOCK_LOCATION
};
/**
@@ -505,7 +512,8 @@ public class AppOpsManager {
"PROCESS_OUTGOING_CALLS",
"USE_FINGERPRINT",
"BODY_SENSORS",
- "READ_CELL_BROADCASTS"
+ "READ_CELL_BROADCASTS",
+ "MOCK_LOCATION"
};
/**
@@ -570,7 +578,8 @@ public class AppOpsManager {
Manifest.permission.PROCESS_OUTGOING_CALLS,
Manifest.permission.USE_FINGERPRINT,
Manifest.permission.BODY_SENSORS,
- Manifest.permission.READ_CELL_BROADCASTS
+ Manifest.permission.READ_CELL_BROADCASTS,
+ null
};
/**
@@ -636,7 +645,8 @@ public class AppOpsManager {
null, // PROCESS_OUTGOING_CALLS
null, // USE_FINGERPRINT
null, // BODY_SENSORS
- null // READ_CELL_BROADCASTS
+ null, // READ_CELL_BROADCASTS
+ null // MOCK_LOCATION
};
/**
@@ -701,7 +711,8 @@ public class AppOpsManager {
false, // PROCESS_OUTGOING_CALLS
false, // USE_FINGERPRINT
false, // BODY_SENSORS
- false // READ_CELL_BROADCASTS
+ false, // READ_CELL_BROADCASTS
+ false // MOCK_LOCATION
};
/**
@@ -765,7 +776,8 @@ public class AppOpsManager {
AppOpsManager.MODE_ALLOWED,
AppOpsManager.MODE_ALLOWED,
AppOpsManager.MODE_ALLOWED,
- AppOpsManager.MODE_ALLOWED
+ AppOpsManager.MODE_ALLOWED,
+ AppOpsManager.MODE_ERRORED // OP_MOCK_LOCATION
};
/**
@@ -833,6 +845,7 @@ public class AppOpsManager {
false,
false,
false,
+ false,
false
};
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index d3a55610480fb..61b8bed83f965 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -4133,7 +4133,10 @@ public final class Settings {
* LocationManager service for testing purposes during application development. These
* locations and status values override actual location and status information generated
* by network, gps, or other location providers.
+ *
+ * @deprecated This settings is not used anymore.
*/
+ @Deprecated
public static final String ALLOW_MOCK_LOCATION = "mock_location";
/**
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index c59c1c9e7d7eb..edff537a51419 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -836,9 +836,7 @@
To send mock locations to Location Services in mock mode, a test app must request the permission - {@link android.Manifest.permission#ACCESS_MOCK_LOCATION}. In addition, you must enable mock + android.Manifest.permission#ACCESS_MOCK_LOCATION. In addition, you must enable mock locations on the test device using the option Enable mock locations. To learn how to enable mock locations on the device, see Setting up a Device for Development. diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl index af76175a1a4a4..a3ea896533805 100644 --- a/location/java/android/location/ILocationManager.aidl +++ b/location/java/android/location/ILocationManager.aidl @@ -77,14 +77,15 @@ interface ILocationManager ProviderProperties getProviderProperties(String provider); boolean isProviderEnabled(String provider); - void addTestProvider(String name, in ProviderProperties properties); - void removeTestProvider(String provider); - void setTestProviderLocation(String provider, in Location loc); - void clearTestProviderLocation(String provider); - void setTestProviderEnabled(String provider, boolean enabled); - void clearTestProviderEnabled(String provider); - void setTestProviderStatus(String provider, int status, in Bundle extras, long updateTime); - void clearTestProviderStatus(String provider); + void addTestProvider(String name, in ProviderProperties properties, String opPackageName); + void removeTestProvider(String provider, String opPackageName); + void setTestProviderLocation(String provider, in Location loc, String opPackageName); + void clearTestProviderLocation(String provider, String opPackageName); + void setTestProviderEnabled(String provider, boolean enabled, String opPackageName); + void clearTestProviderEnabled(String provider, String opPackageName); + void setTestProviderStatus(String provider, int status, in Bundle extras, long updateTime, + String opPackageName); + void clearTestProviderStatus(String provider, String opPackageName); boolean sendExtraCommand(String provider, String command, inout Bundle extras); diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java index a3d04d97cea14..b09f2169e8ad6 100644 --- a/location/java/android/location/LocationManager.java +++ b/location/java/android/location/LocationManager.java @@ -37,7 +37,6 @@ import java.util.List; import static android.Manifest.permission.ACCESS_COARSE_LOCATION; import static android.Manifest.permission.ACCESS_FINE_LOCATION; -import static android.Manifest.permission.ACCESS_MOCK_LOCATION; /** * This class provides access to the system location services. These @@ -1218,12 +1217,11 @@ public class LocationManager { * * @param name the provider name * - * @throws SecurityException if the ACCESS_MOCK_LOCATION permission is not present - * or the {@link android.provider.Settings.Secure#ALLOW_MOCK_LOCATION - * Settings.Secure.ALLOW_MOCK_LOCATION} system setting is not enabled + * @throws SecurityException if {@link android.app.AppOpsManager#OPSTR_MOCK_LOCATION + * mock location app op} is not set to {@link android.app.AppOpsManager#MODE_ALLOWED + * allowed} for your app. * @throws IllegalArgumentException if a provider with the given name already exists */ - @RequiresPermission(value = ACCESS_MOCK_LOCATION, conditional = true) public void addTestProvider(String name, boolean requiresNetwork, boolean requiresSatellite, boolean requiresCell, boolean hasMonetaryCost, boolean supportsAltitude, boolean supportsSpeed, boolean supportsBearing, int powerRequirement, int accuracy) { @@ -1235,7 +1233,7 @@ public class LocationManager { } try { - mService.addTestProvider(name, properties); + mService.addTestProvider(name, properties, mContext.getOpPackageName()); } catch (RemoteException e) { Log.e(TAG, "RemoteException", e); } @@ -1246,15 +1244,14 @@ public class LocationManager { * * @param provider the provider name * - * @throws SecurityException if the ACCESS_MOCK_LOCATION permission is not present - * or the {@link android.provider.Settings.Secure#ALLOW_MOCK_LOCATION - * Settings.Secure.ALLOW_MOCK_LOCATION}} system setting is not enabled + * @throws SecurityException if {@link android.app.AppOpsManager#OPSTR_MOCK_LOCATION + * mock location app op} is not set to {@link android.app.AppOpsManager#MODE_ALLOWED + * allowed} for your app. * @throws IllegalArgumentException if no provider with the given name exists */ - @RequiresPermission(value = ACCESS_MOCK_LOCATION, conditional = true) public void removeTestProvider(String provider) { try { - mService.removeTestProvider(provider); + mService.removeTestProvider(provider, mContext.getOpPackageName()); } catch (RemoteException e) { Log.e(TAG, "RemoteException", e); } @@ -1270,13 +1267,12 @@ public class LocationManager { * @param provider the provider name * @param loc the mock location * - * @throws SecurityException if the ACCESS_MOCK_LOCATION permission is not present - * or the {@link android.provider.Settings.Secure#ALLOW_MOCK_LOCATION - * Settings.Secure.ALLOW_MOCK_LOCATION}} system setting is not enabled + * @throws SecurityException if {@link android.app.AppOpsManager#OPSTR_MOCK_LOCATION + * mock location app op} is not set to {@link android.app.AppOpsManager#MODE_ALLOWED + * allowed} for your app. * @throws IllegalArgumentException if no provider with the given name exists * @throws IllegalArgumentException if the location is incomplete */ - @RequiresPermission(value = ACCESS_MOCK_LOCATION, conditional = true) public void setTestProviderLocation(String provider, Location loc) { if (!loc.isComplete()) { IllegalArgumentException e = new IllegalArgumentException( @@ -1292,7 +1288,7 @@ public class LocationManager { } try { - mService.setTestProviderLocation(provider, loc); + mService.setTestProviderLocation(provider, loc, mContext.getOpPackageName()); } catch (RemoteException e) { Log.e(TAG, "RemoteException", e); } @@ -1303,15 +1299,14 @@ public class LocationManager { * * @param provider the provider name * - * @throws SecurityException if the ACCESS_MOCK_LOCATION permission is not present - * or the {@link android.provider.Settings.Secure#ALLOW_MOCK_LOCATION - * Settings.Secure.ALLOW_MOCK_LOCATION}} system setting is not enabled + * @throws SecurityException if {@link android.app.AppOpsManager#OPSTR_MOCK_LOCATION + * mock location app op} is not set to {@link android.app.AppOpsManager#MODE_ALLOWED + * allowed} for your app. * @throws IllegalArgumentException if no provider with the given name exists */ - @RequiresPermission(value = ACCESS_MOCK_LOCATION, conditional = true) public void clearTestProviderLocation(String provider) { try { - mService.clearTestProviderLocation(provider); + mService.clearTestProviderLocation(provider, mContext.getOpPackageName()); } catch (RemoteException e) { Log.e(TAG, "RemoteException", e); } @@ -1324,15 +1319,14 @@ public class LocationManager { * @param provider the provider name * @param enabled the mock enabled value * - * @throws SecurityException if the ACCESS_MOCK_LOCATION permission is not present - * or the {@link android.provider.Settings.Secure#ALLOW_MOCK_LOCATION - * Settings.Secure.ALLOW_MOCK_LOCATION}} system setting is not enabled + * @throws SecurityException if {@link android.app.AppOpsManager#OPSTR_MOCK_LOCATION + * mock location app op} is not set to {@link android.app.AppOpsManager#MODE_ALLOWED + * allowed} for your app. * @throws IllegalArgumentException if no provider with the given name exists */ - @RequiresPermission(value = ACCESS_MOCK_LOCATION, conditional = true) public void setTestProviderEnabled(String provider, boolean enabled) { try { - mService.setTestProviderEnabled(provider, enabled); + mService.setTestProviderEnabled(provider, enabled, mContext.getOpPackageName()); } catch (RemoteException e) { Log.e(TAG, "RemoteException", e); } @@ -1343,15 +1337,14 @@ public class LocationManager { * * @param provider the provider name * - * @throws SecurityException if the ACCESS_MOCK_LOCATION permission is not present - * or the {@link android.provider.Settings.Secure#ALLOW_MOCK_LOCATION - * Settings.Secure.ALLOW_MOCK_LOCATION}} system setting is not enabled + * @throws SecurityException if {@link android.app.AppOpsManager#OPSTR_MOCK_LOCATION + * mock location app op} is not set to {@link android.app.AppOpsManager#MODE_ALLOWED + * allowed} for your app. * @throws IllegalArgumentException if no provider with the given name exists */ - @RequiresPermission(value = ACCESS_MOCK_LOCATION, conditional = true) public void clearTestProviderEnabled(String provider) { try { - mService.clearTestProviderEnabled(provider); + mService.clearTestProviderEnabled(provider, mContext.getOpPackageName()); } catch (RemoteException e) { Log.e(TAG, "RemoteException", e); } @@ -1366,15 +1359,15 @@ public class LocationManager { * @param extras a Bundle containing mock extras * @param updateTime the mock update time * - * @throws SecurityException if the ACCESS_MOCK_LOCATION permission is not present - * or the {@link android.provider.Settings.Secure#ALLOW_MOCK_LOCATION - * Settings.Secure.ALLOW_MOCK_LOCATION}} system setting is not enabled + * @throws SecurityException if {@link android.app.AppOpsManager#OPSTR_MOCK_LOCATION + * mock location app op} is not set to {@link android.app.AppOpsManager#MODE_ALLOWED + * allowed} for your app. * @throws IllegalArgumentException if no provider with the given name exists */ - @RequiresPermission(value = ACCESS_MOCK_LOCATION, conditional = true) public void setTestProviderStatus(String provider, int status, Bundle extras, long updateTime) { try { - mService.setTestProviderStatus(provider, status, extras, updateTime); + mService.setTestProviderStatus(provider, status, extras, updateTime, + mContext.getOpPackageName()); } catch (RemoteException e) { Log.e(TAG, "RemoteException", e); } @@ -1385,15 +1378,14 @@ public class LocationManager { * * @param provider the provider name * - * @throws SecurityException if the ACCESS_MOCK_LOCATION permission is not present - * or the {@link android.provider.Settings.Secure#ALLOW_MOCK_LOCATION - * Settings.Secure.ALLOW_MOCK_LOCATION}} system setting is not enabled + * @throws SecurityException if {@link android.app.AppOpsManager#OPSTR_MOCK_LOCATION + * mock location app op} is not set to {@link android.app.AppOpsManager#MODE_ALLOWED + * allowed} for your app. * @throws IllegalArgumentException if no provider with the given name exists */ - @RequiresPermission(value = ACCESS_MOCK_LOCATION, conditional = true) public void clearTestProviderStatus(String provider) { try { - mService.clearTestProviderStatus(provider); + mService.clearTestProviderStatus(provider, mContext.getOpPackageName()); } catch (RemoteException e) { Log.e(TAG, "RemoteException", e); } diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java index 387967644fead..c76fc1c2a1236 100644 --- a/services/core/java/com/android/server/LocationManagerService.java +++ b/services/core/java/com/android/server/LocationManagerService.java @@ -2352,22 +2352,16 @@ public class LocationManagerService extends ILocationManager.Stub { // Mock Providers - private void checkMockPermissionsSafe() { - boolean allowMocks = Settings.Secure.getInt(mContext.getContentResolver(), - Settings.Secure.ALLOW_MOCK_LOCATION, 0) == 1; - if (!allowMocks) { - throw new SecurityException("Requires ACCESS_MOCK_LOCATION secure setting"); - } - - if (mContext.checkCallingPermission(ACCESS_MOCK_LOCATION) != - PackageManager.PERMISSION_GRANTED) { - throw new SecurityException("Requires ACCESS_MOCK_LOCATION permission"); - } + private boolean canCallerAccessMockLocation(String opPackageName) { + return mAppOps.noteOp(AppOpsManager.OP_MOCK_LOCATION, Binder.getCallingUid(), + opPackageName) == AppOpsManager.MODE_ALLOWED; } @Override - public void addTestProvider(String name, ProviderProperties properties) { - checkMockPermissionsSafe(); + public void addTestProvider(String name, ProviderProperties properties, String opPackageName) { + if (!canCallerAccessMockLocation(opPackageName)) { + return; + } if (LocationManager.PASSIVE_PROVIDER.equals(name)) { throw new IllegalArgumentException("Cannot mock the passive location provider"); @@ -2402,15 +2396,18 @@ public class LocationManagerService extends ILocationManager.Stub { } @Override - public void removeTestProvider(String provider) { - checkMockPermissionsSafe(); + public void removeTestProvider(String provider, String opPackageName) { + if (!canCallerAccessMockLocation(opPackageName)) { + return; + } + synchronized (mLock) { // These methods can't be called after removing the test provider, so first make sure // we don't leave anything dangling. - clearTestProviderEnabled(provider); - clearTestProviderLocation(provider); - clearTestProviderStatus(provider); + clearTestProviderEnabled(provider, opPackageName); + clearTestProviderLocation(provider, opPackageName); + clearTestProviderStatus(provider, opPackageName); MockProvider mockProvider = mMockProviders.remove(provider); if (mockProvider == null) { @@ -2432,8 +2429,11 @@ public class LocationManagerService extends ILocationManager.Stub { } @Override - public void setTestProviderLocation(String provider, Location loc) { - checkMockPermissionsSafe(); + public void setTestProviderLocation(String provider, Location loc, String opPackageName) { + if (!canCallerAccessMockLocation(opPackageName)) { + return; + } + synchronized (mLock) { MockProvider mockProvider = mMockProviders.get(provider); if (mockProvider == null) { @@ -2447,8 +2447,11 @@ public class LocationManagerService extends ILocationManager.Stub { } @Override - public void clearTestProviderLocation(String provider) { - checkMockPermissionsSafe(); + public void clearTestProviderLocation(String provider, String opPackageName) { + if (!canCallerAccessMockLocation(opPackageName)) { + return; + } + synchronized (mLock) { MockProvider mockProvider = mMockProviders.get(provider); if (mockProvider == null) { @@ -2459,8 +2462,11 @@ public class LocationManagerService extends ILocationManager.Stub { } @Override - public void setTestProviderEnabled(String provider, boolean enabled) { - checkMockPermissionsSafe(); + public void setTestProviderEnabled(String provider, boolean enabled, String opPackageName) { + if (!canCallerAccessMockLocation(opPackageName)) { + return; + } + synchronized (mLock) { MockProvider mockProvider = mMockProviders.get(provider); if (mockProvider == null) { @@ -2482,8 +2488,11 @@ public class LocationManagerService extends ILocationManager.Stub { } @Override - public void clearTestProviderEnabled(String provider) { - checkMockPermissionsSafe(); + public void clearTestProviderEnabled(String provider, String opPackageName) { + if (!canCallerAccessMockLocation(opPackageName)) { + return; + } + synchronized (mLock) { MockProvider mockProvider = mMockProviders.get(provider); if (mockProvider == null) { @@ -2498,8 +2507,12 @@ public class LocationManagerService extends ILocationManager.Stub { } @Override - public void setTestProviderStatus(String provider, int status, Bundle extras, long updateTime) { - checkMockPermissionsSafe(); + public void setTestProviderStatus(String provider, int status, Bundle extras, long updateTime, + String opPackageName) { + if (!canCallerAccessMockLocation(opPackageName)) { + return; + } + synchronized (mLock) { MockProvider mockProvider = mMockProviders.get(provider); if (mockProvider == null) { @@ -2510,8 +2523,11 @@ public class LocationManagerService extends ILocationManager.Stub { } @Override - public void clearTestProviderStatus(String provider) { - checkMockPermissionsSafe(); + public void clearTestProviderStatus(String provider, String opPackageName) { + if (!canCallerAccessMockLocation(opPackageName)) { + return; + } + synchronized (mLock) { MockProvider mockProvider = mMockProviders.get(provider); if (mockProvider == null) {