Access mock location is no longer a runtime permission - framework

The access mock location is no longer a runtime permission. It is a
signature protected one that apps cannot get but the fact they request
it means they want to inject location into the system. Now the user
gets to choose the current mock location app in developer options from
the apps that request the mock location permission. The access to mock
location is no longer guarded by the permisson but from a new app op
which is off by default and the settiings UI sets it to enabled only
for the currently selected mock location app.

bug:21078873

Change-Id: I19e3f9dc7c7de82eab46b30fec1abfbca54a0e59
This commit is contained in:
Svet Ganov
2015-05-13 10:40:31 -07:00
committed by Svetoslav
parent 90c66e3ded
commit f7e9cf4fb4
10 changed files with 118 additions and 101 deletions

View File

@@ -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";

View File

@@ -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";

View File

@@ -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
};

View File

@@ -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";
/**

View File

@@ -836,9 +836,7 @@
<!-- Allows an application to create mock location providers for testing. -->
<permission android:name="android.permission.ACCESS_MOCK_LOCATION"
android:label="@string/permlab_accessMockLocation"
android:description="@string/permdesc_accessMockLocation"
android:protectionLevel="normal" />
android:protectionLevel="signature" />
<!-- ======================================= -->
<!-- Permissions for accessing networks -->

View File

@@ -945,14 +945,6 @@
owners\' knowledge.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_accessMockLocation">mock location sources for testing</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_accessMockLocation">Create mock location sources for
testing or install a new location provider. This allows the app to
override the location and/or status returned by other location sources
such as GPS or location providers.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_accessLocationExtraCommands">access extra location provider commands</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->

View File

@@ -79,7 +79,7 @@ trainingnavtop=true
<h2 id="TurnOnMockMode">Turn On Mock Mode</h2>
<p>
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 <b>Enable mock locations</b>. To learn how to
enable mock locations on the device, see
<a href="{@docRoot}tools/device.html#setting-up">Setting up a Device for Development</a>.

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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) {