Add new app op to monitor high power location requests.
This is a new op parallel to the existing OP_MONITOR_LOCATION
but only tracks those requests deemed to be above a
power threshold.
Change-Id: I76fe4d9d2e550293b9da6d5cf902a5b4dd499f0f
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index dfaafb8..7f056c2 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -117,6 +117,9 @@
private static final long NANOS_PER_MILLI = 1000000L;
+ // The maximum interval a location request can have and still be considered "high power".
+ private static final long HIGH_POWER_INTERVAL_MS = 5 * 60 * 1000;
+
// Location Providers may sometimes deliver location updates
// slightly faster that requested - provide grace period so
// we don't unnecessarily filter events that are otherwise on
@@ -463,7 +466,10 @@
final HashMap<String,UpdateRecord> mUpdateRecords = new HashMap<String,UpdateRecord>();
+ // True if app ops has started monitoring this receiver for locations.
boolean mOpMonitoring;
+ // True if app ops has started monitoring this receiver for high power (gps) locations.
+ boolean mOpHighPowerMonitoring;
int mPendingBroadcasts;
PowerManager.WakeLock mWakeLock;
@@ -526,18 +532,48 @@
}
public void updateMonitoring(boolean allow) {
- if (!mOpMonitoring) {
- if (allow) {
- mOpMonitoring = mAppOps.startOpNoThrow(AppOpsManager.OP_MONITOR_LOCATION,
- mUid, mPackageName) == AppOpsManager.MODE_ALLOWED;
- }
- } else {
- if (!allow || mAppOps.checkOpNoThrow(AppOpsManager.OP_MONITOR_LOCATION,
- mUid, mPackageName) != AppOpsManager.MODE_ALLOWED) {
- mAppOps.finishOp(AppOpsManager.OP_MONITOR_LOCATION, mUid, mPackageName);
- mOpMonitoring = false;
+ // First update monitoring of any location request (including high power).
+ mOpMonitoring = updateMonitoring(allow, mOpMonitoring,
+ AppOpsManager.OP_MONITOR_LOCATION);
+
+ // Now update monitoring of high power requests only.
+ // A high power request is any gps request with interval under a threshold.
+ boolean allowHighPower = allow;
+ if (allowHighPower) {
+ UpdateRecord gpsRecord = mUpdateRecords.get(LocationManager.GPS_PROVIDER);
+ if (gpsRecord == null
+ || gpsRecord.mRequest.getInterval() > HIGH_POWER_INTERVAL_MS) {
+ allowHighPower = false;
}
}
+ mOpHighPowerMonitoring = updateMonitoring(allowHighPower, mOpHighPowerMonitoring,
+ AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION);
+ }
+
+ /**
+ * Update AppOps monitoring for a single location request and op type.
+ *
+ * @param allowMonitoring True if monitoring is allowed for this request/op.
+ * @param currentlyMonitoring True if AppOps is currently monitoring this request/op.
+ * @param op AppOps code for the op to update.
+ * @return True if monitoring is on for this request/op after updating.
+ */
+ private boolean updateMonitoring(boolean allowMonitoring, boolean currentlyMonitoring,
+ int op) {
+ if (!currentlyMonitoring) {
+ if (allowMonitoring) {
+ return mAppOps.startOpNoThrow(op, mUid, mPackageName)
+ == AppOpsManager.MODE_ALLOWED;
+ }
+ } else {
+ if (!allowMonitoring || mAppOps.checkOpNoThrow(op, mUid, mPackageName)
+ != AppOpsManager.MODE_ALLOWED) {
+ mAppOps.finishOp(op, mUid, mPackageName);
+ return false;
+ }
+ }
+
+ return currentlyMonitoring;
}
public boolean isListener() {
@@ -1383,6 +1419,9 @@
// Notify the listener that updates are currently disabled
receiver.callProviderEnabledLocked(name, false);
}
+ // Update the monitoring here just in case multiple location requests were added to the
+ // same receiver (this request may be high power and the initial might not have been).
+ receiver.updateMonitoring(true);
}
@Override