Loading api/current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -3164,6 +3164,7 @@ package android.app { field public static final int OP_COARSE_LOCATION = 0; // 0x0 field public static final int OP_FINE_LOCATION = 1; // 0x1 field public static final int OP_GPS = 2; // 0x2 field public static final int OP_MONITOR_HIGH_POWER_LOCATION = 42; // 0x2a field public static final int OP_MONITOR_LOCATION = 41; // 0x29 field public static final int OP_NONE = -1; // 0xffffffff } core/java/android/app/AppOpsManager.java +8 −2 Original line number Diff line number Diff line Loading @@ -67,6 +67,7 @@ public class AppOpsManager { // - increment _NUM_OP // - add rows to sOpToSwitch, sOpNames, sOpPerms // - add descriptive strings to Settings/res/values/arrays.xml // - add the op to the appropriate template in AppOpsState.OpsTemplate (settings app) /** No operation specified. */ public static final int OP_NONE = -1; Loading Loading @@ -154,15 +155,17 @@ public class AppOpsManager { public static final int OP_WAKE_LOCK = 40; /** Continually monitoring location data. */ public static final int OP_MONITOR_LOCATION = 41; /** Continually monitoring location data with a relatively high power request. */ public static final int OP_MONITOR_HIGH_POWER_LOCATION = 42; /** @hide */ public static final int _NUM_OP = 42; public static final int _NUM_OP = 43; /** * This maps each operation to the operation that serves as the * switch to determine whether it is allowed. Generally this is * a 1:1 mapping, but for some things (like location) that have * multiple low-level operations being tracked that should be * presented to hte user as one switch then this can be used to * presented to the user as one switch then this can be used to * make them all controlled by the same single operation. */ private static int[] sOpToSwitch = new int[] { Loading Loading @@ -208,6 +211,7 @@ public class AppOpsManager { OP_AUDIO_BLUETOOTH_VOLUME, OP_WAKE_LOCK, OP_COARSE_LOCATION, OP_COARSE_LOCATION, }; /** Loading Loading @@ -257,6 +261,7 @@ public class AppOpsManager { "AUDIO_BLUETOOTH_VOLUME", "WAKE_LOCK", "MONITOR_LOCATION", "MONITOR_HIGH_POWER_LOCATION", }; /** Loading Loading @@ -306,6 +311,7 @@ public class AppOpsManager { null, // no permission for changing bluetooth volume android.Manifest.permission.WAKE_LOCK, null, // no permission for generic location monitoring null, // no permission for high power location monitoring }; /** Loading services/java/com/android/server/LocationManagerService.java +47 −8 Original line number Diff line number Diff line Loading @@ -117,6 +117,9 @@ public class LocationManagerService extends ILocationManager.Stub { 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 Loading Loading @@ -463,7 +466,10 @@ public class LocationManagerService extends ILocationManager.Stub { 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; Loading Loading @@ -526,18 +532,48 @@ public class LocationManagerService extends ILocationManager.Stub { } public void updateMonitoring(boolean allow) { if (!mOpMonitoring) { if (allow) { mOpMonitoring = mAppOps.startOpNoThrow(AppOpsManager.OP_MONITOR_LOCATION, mUid, mPackageName) == AppOpsManager.MODE_ALLOWED; // 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 (!allow || mAppOps.checkOpNoThrow(AppOpsManager.OP_MONITOR_LOCATION, mUid, mPackageName) != AppOpsManager.MODE_ALLOWED) { mAppOps.finishOp(AppOpsManager.OP_MONITOR_LOCATION, mUid, mPackageName); mOpMonitoring = false; if (!allowMonitoring || mAppOps.checkOpNoThrow(op, mUid, mPackageName) != AppOpsManager.MODE_ALLOWED) { mAppOps.finishOp(op, mUid, mPackageName); return false; } } return currentlyMonitoring; } public boolean isListener() { Loading Loading @@ -1383,6 +1419,9 @@ public class LocationManagerService extends ILocationManager.Stub { // 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 Loading Loading
api/current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -3164,6 +3164,7 @@ package android.app { field public static final int OP_COARSE_LOCATION = 0; // 0x0 field public static final int OP_FINE_LOCATION = 1; // 0x1 field public static final int OP_GPS = 2; // 0x2 field public static final int OP_MONITOR_HIGH_POWER_LOCATION = 42; // 0x2a field public static final int OP_MONITOR_LOCATION = 41; // 0x29 field public static final int OP_NONE = -1; // 0xffffffff }
core/java/android/app/AppOpsManager.java +8 −2 Original line number Diff line number Diff line Loading @@ -67,6 +67,7 @@ public class AppOpsManager { // - increment _NUM_OP // - add rows to sOpToSwitch, sOpNames, sOpPerms // - add descriptive strings to Settings/res/values/arrays.xml // - add the op to the appropriate template in AppOpsState.OpsTemplate (settings app) /** No operation specified. */ public static final int OP_NONE = -1; Loading Loading @@ -154,15 +155,17 @@ public class AppOpsManager { public static final int OP_WAKE_LOCK = 40; /** Continually monitoring location data. */ public static final int OP_MONITOR_LOCATION = 41; /** Continually monitoring location data with a relatively high power request. */ public static final int OP_MONITOR_HIGH_POWER_LOCATION = 42; /** @hide */ public static final int _NUM_OP = 42; public static final int _NUM_OP = 43; /** * This maps each operation to the operation that serves as the * switch to determine whether it is allowed. Generally this is * a 1:1 mapping, but for some things (like location) that have * multiple low-level operations being tracked that should be * presented to hte user as one switch then this can be used to * presented to the user as one switch then this can be used to * make them all controlled by the same single operation. */ private static int[] sOpToSwitch = new int[] { Loading Loading @@ -208,6 +211,7 @@ public class AppOpsManager { OP_AUDIO_BLUETOOTH_VOLUME, OP_WAKE_LOCK, OP_COARSE_LOCATION, OP_COARSE_LOCATION, }; /** Loading Loading @@ -257,6 +261,7 @@ public class AppOpsManager { "AUDIO_BLUETOOTH_VOLUME", "WAKE_LOCK", "MONITOR_LOCATION", "MONITOR_HIGH_POWER_LOCATION", }; /** Loading Loading @@ -306,6 +311,7 @@ public class AppOpsManager { null, // no permission for changing bluetooth volume android.Manifest.permission.WAKE_LOCK, null, // no permission for generic location monitoring null, // no permission for high power location monitoring }; /** Loading
services/java/com/android/server/LocationManagerService.java +47 −8 Original line number Diff line number Diff line Loading @@ -117,6 +117,9 @@ public class LocationManagerService extends ILocationManager.Stub { 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 Loading Loading @@ -463,7 +466,10 @@ public class LocationManagerService extends ILocationManager.Stub { 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; Loading Loading @@ -526,18 +532,48 @@ public class LocationManagerService extends ILocationManager.Stub { } public void updateMonitoring(boolean allow) { if (!mOpMonitoring) { if (allow) { mOpMonitoring = mAppOps.startOpNoThrow(AppOpsManager.OP_MONITOR_LOCATION, mUid, mPackageName) == AppOpsManager.MODE_ALLOWED; // 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 (!allow || mAppOps.checkOpNoThrow(AppOpsManager.OP_MONITOR_LOCATION, mUid, mPackageName) != AppOpsManager.MODE_ALLOWED) { mAppOps.finishOp(AppOpsManager.OP_MONITOR_LOCATION, mUid, mPackageName); mOpMonitoring = false; if (!allowMonitoring || mAppOps.checkOpNoThrow(op, mUid, mPackageName) != AppOpsManager.MODE_ALLOWED) { mAppOps.finishOp(op, mUid, mPackageName); return false; } } return currentlyMonitoring; } public boolean isListener() { Loading Loading @@ -1383,6 +1419,9 @@ public class LocationManagerService extends ILocationManager.Stub { // 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 Loading