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