App ops: you can now turn off operations.

Also add new ops for calendar and wi-fi scans, finish
implementing rejection of content provider calls, fix
issues with rejecting location calls, fix bug in the
new pm call to retrieve apps with permissions.

Change-Id: I29d9f8600bfbbf6561abf6d491907e2bbf6af417
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index b351fc2..f63719e 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -529,9 +529,6 @@
         }
 
         public boolean callLocationChangedLocked(Location location) {
-            if (!reportLocationAccessNoThrow(mUid, mPackageName, mAllowedResolutionLevel)) {
-                return true;
-            }
             if (mListener != null) {
                 try {
                     synchronized (this) {
@@ -802,14 +799,20 @@
         }
     }
 
-    boolean reportLocationAccessNoThrow(int uid, String packageName, int allowedResolutionLevel) {
-        int op;
+    public static int resolutionLevelToOp(int allowedResolutionLevel) {
         if (allowedResolutionLevel != RESOLUTION_LEVEL_NONE) {
             if (allowedResolutionLevel == RESOLUTION_LEVEL_COARSE) {
-                op = AppOpsManager.OP_COARSE_LOCATION;
+                return AppOpsManager.OP_COARSE_LOCATION;
             } else {
-                op = AppOpsManager.OP_FINE_LOCATION;
+                return AppOpsManager.OP_FINE_LOCATION;
             }
+        }
+        return -1;
+    }
+
+    boolean reportLocationAccessNoThrow(int uid, String packageName, int allowedResolutionLevel) {
+        int op = resolutionLevelToOp(allowedResolutionLevel);
+        if (op >= 0) {
             if (mAppOps.noteOpNoThrow(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) {
                 return false;
             }
@@ -818,13 +821,8 @@
     }
 
     boolean checkLocationAccess(int uid, String packageName, int allowedResolutionLevel) {
-        int op;
-        if (allowedResolutionLevel != RESOLUTION_LEVEL_NONE) {
-            if (allowedResolutionLevel == RESOLUTION_LEVEL_COARSE) {
-                op = AppOpsManager.OP_COARSE_LOCATION;
-            } else {
-                op = AppOpsManager.OP_FINE_LOCATION;
-            }
+        int op = resolutionLevelToOp(allowedResolutionLevel);
+        if (op >= 0) {
             if (mAppOps.checkOp(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) {
                 return false;
             }
@@ -1019,11 +1017,14 @@
         if (records != null) {
             for (UpdateRecord record : records) {
                 if (UserHandle.getUserId(record.mReceiver.mUid) == mCurrentUserId) {
-                    LocationRequest locationRequest = record.mRequest;
-                    providerRequest.locationRequests.add(locationRequest);
-                    if (locationRequest.getInterval() < providerRequest.interval) {
-                        providerRequest.reportLocation = true;
-                        providerRequest.interval = locationRequest.getInterval();
+                    if (checkLocationAccess(record.mReceiver.mUid, record.mReceiver.mPackageName,
+                            record.mReceiver.mAllowedResolutionLevel)) {
+                        LocationRequest locationRequest = record.mRequest;
+                        providerRequest.locationRequests.add(locationRequest);
+                        if (locationRequest.getInterval() < providerRequest.interval) {
+                            providerRequest.reportLocation = true;
+                            providerRequest.interval = locationRequest.getInterval();
+                        }
                     }
                 }
             }
@@ -1144,9 +1145,6 @@
      * and consistency requirements.
      *
      * @param request the LocationRequest from which to create a sanitized version
-     * @param shouldBeCoarse whether the sanitized version should be held to coarse resolution
-     * constraints
-     * @param fastestCoarseIntervalMS minimum interval allowed for coarse resolution
      * @return a version of request that meets the given resolution and consistency requirements
      * @hide
      */
@@ -1340,16 +1338,18 @@
         final int uid = Binder.getCallingUid();
         final long identity = Binder.clearCallingIdentity();
         try {
-            if (!reportLocationAccessNoThrow(uid, packageName, allowedResolutionLevel)) {
-                return null;
-            }
-            
             if (mBlacklist.isBlacklisted(packageName)) {
                 if (D) Log.d(TAG, "not returning last loc for blacklisted app: " +
                         packageName);
                 return null;
             }
 
+            if (!reportLocationAccessNoThrow(uid, packageName, allowedResolutionLevel)) {
+                if (D) Log.d(TAG, "not returning last loc for no op app: " +
+                        packageName);
+                return null;
+            }
+
             synchronized (mLock) {
                 // Figure out the provider. Either its explicitly request (deprecated API's),
                 // or use the fused provider
@@ -1402,7 +1402,8 @@
         }
         long identity = Binder.clearCallingIdentity();
         try {
-            mGeofenceManager.addFence(sanitizedRequest, geofence, intent, uid, packageName);
+            mGeofenceManager.addFence(sanitizedRequest, geofence, intent, allowedResolutionLevel,
+                    uid, packageName);
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
@@ -1703,6 +1704,13 @@
                 continue;
             }
 
+            if (!reportLocationAccessNoThrow(receiver.mUid, receiver.mPackageName,
+                    receiver.mAllowedResolutionLevel)) {
+                if (D) Log.d(TAG, "skipping loc update for no op app: " +
+                        receiver.mPackageName);
+                continue;
+            }
+
             Location notifyLocation = null;
             if (receiver.mAllowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
                 notifyLocation = coarseLocation;  // use coarse location