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
diff --git a/api/current.txt b/api/current.txt
index d7b5982..1f31221 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -3883,6 +3883,7 @@
     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 @@
     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 832895c..eef35c4 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -3975,6 +3975,7 @@
     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 @@
     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 7104185..e728971 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -227,8 +227,10 @@
     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 @@
     /** @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 @@
             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 @@
             null,
             OPSTR_USE_FINGERPRINT,
             OPSTR_BODY_SENSORS,
-            OPSTR_READ_CELL_BROADCASTS
+            OPSTR_READ_CELL_BROADCASTS,
+            OPSTR_MOCK_LOCATION
     };
 
     /**
@@ -505,7 +512,8 @@
             "PROCESS_OUTGOING_CALLS",
             "USE_FINGERPRINT",
             "BODY_SENSORS",
-            "READ_CELL_BROADCASTS"
+            "READ_CELL_BROADCASTS",
+            "MOCK_LOCATION"
     };
 
     /**
@@ -570,7 +578,8 @@
             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 @@
             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 @@
             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 @@
             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 @@
             false,
             false,
             false,
+            false,
             false
     };
 
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index d3a5561..61b8bed 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -4133,7 +4133,10 @@
          * 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 c59c1c9..edff537 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -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 -->
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 5b564e1..359e3a6 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -946,14 +946,6 @@
 
 
     <!-- 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. -->
     <string name="permdesc_accessLocationExtraCommands">Allows the app to access
diff --git a/docs/html/training/location/location-testing.jd b/docs/html/training/location/location-testing.jd
index 5021fc0..8f73d51 100644
--- a/docs/html/training/location/location-testing.jd
+++ b/docs/html/training/location/location-testing.jd
@@ -79,7 +79,7 @@
 <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>.
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl
index af76175..a3ea896 100644
--- a/location/java/android/location/ILocationManager.aidl
+++ b/location/java/android/location/ILocationManager.aidl
@@ -77,14 +77,15 @@
     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 a3d04d9..b09f216 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -37,7 +37,6 @@
 
 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 @@
      *
      * @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 @@
         }
 
         try {
-            mService.addTestProvider(name, properties);
+            mService.addTestProvider(name, properties, mContext.getOpPackageName());
         } catch (RemoteException e) {
             Log.e(TAG, "RemoteException", e);
         }
@@ -1246,15 +1244,14 @@
      *
      * @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 @@
      * @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 @@
         }
 
         try {
-            mService.setTestProviderLocation(provider, loc);
+            mService.setTestProviderLocation(provider, loc, mContext.getOpPackageName());
         } catch (RemoteException e) {
             Log.e(TAG, "RemoteException", e);
         }
@@ -1303,15 +1299,14 @@
      *
      * @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 @@
      * @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 @@
      *
      * @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 @@
      * @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 @@
      *
      * @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 3879676..c76fc1c 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -2352,22 +2352,16 @@
 
     // 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 @@
     }
 
     @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 @@
     }
 
     @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 @@
     }
 
     @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 @@
     }
 
     @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 @@
     }
 
     @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 @@
     }
 
     @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 @@
     }
 
     @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) {