Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0b837450 authored by David Christie's avatar David Christie
Browse files

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
parent d8501485
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -3162,6 +3162,7 @@ package android.app {
    field public static final int OP_COARSE_LOCATION = 0; // 0x0
    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_FINE_LOCATION = 1; // 0x1
    field public static final int OP_GPS = 2; // 0x2
    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_MONITOR_LOCATION = 41; // 0x29
    field public static final int OP_NONE = -1; // 0xffffffff
    field public static final int OP_NONE = -1; // 0xffffffff
  }
  }
+8 −2
Original line number Original line Diff line number Diff line
@@ -67,6 +67,7 @@ public class AppOpsManager {
    //  - increment _NUM_OP
    //  - increment _NUM_OP
    //  - add rows to sOpToSwitch, sOpNames, sOpPerms
    //  - add rows to sOpToSwitch, sOpNames, sOpPerms
    //  - add descriptive strings to Settings/res/values/arrays.xml
    //  - add descriptive strings to Settings/res/values/arrays.xml
    //  - add the op to the appropriate template in AppOpsState.OpsTemplate (settings app)


    /** No operation specified. */
    /** No operation specified. */
    public static final int OP_NONE = -1;
    public static final int OP_NONE = -1;
@@ -154,15 +155,17 @@ public class AppOpsManager {
    public static final int OP_WAKE_LOCK = 40;
    public static final int OP_WAKE_LOCK = 40;
    /** Continually monitoring location data. */
    /** Continually monitoring location data. */
    public static final int OP_MONITOR_LOCATION = 41;
    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 */
    /** @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
     * This maps each operation to the operation that serves as the
     * switch to determine whether it is allowed.  Generally this is
     * switch to determine whether it is allowed.  Generally this is
     * a 1:1 mapping, but for some things (like location) that have
     * a 1:1 mapping, but for some things (like location) that have
     * multiple low-level operations being tracked that should be
     * 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.
     * make them all controlled by the same single operation.
     */
     */
    private static int[] sOpToSwitch = new int[] {
    private static int[] sOpToSwitch = new int[] {
@@ -208,6 +211,7 @@ public class AppOpsManager {
            OP_AUDIO_BLUETOOTH_VOLUME,
            OP_AUDIO_BLUETOOTH_VOLUME,
            OP_WAKE_LOCK,
            OP_WAKE_LOCK,
            OP_COARSE_LOCATION,
            OP_COARSE_LOCATION,
            OP_COARSE_LOCATION,
    };
    };


    /**
    /**
@@ -257,6 +261,7 @@ public class AppOpsManager {
            "AUDIO_BLUETOOTH_VOLUME",
            "AUDIO_BLUETOOTH_VOLUME",
            "WAKE_LOCK",
            "WAKE_LOCK",
            "MONITOR_LOCATION",
            "MONITOR_LOCATION",
            "MONITOR_HIGH_POWER_LOCATION",
    };
    };


    /**
    /**
@@ -306,6 +311,7 @@ public class AppOpsManager {
            null, // no permission for changing bluetooth volume
            null, // no permission for changing bluetooth volume
            android.Manifest.permission.WAKE_LOCK,
            android.Manifest.permission.WAKE_LOCK,
            null, // no permission for generic location monitoring
            null, // no permission for generic location monitoring
            null, // no permission for high power location monitoring
    };
    };


    /**
    /**
+47 −8
Original line number Original line Diff line number Diff line
@@ -117,6 +117,9 @@ public class LocationManagerService extends ILocationManager.Stub {


    private static final long NANOS_PER_MILLI = 1000000L;
    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
    // Location Providers may sometimes deliver location updates
    // slightly faster that requested - provide grace period so
    // slightly faster that requested - provide grace period so
    // we don't unnecessarily filter events that are otherwise on
    // we don't unnecessarily filter events that are otherwise on
@@ -463,7 +466,10 @@ public class LocationManagerService extends ILocationManager.Stub {


        final HashMap<String,UpdateRecord> mUpdateRecords = new HashMap<String,UpdateRecord>();
        final HashMap<String,UpdateRecord> mUpdateRecords = new HashMap<String,UpdateRecord>();


        // True if app ops has started monitoring this receiver for locations.
        boolean mOpMonitoring;
        boolean mOpMonitoring;
        // True if app ops has started monitoring this receiver for high power (gps) locations.
        boolean mOpHighPowerMonitoring;
        int mPendingBroadcasts;
        int mPendingBroadcasts;
        PowerManager.WakeLock mWakeLock;
        PowerManager.WakeLock mWakeLock;


@@ -526,18 +532,48 @@ public class LocationManagerService extends ILocationManager.Stub {
        }
        }


        public void updateMonitoring(boolean allow) {
        public void updateMonitoring(boolean allow) {
            if (!mOpMonitoring) {
            // First update monitoring of any location request (including high power).
                if (allow) {
            mOpMonitoring = updateMonitoring(allow, mOpMonitoring,
                    mOpMonitoring = mAppOps.startOpNoThrow(AppOpsManager.OP_MONITOR_LOCATION,
                    AppOpsManager.OP_MONITOR_LOCATION);
                            mUid, mPackageName) == AppOpsManager.MODE_ALLOWED;

            // 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 {
            } else {
                if (!allow || mAppOps.checkOpNoThrow(AppOpsManager.OP_MONITOR_LOCATION,
                if (!allowMonitoring || mAppOps.checkOpNoThrow(op, mUid, mPackageName)
                        mUid, mPackageName) != AppOpsManager.MODE_ALLOWED) {
                        != AppOpsManager.MODE_ALLOWED) {
                    mAppOps.finishOp(AppOpsManager.OP_MONITOR_LOCATION, mUid, mPackageName);
                    mAppOps.finishOp(op, mUid, mPackageName);
                    mOpMonitoring = false;
                    return false;
                }
                }
            }
            }

            return currentlyMonitoring;
        }
        }


        public boolean isListener() {
        public boolean isListener() {
@@ -1383,6 +1419,9 @@ public class LocationManagerService extends ILocationManager.Stub {
            // Notify the listener that updates are currently disabled
            // Notify the listener that updates are currently disabled
            receiver.callProviderEnabledLocked(name, false);
            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
    @Override