Merge "Pull out Settings usage into utility"
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 39f039a..593faf1 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -43,7 +43,6 @@
import android.content.pm.ResolveInfo;
import android.content.pm.Signature;
import android.content.res.Resources;
-import android.database.ContentObserver;
import android.hardware.location.ActivityRecognitionHardware;
import android.location.Address;
import android.location.Criteria;
@@ -79,7 +78,6 @@
import android.provider.Settings;
import android.stats.location.LocationStatsEnums;
import android.text.TextUtils;
-import android.util.ArraySet;
import android.util.EventLog;
import android.util.Log;
import android.util.Slog;
@@ -99,12 +97,12 @@
import com.android.server.location.GeocoderProxy;
import com.android.server.location.GeofenceManager;
import com.android.server.location.GeofenceProxy;
-import com.android.server.location.LocationBlacklist;
import com.android.server.location.LocationFudger;
import com.android.server.location.LocationProviderProxy;
import com.android.server.location.LocationRequestStatistics;
import com.android.server.location.LocationRequestStatistics.PackageProviderKey;
import com.android.server.location.LocationRequestStatistics.PackageStatistics;
+import com.android.server.location.LocationSettingsStore;
import com.android.server.location.MockProvider;
import com.android.server.location.PassiveProvider;
import com.android.server.pm.permission.PermissionManagerServiceInternal;
@@ -183,13 +181,6 @@
private static final int FOREGROUND_IMPORTANCE_CUTOFF
= ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE;
- // 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
@@ -208,13 +199,14 @@
private ActivityManager mActivityManager;
private UserManager mUserManager;
+ private LocationSettingsStore mSettingsStore;
+
private GeofenceManager mGeofenceManager;
private LocationFudger mLocationFudger;
private GeocoderProxy mGeocodeProvider;
@Nullable
private GnssManagerService mGnssManagerService;
private PassiveProvider mPassiveProvider; // track passive provider for special cases
- private LocationBlacklist mBlacklist;
@GuardedBy("mLock")
private String mExtraLocationControllerPackage;
private boolean mExtraLocationControllerPackageEnabled;
@@ -245,10 +237,6 @@
private final HashMap<String, Location> mLastLocationCoarseInterval =
new HashMap<>();
- private final ArraySet<String> mBackgroundThrottlePackageWhitelist = new ArraySet<>();
-
- private final ArraySet<String> mIgnoreSettingsPackageWhitelist = new ArraySet<>();
-
// current active user on the device - other users are denied location data
private int mCurrentUserId = UserHandle.USER_SYSTEM;
private int[] mCurrentUserProfiles = new int[]{UserHandle.USER_SYSTEM};
@@ -287,16 +275,19 @@
@GuardedBy("mLock")
private void initializeLocked() {
- mAppOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
mPackageManager = mContext.getPackageManager();
- mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
- mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
- mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+ mAppOps = mContext.getSystemService(AppOpsManager.class);
+ mPowerManager = mContext.getSystemService(PowerManager.class);
+ mActivityManager = mContext.getSystemService(ActivityManager.class);
+ mUserManager = mContext.getSystemService(UserManager.class);
+
+ mSettingsStore = new LocationSettingsStore(mContext, mHandler);
mLocationFudger = new LocationFudger(mContext, mHandler);
- mBlacklist = new LocationBlacklist(mContext, mHandler);
- mBlacklist.init();
- mGeofenceManager = new GeofenceManager(mContext, mBlacklist);
+ mGeofenceManager = new GeofenceManager(mContext, mSettingsStore);
+
+ PowerManagerInternal localPowerManager =
+ LocalServices.getService(PowerManagerInternal.class);
// prepare providers
initializeProvidersLocked();
@@ -327,7 +318,6 @@
}
});
});
-
mActivityManager.addOnUidImportanceListener(
(uid, importance) -> {
// listener invoked on ui thread, move to our thread to reduce risk of blocking
@@ -339,63 +329,7 @@
});
},
FOREGROUND_IMPORTANCE_CUTOFF);
- mContext.getContentResolver().registerContentObserver(
- Settings.Secure.getUriFor(Settings.Secure.LOCATION_MODE), true,
- new ContentObserver(mHandler) {
- @Override
- public void onChange(boolean selfChange) {
- synchronized (mLock) {
- onLocationModeChangedLocked(true);
- }
- }
- }, UserHandle.USER_ALL);
- mContext.getContentResolver().registerContentObserver(
- Settings.Secure.getUriFor(Settings.Secure.LOCATION_PROVIDERS_ALLOWED), true,
- new ContentObserver(mHandler) {
- @Override
- public void onChange(boolean selfChange) {
- synchronized (mLock) {
- onProviderAllowedChangedLocked();
- }
- }
- }, UserHandle.USER_ALL);
- mContext.getContentResolver().registerContentObserver(
- Settings.Global.getUriFor(Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS),
- true,
- new ContentObserver(mHandler) {
- @Override
- public void onChange(boolean selfChange) {
- synchronized (mLock) {
- onBackgroundThrottleIntervalChangedLocked();
- }
- }
- }, UserHandle.USER_ALL);
- mContext.getContentResolver().registerContentObserver(
- Settings.Global.getUriFor(
- Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST),
- true,
- new ContentObserver(mHandler) {
- @Override
- public void onChange(boolean selfChange) {
- synchronized (mLock) {
- onBackgroundThrottleWhitelistChangedLocked();
- }
- }
- }, UserHandle.USER_ALL);
- mContext.getContentResolver().registerContentObserver(
- Settings.Global.getUriFor(
- Settings.Global.LOCATION_IGNORE_SETTINGS_PACKAGE_WHITELIST),
- true,
- new ContentObserver(mHandler) {
- @Override
- public void onChange(boolean selfChange) {
- synchronized (mLock) {
- onIgnoreSettingsWhitelistChangedLocked();
- }
- }
- }, UserHandle.USER_ALL);
- PowerManagerInternal localPowerManager =
- LocalServices.getService(PowerManagerInternal.class);
+
localPowerManager.registerLowPowerModeObserver(ServiceType.LOCATION,
state -> {
// listener invoked on ui thread, move to our thread to reduce risk of blocking
@@ -406,6 +340,33 @@
}
});
});
+ mBatterySaverMode = mPowerManager.getLocationPowerSaveMode();
+
+ mSettingsStore.addOnLocationEnabledChangedListener(() -> {
+ synchronized (mLock) {
+ onLocationModeChangedLocked(true);
+ }
+ });
+ mSettingsStore.addOnLocationProvidersAllowedChangedListener(() -> {
+ synchronized (mLock) {
+ onProviderAllowedChangedLocked();
+ }
+ });
+ mSettingsStore.addOnBackgroundThrottleIntervalChangedListener(() -> {
+ synchronized (mLock) {
+ onBackgroundThrottleIntervalChangedLocked();
+ }
+ });
+ mSettingsStore.addOnBackgroundThrottlePackageWhitelistChangedListener(() -> {
+ synchronized (mLock) {
+ onBackgroundThrottleWhitelistChangedLocked();
+ }
+ });
+ mSettingsStore.addOnIgnoreSettingsPackageWhitelistChangedListener(() -> {
+ synchronized (mLock) {
+ onIgnoreSettingsWhitelistChangedLocked();
+ }
+ });
new PackageMonitor() {
@Override
@@ -453,11 +414,6 @@
// provider initialization, and propagates changes until a steady state is reached
mCurrentUserId = UserHandle.USER_NULL;
onUserChangedLocked(ActivityManager.getCurrentUser());
-
- // initialize in-memory settings values
- onBackgroundThrottleWhitelistChangedLocked();
- onIgnoreSettingsWhitelistChangedLocked();
- onBatterySaverModeChangedLocked(mPowerManager.getLocationPowerSaveMode());
}
@GuardedBy("mLock")
@@ -479,6 +435,10 @@
@GuardedBy("mLock")
private void onBatterySaverModeChangedLocked(int newLocationMode) {
+ if (mBatterySaverMode == newLocationMode) {
+ return;
+ }
+
if (D) {
Slog.d(TAG,
"Battery Saver location mode changed from "
@@ -486,11 +446,8 @@
+ locationPowerSaveModeToString(newLocationMode));
}
- if (mBatterySaverMode == newLocationMode) {
- return;
- }
-
mBatterySaverMode = newLocationMode;
+
for (LocationProvider p : mProviders) {
applyRequirementsLocked(p);
}
@@ -588,17 +545,6 @@
@GuardedBy("mLock")
private void onBackgroundThrottleWhitelistChangedLocked() {
- mBackgroundThrottlePackageWhitelist.clear();
- mBackgroundThrottlePackageWhitelist.addAll(
- SystemConfig.getInstance().getAllowUnthrottledLocation());
-
- String setting = Settings.Global.getString(
- mContext.getContentResolver(),
- Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST);
- if (!TextUtils.isEmpty(setting)) {
- mBackgroundThrottlePackageWhitelist.addAll(Arrays.asList(setting.split(",")));
- }
-
for (LocationProvider p : mProviders) {
applyRequirementsLocked(p);
}
@@ -606,17 +552,6 @@
@GuardedBy("lock")
private void onIgnoreSettingsWhitelistChangedLocked() {
- mIgnoreSettingsPackageWhitelist.clear();
- mIgnoreSettingsPackageWhitelist.addAll(
- SystemConfig.getInstance().getAllowIgnoreLocationSettings());
-
- String setting = Settings.Global.getString(
- mContext.getContentResolver(),
- Settings.Global.LOCATION_IGNORE_SETTINGS_PACKAGE_WHITELIST);
- if (!TextUtils.isEmpty(setting)) {
- mIgnoreSettingsPackageWhitelist.addAll(Arrays.asList(setting.split(",")));
- }
-
for (LocationProvider p : mProviders) {
applyRequirementsLocked(p);
}
@@ -859,8 +794,6 @@
mCurrentUserId = userId;
onUserProfilesChangedLocked();
- mBlacklist.switchUser(userId);
-
// if the user changes, per-user settings may also have changed
onLocationModeChangedLocked(false);
onProviderAllowedChangedLocked();
@@ -1083,11 +1016,8 @@
@GuardedBy("mLock")
public void onAllowedChangedLocked() {
if (mIsManagedBySettings) {
- String allowedProviders = Settings.Secure.getStringForUser(
- mContext.getContentResolver(),
- Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
- mCurrentUserId);
- boolean allowed = TextUtils.delimitedStringContains(allowedProviders, ',', mName);
+ boolean allowed = mSettingsStore.getLocationProvidersAllowed(
+ mCurrentUserId).contains(mName);
if (allowed == mAllowed) {
return;
@@ -1909,10 +1839,7 @@
long identity = Binder.clearCallingIdentity();
try {
- backgroundThrottleInterval = Settings.Global.getLong(
- mContext.getContentResolver(),
- Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS,
- DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS);
+ backgroundThrottleInterval = mSettingsStore.getBackgroundThrottleIntervalMs();
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -2032,16 +1959,12 @@
@Override
public String[] getBackgroundThrottlingWhitelist() {
- synchronized (mLock) {
- return mBackgroundThrottlePackageWhitelist.toArray(new String[0]);
- }
+ return mSettingsStore.getBackgroundThrottlePackageWhitelist().toArray(new String[0]);
}
@Override
public String[] getIgnoreSettingsWhitelist() {
- synchronized (mLock) {
- return mIgnoreSettingsPackageWhitelist.toArray(new String[0]);
- }
+ return mSettingsStore.getIgnoreSettingsPackageWhitelist().toArray(new String[0]);
}
@GuardedBy("mLock")
@@ -2050,7 +1973,8 @@
return true;
}
- if (mBackgroundThrottlePackageWhitelist.contains(callerIdentity.mPackageName)) {
+ if (mSettingsStore.getBackgroundThrottlePackageWhitelist().contains(
+ callerIdentity.mPackageName)) {
return true;
}
@@ -2064,7 +1988,7 @@
return false;
}
- if (mIgnoreSettingsPackageWhitelist.contains(
+ if (mSettingsStore.getIgnoreSettingsPackageWhitelist().contains(
record.mReceiver.mCallerIdentity.mPackageName)) {
return true;
}
@@ -2472,7 +2396,8 @@
final int uid = Binder.getCallingUid();
final long identity = Binder.clearCallingIdentity();
try {
- if (mBlacklist.isBlacklisted(packageName)) {
+ if (mSettingsStore.isLocationPackageBlacklisted(UserHandle.getUserId(uid),
+ packageName)) {
if (D) {
Log.d(TAG, "not returning last loc for blacklisted app: "
+ packageName);
@@ -2513,10 +2438,7 @@
String op = resolutionLevelToOpStr(allowedResolutionLevel);
long locationAgeMs = TimeUnit.NANOSECONDS.toMillis(
SystemClock.elapsedRealtime() - location.getElapsedRealtimeNanos());
- if ((locationAgeMs > Settings.Global.getLong(
- mContext.getContentResolver(),
- Settings.Global.LOCATION_LAST_LOCATION_MAX_AGE_MILLIS,
- DEFAULT_LAST_LOCATION_MAX_AGE_MS))
+ if (locationAgeMs > mSettingsStore.getMaxLastLocationAgeMs()
&& (mAppOps.unsafeCheckOp(op, uid, packageName)
== AppOpsManager.MODE_FOREGROUND)) {
return null;
@@ -2575,11 +2497,7 @@
boolean foreground = LocationManagerServiceUtils.isImportanceForeground(
mActivityManager.getPackageImportance(packageName));
if (!foreground) {
- long backgroundThrottleIntervalMs = Settings.Global.getLong(
- mContext.getContentResolver(),
- Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS,
- DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS);
- if (locationAgeMs < backgroundThrottleIntervalMs) {
+ if (locationAgeMs < mSettingsStore.getBackgroundThrottleIntervalMs()) {
// not allowed to request new locations, so we can't return anything
return false;
}
@@ -2910,11 +2828,7 @@
long identity = Binder.clearCallingIdentity();
try {
- return Settings.Secure.getIntForUser(
- mContext.getContentResolver(),
- Settings.Secure.LOCATION_MODE,
- Settings.Secure.LOCATION_MODE_OFF,
- userId) != Settings.Secure.LOCATION_MODE_OFF;
+ return mSettingsStore.isLocationEnabled(userId);
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -3050,7 +2964,8 @@
continue;
}
- if (mBlacklist.isBlacklisted(receiver.mCallerIdentity.mPackageName)) {
+ if (mSettingsStore.isLocationPackageBlacklisted(receiverUserId,
+ receiver.mCallerIdentity.mPackageName)) {
if (D) {
Log.d(TAG, "skipping loc update for blacklisted app: " +
receiver.mCallerIdentity.mPackageName);
@@ -3392,33 +3307,11 @@
ipw.decreaseIndent();
}
- if (mBlacklist != null) {
- mBlacklist.dump(ipw);
- }
-
if (mExtraLocationControllerPackage != null) {
ipw.println("Location Controller Extra Package: " + mExtraLocationControllerPackage
+ (mExtraLocationControllerPackageEnabled ? " [enabled]" : "[disabled]"));
}
- if (!mBackgroundThrottlePackageWhitelist.isEmpty()) {
- ipw.println("Throttling Whitelisted Packages:");
- ipw.increaseIndent();
- for (String packageName : mBackgroundThrottlePackageWhitelist) {
- ipw.println(packageName);
- }
- ipw.decreaseIndent();
- }
-
- if (!mIgnoreSettingsPackageWhitelist.isEmpty()) {
- ipw.println("Bypass Whitelisted Packages:");
- ipw.increaseIndent();
- for (String packageName : mIgnoreSettingsPackageWhitelist) {
- ipw.println(packageName);
- }
- ipw.decreaseIndent();
- }
-
if (mLocationFudger != null) {
ipw.println("Location Fudger:");
ipw.increaseIndent();
@@ -3426,6 +3319,8 @@
ipw.decreaseIndent();
}
+ mSettingsStore.dump(fd, pw, args);
+
ipw.println("Location Providers:");
ipw.increaseIndent();
for (LocationProvider provider : mProviders) {
diff --git a/services/core/java/com/android/server/location/GeofenceManager.java b/services/core/java/com/android/server/location/GeofenceManager.java
index 17a2169..c970788 100644
--- a/services/core/java/com/android/server/location/GeofenceManager.java
+++ b/services/core/java/com/android/server/location/GeofenceManager.java
@@ -18,12 +18,11 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.app.PendingIntent;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
-import android.database.ContentObserver;
import android.location.Geofence;
import android.location.Location;
import android.location.LocationListener;
@@ -31,13 +30,14 @@
import android.location.LocationRequest;
import android.os.Bundle;
import android.os.Handler;
+import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
import android.os.SystemClock;
-import android.os.UserHandle;
-import android.provider.Settings;
+import android.util.Log;
import android.util.Slog;
+import com.android.server.FgThread;
import com.android.server.LocationManagerService;
import com.android.server.PendingIntentUtils;
@@ -48,7 +48,7 @@
public class GeofenceManager implements LocationListener, PendingIntent.OnFinished {
private static final String TAG = "GeofenceManager";
- private static final boolean D = LocationManagerService.D;
+ private static final boolean D = Log.isLoggable(TAG, Log.DEBUG);
private static final int MSG_UPDATE_FENCES = 1;
@@ -64,10 +64,6 @@
*/
private static final long MAX_AGE_NANOS = 5 * 60 * 1000000000L; // five minutes
- /**
- * The default value of most frequent update interval allowed.
- */
- private static final long DEFAULT_MIN_INTERVAL_MS = 30 * 60 * 1000; // 30 minutes
/**
* Least frequent update interval allowed.
@@ -75,11 +71,13 @@
private static final long MAX_INTERVAL_MS = 2 * 60 * 60 * 1000; // two hours
private final Context mContext;
+ private final GeofenceHandler mHandler;
+
private final LocationManager mLocationManager;
private final AppOpsManager mAppOps;
private final PowerManager.WakeLock mWakeLock;
- private final GeofenceHandler mHandler;
- private final LocationBlacklist mBlacklist;
+
+ private final LocationSettingsStore mSettingsStore;
private final Object mLock = new Object();
@@ -113,43 +111,17 @@
*/
private boolean mPendingUpdate;
- /**
- * The actual value of most frequent update interval allowed.
- */
- private long mEffectiveMinIntervalMs;
- private ContentResolver mResolver;
-
- public GeofenceManager(Context context, LocationBlacklist blacklist) {
+ public GeofenceManager(Context context, LocationSettingsStore settingsStore) {
mContext = context;
- mLocationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
- mAppOps = (AppOpsManager)mContext.getSystemService(Context.APP_OPS_SERVICE);
- PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
- mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
- mHandler = new GeofenceHandler();
- mBlacklist = blacklist;
- mResolver = mContext.getContentResolver();
- updateMinInterval();
- mResolver.registerContentObserver(
- Settings.Global.getUriFor(
- Settings.Global.LOCATION_BACKGROUND_THROTTLE_PROXIMITY_ALERT_INTERVAL_MS),
- true,
- new ContentObserver(mHandler) {
- @Override
- public void onChange(boolean selfChange) {
- synchronized (mLock) {
- updateMinInterval();
- }
- }
- }, UserHandle.USER_ALL);
- }
+ mHandler = new GeofenceHandler(FgThread.getHandler().getLooper());
- /**
- * Updates the minimal location request frequency.
- */
- private void updateMinInterval() {
- mEffectiveMinIntervalMs = Settings.Global.getLong(mResolver,
- Settings.Global.LOCATION_BACKGROUND_THROTTLE_PROXIMITY_ALERT_INTERVAL_MS,
- DEFAULT_MIN_INTERVAL_MS);
+ mLocationManager = mContext.getSystemService(LocationManager.class);
+ mAppOps = mContext.getSystemService(AppOpsManager.class);
+
+ mWakeLock = mContext.getSystemService(PowerManager.class).newWakeLock(
+ PowerManager.PARTIAL_WAKE_LOCK, TAG);
+
+ mSettingsStore = settingsStore;
}
public void addFence(LocationRequest request, Geofence geofence, PendingIntent intent,
@@ -294,7 +266,8 @@
double minFenceDistance = Double.MAX_VALUE;
boolean needUpdates = false;
for (GeofenceState state : mFences) {
- if (mBlacklist.isBlacklisted(state.mPackageName)) {
+ if (mSettingsStore.isLocationPackageBlacklisted(ActivityManager.getCurrentUser(),
+ state.mPackageName)) {
if (D) {
Slog.d(TAG, "skipping geofence processing for blacklisted app: "
+ state.mPackageName);
@@ -340,10 +313,11 @@
// Compute a location update interval based on the distance to the nearest fence.
long intervalMs;
if (location != null && Double.compare(minFenceDistance, Double.MAX_VALUE) != 0) {
- intervalMs = (long)Math.min(MAX_INTERVAL_MS, Math.max(mEffectiveMinIntervalMs,
+ intervalMs = (long) Math.min(MAX_INTERVAL_MS, Math.max(
+ mSettingsStore.getBackgroundThrottleProximityAlertIntervalMs(),
minFenceDistance * 1000 / MAX_SPEED_M_S));
} else {
- intervalMs = mEffectiveMinIntervalMs;
+ intervalMs = mSettingsStore.getBackgroundThrottleProximityAlertIntervalMs();
}
if (!mReceivingLocationUpdates || mLocationUpdateInterval != intervalMs) {
mReceivingLocationUpdates = true;
@@ -436,13 +410,16 @@
}
@Override
- public void onStatusChanged(String provider, int status, Bundle extras) { }
+ public void onStatusChanged(String provider, int status, Bundle extras) {
+ }
@Override
- public void onProviderEnabled(String provider) { }
+ public void onProviderEnabled(String provider) {
+ }
@Override
- public void onProviderDisabled(String provider) { }
+ public void onProviderDisabled(String provider) {
+ }
@Override
public void onSendFinished(PendingIntent pendingIntent, Intent intent, int resultCode,
@@ -457,17 +434,14 @@
}
private final class GeofenceHandler extends Handler {
- public GeofenceHandler() {
- super(true /*async*/);
+ private GeofenceHandler(Looper looper) {
+ super(looper);
}
@Override
public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_UPDATE_FENCES: {
- updateFences();
- break;
- }
+ if (msg.what == MSG_UPDATE_FENCES) {
+ updateFences();
}
}
}
diff --git a/services/core/java/com/android/server/location/LocationBlacklist.java b/services/core/java/com/android/server/location/LocationBlacklist.java
deleted file mode 100644
index 3f3f828..0000000
--- a/services/core/java/com/android/server/location/LocationBlacklist.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-package com.android.server.location;
-
-import android.content.Context;
-import android.database.ContentObserver;
-import android.os.Handler;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.util.Log;
-import android.util.Slog;
-
-import com.android.server.LocationManagerService;
-
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.Arrays;
-
-/**
- * Allows applications to be blacklisted from location updates at run-time.
- *
- * This is a silent blacklist. Applications can still call Location Manager
- * API's, but they just won't receive any locations.
- */
-public final class LocationBlacklist extends ContentObserver {
- private static final String TAG = "LocationBlacklist";
- private static final boolean D = LocationManagerService.D;
- private static final String BLACKLIST_CONFIG_NAME = "locationPackagePrefixBlacklist";
- private static final String WHITELIST_CONFIG_NAME = "locationPackagePrefixWhitelist";
-
- private final Context mContext;
- private final Object mLock = new Object();
-
- // all fields below synchronized on mLock
- private String[] mWhitelist = new String[0];
- private String[] mBlacklist = new String[0];
-
- private int mCurrentUserId = UserHandle.USER_SYSTEM;
-
- public LocationBlacklist(Context context, Handler handler) {
- super(handler);
- mContext = context;
- }
-
- public void init() {
- mContext.getContentResolver().registerContentObserver(Settings.Secure.getUriFor(
- BLACKLIST_CONFIG_NAME), false, this, UserHandle.USER_ALL);
-// mContext.getContentResolver().registerContentObserver(Settings.Secure.getUriFor(
-// WHITELIST_CONFIG_NAME), false, this, UserHandle.USER_ALL);
- reloadBlacklist();
- }
-
- private void reloadBlacklistLocked() {
- mWhitelist = getStringArrayLocked(WHITELIST_CONFIG_NAME);
- if (D) Slog.d(TAG, "whitelist: " + Arrays.toString(mWhitelist));
- mBlacklist = getStringArrayLocked(BLACKLIST_CONFIG_NAME);
- if (D) Slog.d(TAG, "blacklist: " + Arrays.toString(mBlacklist));
- }
-
- private void reloadBlacklist() {
- synchronized (mLock) {
- reloadBlacklistLocked();
- }
- }
-
- /**
- * Return true if in blacklist
- * (package name matches blacklist, and does not match whitelist)
- */
- public boolean isBlacklisted(String packageName) {
- synchronized (mLock) {
- for (String black : mBlacklist) {
- if (packageName.startsWith(black)) {
- if (inWhitelist(packageName)) {
- continue;
- } else {
- if (D) Log.d(TAG, "dropping location (blacklisted): "
- + packageName + " matches " + black);
- return true;
- }
- }
- }
- }
- return false;
- }
-
- /**
- * Return true if any of packages are in whitelist
- */
- private boolean inWhitelist(String pkg) {
- synchronized (mLock) {
- for (String white : mWhitelist) {
- if (pkg.startsWith(white)) return true;
- }
- }
- return false;
- }
-
- @Override
- public void onChange(boolean selfChange) {
- reloadBlacklist();
- }
-
- public void switchUser(int userId) {
- synchronized(mLock) {
- mCurrentUserId = userId;
- reloadBlacklistLocked();
- }
- }
-
- private String[] getStringArrayLocked(String key) {
- String flatString;
- synchronized(mLock) {
- flatString = Settings.Secure.getStringForUser(mContext.getContentResolver(), key,
- mCurrentUserId);
- }
- if (flatString == null) {
- return new String[0];
- }
- String[] splitStrings = flatString.split(",");
- ArrayList<String> result = new ArrayList<String>();
- for (String pkg : splitStrings) {
- pkg = pkg.trim();
- if (pkg.isEmpty()) {
- continue;
- }
- result.add(pkg);
- }
- return result.toArray(new String[result.size()]);
- }
-
- public void dump(PrintWriter pw) {
- pw.println("mWhitelist=" + Arrays.toString(mWhitelist) + " mBlacklist=" +
- Arrays.toString(mBlacklist));
- }
-}
diff --git a/services/core/java/com/android/server/location/LocationSettingsStore.java b/services/core/java/com/android/server/location/LocationSettingsStore.java
new file mode 100644
index 0000000..a4b6d97
--- /dev/null
+++ b/services/core/java/com/android/server/location/LocationSettingsStore.java
@@ -0,0 +1,461 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.location;
+
+import static android.provider.Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS;
+import static android.provider.Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST;
+import static android.provider.Settings.Global.LOCATION_BACKGROUND_THROTTLE_PROXIMITY_ALERT_INTERVAL_MS;
+import static android.provider.Settings.Global.LOCATION_IGNORE_SETTINGS_PACKAGE_WHITELIST;
+import static android.provider.Settings.Global.LOCATION_LAST_LOCATION_MAX_AGE_MILLIS;
+import static android.provider.Settings.Secure.LOCATION_MODE;
+import static android.provider.Settings.Secure.LOCATION_MODE_OFF;
+import static android.provider.Settings.Secure.LOCATION_PROVIDERS_ALLOWED;
+
+import android.app.ActivityManager;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.text.TextUtils;
+
+import com.android.internal.util.IndentingPrintWriter;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+/**
+ * Provides accessors and listeners for all location related settings.
+ */
+public class LocationSettingsStore {
+
+ private static final String LOCATION_PACKAGE_BLACKLIST = "locationPackagePrefixBlacklist";
+ private static final String LOCATION_PACKAGE_WHITELIST = "locationPackagePrefixWhitelist";
+
+ private static final long DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS = 30 * 60 * 1000;
+ private static final long DEFAULT_BACKGROUND_THROTTLE_PROXIMITY_ALERT_INTERVAL_MS =
+ 30 * 60 * 1000;
+ private static final long DEFAULT_MAX_LAST_LOCATION_AGE_MS = 20 * 60 * 1000;
+
+ private final Context mContext;
+
+ private final IntegerSecureSetting mLocationMode;
+ private final StringListCachedSecureSetting mLocationProvidersAllowed;
+ private final LongGlobalSetting mBackgroundThrottleIntervalMs;
+ private final StringListCachedSecureSetting mLocationPackageBlacklist;
+ private final StringListCachedSecureSetting mLocationPackageWhitelist;
+ private final StringListCachedGlobalSetting mBackgroundThrottlePackageWhitelist;
+ private final StringListCachedGlobalSetting mIgnoreSettingsPackageWhitelist;
+
+ public LocationSettingsStore(Context context, Handler handler) {
+ mContext = context;
+
+ mLocationMode = new IntegerSecureSetting(context, LOCATION_MODE, handler);
+ mLocationProvidersAllowed = new StringListCachedSecureSetting(context,
+ LOCATION_PROVIDERS_ALLOWED, handler);
+ mBackgroundThrottleIntervalMs = new LongGlobalSetting(context,
+ LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS, handler);
+ mLocationPackageBlacklist = new StringListCachedSecureSetting(context,
+ LOCATION_PACKAGE_BLACKLIST, handler);
+ mLocationPackageWhitelist = new StringListCachedSecureSetting(context,
+ LOCATION_PACKAGE_WHITELIST, handler);
+ mBackgroundThrottlePackageWhitelist = new StringListCachedGlobalSetting(context,
+ LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST, handler);
+ mIgnoreSettingsPackageWhitelist = new StringListCachedGlobalSetting(context,
+ LOCATION_IGNORE_SETTINGS_PACKAGE_WHITELIST, handler);
+ }
+
+ /**
+ * Retrieve if location is enabled or not.
+ */
+ public boolean isLocationEnabled(int userId) {
+ return mLocationMode.getValueForUser(LOCATION_MODE_OFF, userId) != LOCATION_MODE_OFF;
+ }
+
+ /**
+ * Add a listener for changes to the location enabled setting.
+ */
+ public void addOnLocationEnabledChangedListener(Runnable listener) {
+ mLocationMode.addListener(listener);
+ }
+
+ /**
+ * Remove a listener for changes to the location enabled setting.
+ */
+ public void removeOnLocationEnabledChangedListener(Runnable listener) {
+ mLocationMode.addListener(listener);
+ }
+
+ /**
+ * Retrieve the currently allowed location providers.
+ */
+ public List<String> getLocationProvidersAllowed(int userId) {
+ return mLocationProvidersAllowed.getValueForUser(userId);
+ }
+
+ /**
+ * Add a listener for changes to the currently allowed location providers.
+ */
+ public void addOnLocationProvidersAllowedChangedListener(Runnable runnable) {
+ mLocationProvidersAllowed.addListener(runnable);
+ }
+
+ /**
+ * Remove a listener for changes to the currently allowed location providers.
+ */
+ public void removeOnLocationProvidersAllowedChangedListener(Runnable runnable) {
+ mLocationProvidersAllowed.removeListener(runnable);
+ }
+
+ /**
+ * Retrieve the background throttle interval.
+ */
+ public long getBackgroundThrottleIntervalMs() {
+ return mBackgroundThrottleIntervalMs.getValue(DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS);
+ }
+
+ /**
+ * Add a listener for changes to the background throttle interval.
+ */
+ public void addOnBackgroundThrottleIntervalChangedListener(Runnable listener) {
+ mBackgroundThrottleIntervalMs.addListener(listener);
+ }
+
+ /**
+ * Remove a listener for changes to the background throttle interval.
+ */
+ public void removeOnBackgroundThrottleIntervalChangedListener(Runnable listener) {
+ mBackgroundThrottleIntervalMs.removeListener(listener);
+ }
+
+ /**
+ * Check if the given package is blacklisted for location access.
+ */
+ public boolean isLocationPackageBlacklisted(int userId, String packageName) {
+ List<String> locationPackageBlacklist = mLocationPackageBlacklist.getValueForUser(userId);
+ if (locationPackageBlacklist.isEmpty()) {
+ return false;
+ }
+
+ List<String> locationPackageWhitelist = mLocationPackageWhitelist.getValueForUser(userId);
+ for (String locationWhitelistPackage : locationPackageWhitelist) {
+ if (packageName.startsWith(locationWhitelistPackage)) {
+ return false;
+ }
+ }
+
+ for (String locationBlacklistPackage : locationPackageBlacklist) {
+ if (packageName.startsWith(locationBlacklistPackage)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Retrieve the background throttle package whitelist.
+ */
+ public List<String> getBackgroundThrottlePackageWhitelist() {
+ return mBackgroundThrottlePackageWhitelist.getValue();
+ }
+
+ /**
+ * Add a listener for changes to the background throttle package whitelist.
+ */
+ public void addOnBackgroundThrottlePackageWhitelistChangedListener(Runnable listener) {
+ mBackgroundThrottlePackageWhitelist.addListener(listener);
+ }
+
+ /**
+ * Remove a listener for changes to the background throttle package whitelist.
+ */
+ public void removeOnBackgroundThrottlePackageWhitelistChangedListener(Runnable listener) {
+ mBackgroundThrottlePackageWhitelist.removeListener(listener);
+ }
+
+ /**
+ * Retrieve the ignore settings package whitelist.
+ */
+ public List<String> getIgnoreSettingsPackageWhitelist() {
+ return mIgnoreSettingsPackageWhitelist.getValue();
+ }
+
+ /**
+ * Add a listener for changes to the ignore settings package whitelist.
+ */
+ public void addOnIgnoreSettingsPackageWhitelistChangedListener(Runnable listener) {
+ mIgnoreSettingsPackageWhitelist.addListener(listener);
+ }
+
+ /**
+ * Remove a listener for changes to the ignore settings package whitelist.
+ */
+ public void removeOnIgnoreSettingsPackageWhitelistChangedListener(Runnable listener) {
+ mIgnoreSettingsPackageWhitelist.removeListener(listener);
+ }
+
+ /**
+ * Retrieve the background throttling proximity alert interval.
+ */
+ public long getBackgroundThrottleProximityAlertIntervalMs() {
+ return Settings.Global.getLong(mContext.getContentResolver(),
+ LOCATION_BACKGROUND_THROTTLE_PROXIMITY_ALERT_INTERVAL_MS,
+ DEFAULT_BACKGROUND_THROTTLE_PROXIMITY_ALERT_INTERVAL_MS);
+ }
+
+ public long getMaxLastLocationAgeMs() {
+ return Settings.Global.getLong(
+ mContext.getContentResolver(),
+ LOCATION_LAST_LOCATION_MAX_AGE_MILLIS,
+ DEFAULT_MAX_LAST_LOCATION_AGE_MS);
+ }
+
+ /**
+ * Dump info for debugging.
+ */
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
+ int userId = ActivityManager.getCurrentUser();
+
+ ipw.println("--Location Settings--");
+ ipw.increaseIndent();
+
+ ipw.print("Location Enabled: ");
+ ipw.println(isLocationEnabled(userId));
+
+ ipw.print("Location Providers Allowed: ");
+ ipw.println(getLocationProvidersAllowed(userId));
+
+ List<String> locationPackageBlacklist = mLocationPackageBlacklist.getValueForUser(userId);
+ if (!locationPackageBlacklist.isEmpty()) {
+ ipw.println("Location Blacklisted Packages:");
+ ipw.increaseIndent();
+ for (String packageName : locationPackageBlacklist) {
+ ipw.println(packageName);
+ }
+ ipw.decreaseIndent();
+
+ List<String> locationPackageWhitelist = mLocationPackageWhitelist.getValueForUser(
+ userId);
+ if (!locationPackageWhitelist.isEmpty()) {
+ ipw.println("Location Whitelisted Packages:");
+ ipw.increaseIndent();
+ for (String packageName : locationPackageWhitelist) {
+ ipw.println(packageName);
+ }
+ ipw.decreaseIndent();
+ }
+ }
+
+ List<String> backgroundThrottlePackageWhitelist =
+ mBackgroundThrottlePackageWhitelist.getValue();
+ if (!backgroundThrottlePackageWhitelist.isEmpty()) {
+ ipw.println("Throttling Whitelisted Packages:");
+ ipw.increaseIndent();
+ for (String packageName : backgroundThrottlePackageWhitelist) {
+ ipw.println(packageName);
+ }
+ ipw.decreaseIndent();
+ }
+
+ List<String> ignoreSettingsPackageWhitelist = mIgnoreSettingsPackageWhitelist.getValue();
+ if (!ignoreSettingsPackageWhitelist.isEmpty()) {
+ ipw.println("Bypass Whitelisted Packages:");
+ ipw.increaseIndent();
+ for (String packageName : ignoreSettingsPackageWhitelist) {
+ ipw.println(packageName);
+ }
+ ipw.decreaseIndent();
+ }
+ }
+
+ private abstract static class ObservingSetting extends ContentObserver {
+
+ private final CopyOnWriteArrayList<Runnable> mListeners;
+
+ private ObservingSetting(Context context, String settingName, Handler handler) {
+ super(handler);
+ mListeners = new CopyOnWriteArrayList<>();
+
+ context.getContentResolver().registerContentObserver(
+ getUriFor(settingName), false, this, UserHandle.USER_ALL);
+ }
+
+ public void addListener(Runnable listener) {
+ mListeners.add(listener);
+ }
+
+ public void removeListener(Runnable listener) {
+ mListeners.remove(listener);
+ }
+
+ protected abstract Uri getUriFor(String settingName);
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri, int userId) {
+ for (Runnable listener : mListeners) {
+ listener.run();
+ }
+ }
+ }
+
+ private static class IntegerSecureSetting extends ObservingSetting {
+
+ private final Context mContext;
+ private final String mSettingName;
+
+ private IntegerSecureSetting(Context context, String settingName, Handler handler) {
+ super(context, settingName, handler);
+ mContext = context;
+ mSettingName = settingName;
+ }
+
+ public int getValueForUser(int defaultValue, int userId) {
+ return Settings.Secure.getIntForUser(mContext.getContentResolver(), mSettingName,
+ defaultValue, userId);
+ }
+
+ @Override
+ protected Uri getUriFor(String settingName) {
+ return Settings.Secure.getUriFor(settingName);
+ }
+ }
+
+ private static class StringListCachedSecureSetting extends ObservingSetting {
+
+ private final Context mContext;
+ private final String mSettingName;
+
+ private int mCachedUserId = UserHandle.USER_NULL;
+ private List<String> mCachedValue;
+
+ private StringListCachedSecureSetting(Context context, String settingName,
+ Handler handler) {
+ super(context, settingName, handler);
+ mContext = context;
+ mSettingName = settingName;
+ }
+
+ public synchronized List<String> getValueForUser(int userId) {
+ if (userId != mCachedUserId) {
+ String setting = Settings.Secure.getStringForUser(mContext.getContentResolver(),
+ mSettingName, userId);
+ if (TextUtils.isEmpty(setting)) {
+ mCachedValue = Collections.emptyList();
+ } else {
+ mCachedValue = Arrays.asList(setting.split(","));
+ }
+ mCachedUserId = userId;
+ }
+
+ return mCachedValue;
+ }
+
+ public synchronized void invalidateForUser(int userId) {
+ if (mCachedUserId == userId) {
+ mCachedUserId = UserHandle.USER_NULL;
+ mCachedValue = null;
+ }
+ }
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri, int userId) {
+ invalidateForUser(userId);
+ super.onChange(selfChange, uri, userId);
+ }
+
+ @Override
+ protected Uri getUriFor(String settingName) {
+ return Settings.Secure.getUriFor(settingName);
+ }
+ }
+
+ private static class LongGlobalSetting extends ObservingSetting {
+
+ private final Context mContext;
+ private final String mSettingName;
+
+ private LongGlobalSetting(Context context, String settingName, Handler handler) {
+ super(context, settingName, handler);
+ mContext = context;
+ mSettingName = settingName;
+ }
+
+ public long getValue(long defaultValue) {
+ return Settings.Global.getLong(mContext.getContentResolver(), mSettingName,
+ defaultValue);
+ }
+
+ @Override
+ protected Uri getUriFor(String settingName) {
+ return Settings.Global.getUriFor(settingName);
+ }
+ }
+
+ private static class StringListCachedGlobalSetting extends ObservingSetting {
+
+ private final Context mContext;
+ private final String mSettingName;
+
+ private boolean mValid;
+ private List<String> mCachedValue;
+
+ private StringListCachedGlobalSetting(Context context, String settingName,
+ Handler handler) {
+ super(context, settingName, handler);
+ mContext = context;
+ mSettingName = settingName;
+ }
+
+ public synchronized List<String> getValue() {
+ if (!mValid) {
+ String setting = Settings.Global.getString(mContext.getContentResolver(),
+ mSettingName);
+ if (TextUtils.isEmpty(setting)) {
+ mCachedValue = Collections.emptyList();
+ } else {
+ mCachedValue = Arrays.asList(setting.split(","));
+ }
+ mValid = true;
+ }
+
+ return mCachedValue;
+ }
+
+ public synchronized void invalidate() {
+ mValid = false;
+ mCachedValue = null;
+ }
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri, int userId) {
+ invalidate();
+ super.onChange(selfChange, uri, userId);
+ }
+
+ @Override
+ protected Uri getUriFor(String settingName) {
+ return Settings.Global.getUriFor(settingName);
+ }
+ }
+}