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

Commit dd070f2f authored by Wei Wang's avatar Wei Wang
Browse files

Handle tri-state location permission.

Use noteOp instead of checkOp as checkOp doesn't consider
background status.

Watch location permission changes caused by background status.

Restrict age of last location for foreground-only apps.

Bug: 80318398
Test: Manual
Change-Id: I3499d4150478b6f501966953f8e4a08169f3557c
parent 69e716dd
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -9031,6 +9031,14 @@ public final class Settings {
        public static final String LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST =
            "location_background_throttle_package_whitelist";
        /**
         * Maximum staleness allowed for last location when returned to clients with only foreground
         * location permissions.
         * @hide
         */
        public static final String LOCATION_LAST_LOCATION_MAX_AGE_MILLIS =
                "location_last_location_max_age_millis";
        /**
        * Whether TV will switch to MHL port when a mobile device is plugged in.
        * (0 = false, 1 = true)
+1 −0
Original line number Diff line number Diff line
@@ -272,6 +272,7 @@ public class SettingsBackupTest {
                    Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS,
                    Settings.Global.LOCATION_BACKGROUND_THROTTLE_PROXIMITY_ALERT_INTERVAL_MS,
                    Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST,
                    Settings.Global.LOCATION_LAST_LOCATION_MAX_AGE_MILLIS,
                    Settings.Global.LOCATION_GLOBAL_KILL_SWITCH,
                    Settings.Global.LOCATION_SETTINGS_LINK_TO_PERMISSIONS_ENABLED,
                    Settings.Global.LOCK_SOUND,
+45 −3
Original line number Diff line number Diff line
@@ -153,6 +153,10 @@ public class LocationManagerService extends ILocationManager.Stub {
    // default background throttling interval if not overriden in settings
    private static final long DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS = 30 * 60 * 1000;

    // Default value for maximum age of last location returned to applications with foreground-only
    // location permissions.
    private static final long DEFAULT_LAST_LOCATION_MAX_AGE_MS = 20 * 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
@@ -241,6 +245,9 @@ public class LocationManagerService extends ILocationManager.Stub {
    private int mCurrentUserId = UserHandle.USER_SYSTEM;
    private int[] mCurrentUserProfiles = new int[]{UserHandle.USER_SYSTEM};

    // Maximum age of last location returned to clients with foreground-only location permissions.
    private long mLastLocationMaxAgeMs;

    private GnssLocationProvider.GnssSystemInfoProvider mGnssSystemInfoProvider;

    private GnssLocationProvider.GnssMetricsProvider mGnssMetricsProvider;
@@ -308,7 +315,8 @@ public class LocationManagerService extends ILocationManager.Stub {
                    }
                }
            };
            mAppOps.startWatchingMode(AppOpsManager.OP_COARSE_LOCATION, null, callback);
            mAppOps.startWatchingMode(AppOpsManager.OP_COARSE_LOCATION, null,
                    AppOpsManager.WATCH_FOREGROUND_CHANGES, callback);

            PackageManager.OnPermissionsChangedListener permissionListener
                    = new PackageManager.OnPermissionsChangedListener() {
@@ -341,6 +349,7 @@ public class LocationManagerService extends ILocationManager.Stub {
            updateUserProfiles(mCurrentUserId);

            updateBackgroundThrottlingWhitelistLocked();
            updateLastLocationMaxAgeLocked();

            // prepare providers
            loadProvidersLocked();
@@ -369,6 +378,18 @@ public class LocationManagerService extends ILocationManager.Stub {
                        }
                    }
                }, UserHandle.USER_ALL);
        mContext.getContentResolver().registerContentObserver(
                Settings.Global.getUriFor(Settings.Global.LOCATION_LAST_LOCATION_MAX_AGE_MILLIS),
                true,
                new ContentObserver(mLocationHandler) {
                    @Override
                    public void onChange(boolean selfChange) {
                        synchronized (mLock) {
                            updateLastLocationMaxAgeLocked();
                        }
                    }
                }
        );
        mContext.getContentResolver().registerContentObserver(
                Settings.Global.getUriFor(
                        Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST),
@@ -382,6 +403,7 @@ public class LocationManagerService extends ILocationManager.Stub {
                        }
                    }
                }, UserHandle.USER_ALL);

        mPackageMonitor.register(mContext, mLocationHandler.getLooper(), true);

        // listen for user change
@@ -841,6 +863,7 @@ public class LocationManagerService extends ILocationManager.Stub {
            for (String p : mUpdateRecords.keySet()) {
                s.append(" ").append(mUpdateRecords.get(p).toString());
            }
            s.append(" monitoring location: ").append(mOpMonitoring);
            s.append("]");
            return s.toString();
        }
@@ -913,7 +936,7 @@ public class LocationManagerService extends ILocationManager.Stub {
                }
            } else {
                if (!allowMonitoring
                        || mAppOps.checkOpNoThrow(op, mIdentity.mUid, mIdentity.mPackageName)
                        || mAppOps.noteOpNoThrow(op, mIdentity.mUid, mIdentity.mPackageName)
                        != AppOpsManager.MODE_ALLOWED) {
                    mAppOps.finishOp(op, mIdentity.mUid, mIdentity.mPackageName);
                    return false;
@@ -1541,7 +1564,7 @@ public class LocationManagerService extends ILocationManager.Stub {
    boolean checkLocationAccess(int pid, int uid, String packageName, int allowedResolutionLevel) {
        int op = resolutionLevelToOp(allowedResolutionLevel);
        if (op >= 0) {
            if (mAppOps.checkOp(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) {
            if (mAppOps.noteOp(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) {
                return false;
            }
        }
@@ -1857,6 +1880,14 @@ public class LocationManagerService extends ILocationManager.Stub {
                Arrays.asList(setting.split(",")));
    }

    private void updateLastLocationMaxAgeLocked() {
        mLastLocationMaxAgeMs =
                Settings.Global.getLong(
                        mContext.getContentResolver(),
                        Settings.Global.LOCATION_LAST_LOCATION_MAX_AGE_MILLIS,
                        DEFAULT_LAST_LOCATION_MAX_AGE_MS);
    }

    private boolean isThrottlingExemptLocked(Identity identity) {
        if (identity.mUid == Process.SYSTEM_UID) {
            return true;
@@ -2262,6 +2293,17 @@ public class LocationManagerService extends ILocationManager.Stub {
                if (location == null) {
                    return null;
                }

                // Don't return stale location to apps with foreground-only location permission.
                String op = getResolutionPermission(allowedResolutionLevel);
                long locationAgeMs = SystemClock.elapsedRealtime() -
                        location.getElapsedRealtimeNanos() / NANOS_PER_MILLI;
                if ((locationAgeMs > mLastLocationMaxAgeMs)
                        && (mAppOps.unsafeCheckOp(op, uid, packageName)
                            == AppOpsManager.MODE_FOREGROUND)) {
                    return null;
                }

                if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
                    Location noGPSLocation = location.getExtraLocation(
                            Location.EXTRA_NO_GPS_LOCATION);