blob: f625452975c0bd31464b720fed907b512dfe8827 [file] [log] [blame]
Soonil Nagarkarb8466b72019-10-25 14:10:30 -07001/*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.location;
18
19import static android.provider.Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS;
20import static android.provider.Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST;
21import static android.provider.Settings.Global.LOCATION_BACKGROUND_THROTTLE_PROXIMITY_ALERT_INTERVAL_MS;
22import static android.provider.Settings.Global.LOCATION_IGNORE_SETTINGS_PACKAGE_WHITELIST;
23import static android.provider.Settings.Global.LOCATION_LAST_LOCATION_MAX_AGE_MILLIS;
24import static android.provider.Settings.Secure.LOCATION_MODE;
25import static android.provider.Settings.Secure.LOCATION_MODE_OFF;
Soonil Nagarkarb8466b72019-10-25 14:10:30 -070026
27import android.app.ActivityManager;
28import android.content.Context;
29import android.database.ContentObserver;
30import android.net.Uri;
31import android.os.Handler;
32import android.os.UserHandle;
33import android.provider.Settings;
34import android.text.TextUtils;
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -080035import android.util.ArraySet;
Soonil Nagarkarb8466b72019-10-25 14:10:30 -070036
Soonil Nagarkar3f128402019-12-12 08:31:27 -080037import com.android.internal.annotations.GuardedBy;
Soonil Nagarkarb8466b72019-10-25 14:10:30 -070038import com.android.internal.util.IndentingPrintWriter;
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -080039import com.android.internal.util.Preconditions;
40import com.android.server.SystemConfig;
Soonil Nagarkarb8466b72019-10-25 14:10:30 -070041
42import java.io.FileDescriptor;
43import java.io.PrintWriter;
44import java.util.Arrays;
45import java.util.Collections;
46import java.util.List;
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -080047import java.util.Set;
Soonil Nagarkarb8466b72019-10-25 14:10:30 -070048import java.util.concurrent.CopyOnWriteArrayList;
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -080049import java.util.function.Supplier;
Soonil Nagarkarb8466b72019-10-25 14:10:30 -070050
51/**
52 * Provides accessors and listeners for all location related settings.
53 */
54public class LocationSettingsStore {
55
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -080056 /**
57 * Listener for user-specific settings changes.
58 */
59 public interface UserSettingChangedListener {
60 /**
61 * Called when setting changes.
62 */
63 void onSettingChanged(int userId);
64 }
65
66 /**
67 * Listener for global settings changes.
68 */
69 public interface GlobalSettingChangedListener extends UserSettingChangedListener {
70 /**
71 * Called when setting changes.
72 */
73 void onSettingChanged();
74
75 @Override
76 default void onSettingChanged(int userId) {
77 onSettingChanged();
78 }
79 }
80
Soonil Nagarkarb8466b72019-10-25 14:10:30 -070081 private static final String LOCATION_PACKAGE_BLACKLIST = "locationPackagePrefixBlacklist";
82 private static final String LOCATION_PACKAGE_WHITELIST = "locationPackagePrefixWhitelist";
83
84 private static final long DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS = 30 * 60 * 1000;
85 private static final long DEFAULT_BACKGROUND_THROTTLE_PROXIMITY_ALERT_INTERVAL_MS =
86 30 * 60 * 1000;
87 private static final long DEFAULT_MAX_LAST_LOCATION_AGE_MS = 20 * 60 * 1000;
88
89 private final Context mContext;
90
91 private final IntegerSecureSetting mLocationMode;
Soonil Nagarkarb8466b72019-10-25 14:10:30 -070092 private final LongGlobalSetting mBackgroundThrottleIntervalMs;
93 private final StringListCachedSecureSetting mLocationPackageBlacklist;
94 private final StringListCachedSecureSetting mLocationPackageWhitelist;
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -080095 private final StringSetCachedGlobalSetting mBackgroundThrottlePackageWhitelist;
96 private final StringSetCachedGlobalSetting mIgnoreSettingsPackageWhitelist;
Soonil Nagarkarb8466b72019-10-25 14:10:30 -070097
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -080098 // TODO: get rid of handler
Soonil Nagarkarb8466b72019-10-25 14:10:30 -070099 public LocationSettingsStore(Context context, Handler handler) {
100 mContext = context;
101
102 mLocationMode = new IntegerSecureSetting(context, LOCATION_MODE, handler);
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700103 mBackgroundThrottleIntervalMs = new LongGlobalSetting(context,
104 LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS, handler);
105 mLocationPackageBlacklist = new StringListCachedSecureSetting(context,
106 LOCATION_PACKAGE_BLACKLIST, handler);
107 mLocationPackageWhitelist = new StringListCachedSecureSetting(context,
108 LOCATION_PACKAGE_WHITELIST, handler);
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800109 mBackgroundThrottlePackageWhitelist = new StringSetCachedGlobalSetting(context,
110 LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST,
111 () -> SystemConfig.getInstance().getAllowUnthrottledLocation(), handler);
112 mIgnoreSettingsPackageWhitelist = new StringSetCachedGlobalSetting(context,
113 LOCATION_IGNORE_SETTINGS_PACKAGE_WHITELIST,
114 () -> SystemConfig.getInstance().getAllowIgnoreLocationSettings(), handler);
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700115 }
116
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800117 /** Called when system is ready. */
118 public synchronized void onSystemReady() {
119 mLocationMode.register();
120 mBackgroundThrottleIntervalMs.register();
121 mLocationPackageBlacklist.register();
122 mLocationPackageWhitelist.register();
123 mBackgroundThrottlePackageWhitelist.register();
124 mIgnoreSettingsPackageWhitelist.register();
125 }
126
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700127 /**
128 * Retrieve if location is enabled or not.
129 */
130 public boolean isLocationEnabled(int userId) {
131 return mLocationMode.getValueForUser(LOCATION_MODE_OFF, userId) != LOCATION_MODE_OFF;
132 }
133
134 /**
135 * Add a listener for changes to the location enabled setting.
136 */
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800137 public void addOnLocationEnabledChangedListener(UserSettingChangedListener listener) {
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700138 mLocationMode.addListener(listener);
139 }
140
141 /**
142 * Remove a listener for changes to the location enabled setting.
143 */
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800144 public void removeOnLocationEnabledChangedListener(UserSettingChangedListener listener) {
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700145 mLocationMode.addListener(listener);
146 }
147
148 /**
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700149 * Retrieve the background throttle interval.
150 */
151 public long getBackgroundThrottleIntervalMs() {
152 return mBackgroundThrottleIntervalMs.getValue(DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS);
153 }
154
155 /**
156 * Add a listener for changes to the background throttle interval.
157 */
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800158 public void addOnBackgroundThrottleIntervalChangedListener(
159 GlobalSettingChangedListener listener) {
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700160 mBackgroundThrottleIntervalMs.addListener(listener);
161 }
162
163 /**
164 * Remove a listener for changes to the background throttle interval.
165 */
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800166 public void removeOnBackgroundThrottleIntervalChangedListener(
167 GlobalSettingChangedListener listener) {
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700168 mBackgroundThrottleIntervalMs.removeListener(listener);
169 }
170
171 /**
172 * Check if the given package is blacklisted for location access.
173 */
174 public boolean isLocationPackageBlacklisted(int userId, String packageName) {
175 List<String> locationPackageBlacklist = mLocationPackageBlacklist.getValueForUser(userId);
176 if (locationPackageBlacklist.isEmpty()) {
177 return false;
178 }
179
180 List<String> locationPackageWhitelist = mLocationPackageWhitelist.getValueForUser(userId);
181 for (String locationWhitelistPackage : locationPackageWhitelist) {
182 if (packageName.startsWith(locationWhitelistPackage)) {
183 return false;
184 }
185 }
186
187 for (String locationBlacklistPackage : locationPackageBlacklist) {
188 if (packageName.startsWith(locationBlacklistPackage)) {
189 return true;
190 }
191 }
192
193 return false;
194 }
195
196 /**
197 * Retrieve the background throttle package whitelist.
198 */
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800199 public Set<String> getBackgroundThrottlePackageWhitelist() {
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700200 return mBackgroundThrottlePackageWhitelist.getValue();
201 }
202
203 /**
204 * Add a listener for changes to the background throttle package whitelist.
205 */
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800206 public void addOnBackgroundThrottlePackageWhitelistChangedListener(
207 GlobalSettingChangedListener listener) {
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700208 mBackgroundThrottlePackageWhitelist.addListener(listener);
209 }
210
211 /**
212 * Remove a listener for changes to the background throttle package whitelist.
213 */
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800214 public void removeOnBackgroundThrottlePackageWhitelistChangedListener(
215 GlobalSettingChangedListener listener) {
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700216 mBackgroundThrottlePackageWhitelist.removeListener(listener);
217 }
218
219 /**
220 * Retrieve the ignore settings package whitelist.
221 */
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800222 public Set<String> getIgnoreSettingsPackageWhitelist() {
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700223 return mIgnoreSettingsPackageWhitelist.getValue();
224 }
225
226 /**
227 * Add a listener for changes to the ignore settings package whitelist.
228 */
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800229 public void addOnIgnoreSettingsPackageWhitelistChangedListener(
230 GlobalSettingChangedListener listener) {
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700231 mIgnoreSettingsPackageWhitelist.addListener(listener);
232 }
233
234 /**
235 * Remove a listener for changes to the ignore settings package whitelist.
236 */
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800237 public void removeOnIgnoreSettingsPackageWhitelistChangedListener(
238 GlobalSettingChangedListener listener) {
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700239 mIgnoreSettingsPackageWhitelist.removeListener(listener);
240 }
241
242 /**
243 * Retrieve the background throttling proximity alert interval.
244 */
245 public long getBackgroundThrottleProximityAlertIntervalMs() {
246 return Settings.Global.getLong(mContext.getContentResolver(),
247 LOCATION_BACKGROUND_THROTTLE_PROXIMITY_ALERT_INTERVAL_MS,
248 DEFAULT_BACKGROUND_THROTTLE_PROXIMITY_ALERT_INTERVAL_MS);
249 }
250
251 public long getMaxLastLocationAgeMs() {
252 return Settings.Global.getLong(
253 mContext.getContentResolver(),
254 LOCATION_LAST_LOCATION_MAX_AGE_MILLIS,
255 DEFAULT_MAX_LAST_LOCATION_AGE_MS);
256 }
257
258 /**
259 * Dump info for debugging.
260 */
261 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
262 IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
263 int userId = ActivityManager.getCurrentUser();
264
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700265 ipw.print("Location Enabled: ");
266 ipw.println(isLocationEnabled(userId));
267
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700268 List<String> locationPackageBlacklist = mLocationPackageBlacklist.getValueForUser(userId);
269 if (!locationPackageBlacklist.isEmpty()) {
270 ipw.println("Location Blacklisted Packages:");
271 ipw.increaseIndent();
272 for (String packageName : locationPackageBlacklist) {
273 ipw.println(packageName);
274 }
275 ipw.decreaseIndent();
276
277 List<String> locationPackageWhitelist = mLocationPackageWhitelist.getValueForUser(
278 userId);
279 if (!locationPackageWhitelist.isEmpty()) {
280 ipw.println("Location Whitelisted Packages:");
281 ipw.increaseIndent();
282 for (String packageName : locationPackageWhitelist) {
283 ipw.println(packageName);
284 }
285 ipw.decreaseIndent();
286 }
287 }
288
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800289 Set<String> backgroundThrottlePackageWhitelist =
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700290 mBackgroundThrottlePackageWhitelist.getValue();
291 if (!backgroundThrottlePackageWhitelist.isEmpty()) {
292 ipw.println("Throttling Whitelisted Packages:");
293 ipw.increaseIndent();
294 for (String packageName : backgroundThrottlePackageWhitelist) {
295 ipw.println(packageName);
296 }
297 ipw.decreaseIndent();
298 }
299
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800300 Set<String> ignoreSettingsPackageWhitelist = mIgnoreSettingsPackageWhitelist.getValue();
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700301 if (!ignoreSettingsPackageWhitelist.isEmpty()) {
302 ipw.println("Bypass Whitelisted Packages:");
303 ipw.increaseIndent();
304 for (String packageName : ignoreSettingsPackageWhitelist) {
305 ipw.println(packageName);
306 }
307 ipw.decreaseIndent();
308 }
309 }
310
311 private abstract static class ObservingSetting extends ContentObserver {
312
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800313 private final CopyOnWriteArrayList<UserSettingChangedListener> mListeners;
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800314 private boolean mRegistered;
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700315
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800316 private ObservingSetting(Handler handler) {
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700317 super(handler);
318 mListeners = new CopyOnWriteArrayList<>();
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800319 }
320
321 protected boolean isRegistered() {
322 return mRegistered;
323 }
324
325 protected void register(Context context, Uri uri) {
326 if (mRegistered) {
327 return;
328 }
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700329
330 context.getContentResolver().registerContentObserver(
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800331 uri, false, this, UserHandle.USER_ALL);
332 mRegistered = true;
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700333 }
334
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800335 public void addListener(UserSettingChangedListener listener) {
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700336 mListeners.add(listener);
337 }
338
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800339 public void removeListener(UserSettingChangedListener listener) {
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700340 mListeners.remove(listener);
341 }
342
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700343 @Override
344 public void onChange(boolean selfChange, Uri uri, int userId) {
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800345 for (UserSettingChangedListener listener : mListeners) {
346 listener.onSettingChanged(userId);
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700347 }
348 }
349 }
350
351 private static class IntegerSecureSetting extends ObservingSetting {
352
353 private final Context mContext;
354 private final String mSettingName;
355
356 private IntegerSecureSetting(Context context, String settingName, Handler handler) {
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800357 super(handler);
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700358 mContext = context;
359 mSettingName = settingName;
360 }
361
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800362 private void register() {
363 register(mContext, Settings.Secure.getUriFor(mSettingName));
364 }
365
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700366 public int getValueForUser(int defaultValue, int userId) {
367 return Settings.Secure.getIntForUser(mContext.getContentResolver(), mSettingName,
368 defaultValue, userId);
369 }
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700370 }
371
372 private static class StringListCachedSecureSetting extends ObservingSetting {
373
374 private final Context mContext;
375 private final String mSettingName;
376
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800377 @GuardedBy("this")
378 private int mCachedUserId;
379 @GuardedBy("this")
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700380 private List<String> mCachedValue;
381
382 private StringListCachedSecureSetting(Context context, String settingName,
383 Handler handler) {
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800384 super(handler);
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700385 mContext = context;
386 mSettingName = settingName;
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800387
388 mCachedUserId = UserHandle.USER_NULL;
389 }
390
391 public synchronized void register() {
392 register(mContext, Settings.Secure.getUriFor(mSettingName));
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700393 }
394
395 public synchronized List<String> getValueForUser(int userId) {
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800396 Preconditions.checkArgument(userId != UserHandle.USER_NULL);
397
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800398 List<String> value = mCachedValue;
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700399 if (userId != mCachedUserId) {
400 String setting = Settings.Secure.getStringForUser(mContext.getContentResolver(),
401 mSettingName, userId);
402 if (TextUtils.isEmpty(setting)) {
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800403 value = Collections.emptyList();
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700404 } else {
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800405 value = Arrays.asList(setting.split(","));
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700406 }
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800407
408 if (isRegistered()) {
409 mCachedUserId = userId;
410 mCachedValue = value;
411 }
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700412 }
413
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800414 return value;
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700415 }
416
417 public synchronized void invalidateForUser(int userId) {
418 if (mCachedUserId == userId) {
419 mCachedUserId = UserHandle.USER_NULL;
420 mCachedValue = null;
421 }
422 }
423
424 @Override
425 public void onChange(boolean selfChange, Uri uri, int userId) {
426 invalidateForUser(userId);
427 super.onChange(selfChange, uri, userId);
428 }
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700429 }
430
431 private static class LongGlobalSetting extends ObservingSetting {
432
433 private final Context mContext;
434 private final String mSettingName;
435
436 private LongGlobalSetting(Context context, String settingName, Handler handler) {
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800437 super(handler);
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700438 mContext = context;
439 mSettingName = settingName;
440 }
441
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800442 public void register() {
443 register(mContext, Settings.Global.getUriFor(mSettingName));
444 }
445
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700446 public long getValue(long defaultValue) {
447 return Settings.Global.getLong(mContext.getContentResolver(), mSettingName,
448 defaultValue);
449 }
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700450 }
451
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800452 private static class StringSetCachedGlobalSetting extends ObservingSetting {
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700453
454 private final Context mContext;
455 private final String mSettingName;
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800456 private final Supplier<ArraySet<String>> mBaseValuesSupplier;
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700457
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800458 @GuardedBy("this")
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700459 private boolean mValid;
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800460 @GuardedBy("this")
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800461 private ArraySet<String> mCachedValue;
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700462
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800463 private StringSetCachedGlobalSetting(Context context, String settingName,
464 Supplier<ArraySet<String>> baseValuesSupplier, Handler handler) {
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800465 super(handler);
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700466 mContext = context;
467 mSettingName = settingName;
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800468 mBaseValuesSupplier = baseValuesSupplier;
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800469
470 mValid = false;
471 }
472
473 public synchronized void register() {
474 register(mContext, Settings.Global.getUriFor(mSettingName));
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700475 }
476
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800477 public synchronized Set<String> getValue() {
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800478 ArraySet<String> value = mCachedValue;
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700479 if (!mValid) {
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800480 value = new ArraySet<>(mBaseValuesSupplier.get());
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700481 String setting = Settings.Global.getString(mContext.getContentResolver(),
482 mSettingName);
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800483 if (!TextUtils.isEmpty(setting)) {
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800484 value.addAll(Arrays.asList(setting.split(",")));
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700485 }
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800486
487 if (isRegistered()) {
488 mValid = true;
489 mCachedValue = value;
490 }
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700491 }
492
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800493 return value;
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700494 }
495
496 public synchronized void invalidate() {
497 mValid = false;
498 mCachedValue = null;
499 }
500
501 @Override
502 public void onChange(boolean selfChange, Uri uri, int userId) {
503 invalidate();
504 super.onChange(selfChange, uri, userId);
505 }
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700506 }
507}