blob: 9163490fa777c8cb17bb0676efc18e4bf2f4d964 [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
Soonil Nagarkar8df02f42020-01-08 13:23:26 -080019import static android.location.LocationManager.FUSED_PROVIDER;
20import static android.location.LocationManager.PASSIVE_PROVIDER;
Soonil Nagarkarb8466b72019-10-25 14:10:30 -070021import static android.provider.Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS;
22import static android.provider.Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST;
23import static android.provider.Settings.Global.LOCATION_BACKGROUND_THROTTLE_PROXIMITY_ALERT_INTERVAL_MS;
24import static android.provider.Settings.Global.LOCATION_IGNORE_SETTINGS_PACKAGE_WHITELIST;
25import static android.provider.Settings.Global.LOCATION_LAST_LOCATION_MAX_AGE_MILLIS;
26import static android.provider.Settings.Secure.LOCATION_MODE;
27import static android.provider.Settings.Secure.LOCATION_MODE_OFF;
Soonil Nagarkarb8466b72019-10-25 14:10:30 -070028
29import android.app.ActivityManager;
30import android.content.Context;
31import android.database.ContentObserver;
32import android.net.Uri;
Soonil Nagarkar8df02f42020-01-08 13:23:26 -080033import android.os.Binder;
Soonil Nagarkarb8466b72019-10-25 14:10:30 -070034import android.os.Handler;
35import android.os.UserHandle;
36import android.provider.Settings;
37import android.text.TextUtils;
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -080038import android.util.ArraySet;
Soonil Nagarkarb8466b72019-10-25 14:10:30 -070039
Soonil Nagarkar3f128402019-12-12 08:31:27 -080040import com.android.internal.annotations.GuardedBy;
Soonil Nagarkarb8466b72019-10-25 14:10:30 -070041import com.android.internal.util.IndentingPrintWriter;
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -080042import com.android.internal.util.Preconditions;
43import com.android.server.SystemConfig;
Soonil Nagarkarb8466b72019-10-25 14:10:30 -070044
45import java.io.FileDescriptor;
46import java.io.PrintWriter;
47import java.util.Arrays;
48import java.util.Collections;
49import java.util.List;
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -080050import java.util.Set;
Soonil Nagarkarb8466b72019-10-25 14:10:30 -070051import java.util.concurrent.CopyOnWriteArrayList;
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -080052import java.util.function.Supplier;
Soonil Nagarkarb8466b72019-10-25 14:10:30 -070053
54/**
55 * Provides accessors and listeners for all location related settings.
56 */
Soonil Nagarkarb6375a42020-01-29 15:23:06 -080057public class SettingsHelper {
Soonil Nagarkarb8466b72019-10-25 14:10:30 -070058
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -080059 /**
60 * Listener for user-specific settings changes.
61 */
62 public interface UserSettingChangedListener {
63 /**
64 * Called when setting changes.
65 */
66 void onSettingChanged(int userId);
67 }
68
69 /**
70 * Listener for global settings changes.
71 */
72 public interface GlobalSettingChangedListener extends UserSettingChangedListener {
73 /**
74 * Called when setting changes.
75 */
76 void onSettingChanged();
77
78 @Override
79 default void onSettingChanged(int userId) {
80 onSettingChanged();
81 }
82 }
83
Soonil Nagarkarb8466b72019-10-25 14:10:30 -070084 private static final String LOCATION_PACKAGE_BLACKLIST = "locationPackagePrefixBlacklist";
85 private static final String LOCATION_PACKAGE_WHITELIST = "locationPackagePrefixWhitelist";
86
87 private static final long DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS = 30 * 60 * 1000;
88 private static final long DEFAULT_BACKGROUND_THROTTLE_PROXIMITY_ALERT_INTERVAL_MS =
89 30 * 60 * 1000;
90 private static final long DEFAULT_MAX_LAST_LOCATION_AGE_MS = 20 * 60 * 1000;
91
92 private final Context mContext;
93
94 private final IntegerSecureSetting mLocationMode;
Soonil Nagarkarb8466b72019-10-25 14:10:30 -070095 private final LongGlobalSetting mBackgroundThrottleIntervalMs;
96 private final StringListCachedSecureSetting mLocationPackageBlacklist;
97 private final StringListCachedSecureSetting mLocationPackageWhitelist;
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -080098 private final StringSetCachedGlobalSetting mBackgroundThrottlePackageWhitelist;
99 private final StringSetCachedGlobalSetting mIgnoreSettingsPackageWhitelist;
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700100
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800101 // TODO: get rid of handler
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800102 public SettingsHelper(Context context, Handler handler) {
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700103 mContext = context;
104
105 mLocationMode = new IntegerSecureSetting(context, LOCATION_MODE, handler);
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700106 mBackgroundThrottleIntervalMs = new LongGlobalSetting(context,
107 LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS, handler);
108 mLocationPackageBlacklist = new StringListCachedSecureSetting(context,
109 LOCATION_PACKAGE_BLACKLIST, handler);
110 mLocationPackageWhitelist = new StringListCachedSecureSetting(context,
111 LOCATION_PACKAGE_WHITELIST, handler);
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800112 mBackgroundThrottlePackageWhitelist = new StringSetCachedGlobalSetting(context,
113 LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST,
114 () -> SystemConfig.getInstance().getAllowUnthrottledLocation(), handler);
115 mIgnoreSettingsPackageWhitelist = new StringSetCachedGlobalSetting(context,
116 LOCATION_IGNORE_SETTINGS_PACKAGE_WHITELIST,
117 () -> SystemConfig.getInstance().getAllowIgnoreLocationSettings(), handler);
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700118 }
119
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800120 /** Called when system is ready. */
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800121 public void onSystemReady() {
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800122 mLocationMode.register();
123 mBackgroundThrottleIntervalMs.register();
124 mLocationPackageBlacklist.register();
125 mLocationPackageWhitelist.register();
126 mBackgroundThrottlePackageWhitelist.register();
127 mIgnoreSettingsPackageWhitelist.register();
128 }
129
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700130 /**
131 * Retrieve if location is enabled or not.
132 */
133 public boolean isLocationEnabled(int userId) {
134 return mLocationMode.getValueForUser(LOCATION_MODE_OFF, userId) != LOCATION_MODE_OFF;
135 }
136
137 /**
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800138 * Add a listener for changes to the location enabled setting. Callbacks occur on an unspecified
139 * thread.
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700140 */
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800141 public void addOnLocationEnabledChangedListener(UserSettingChangedListener listener) {
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700142 mLocationMode.addListener(listener);
143 }
144
145 /**
146 * Remove a listener for changes to the location enabled setting.
147 */
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800148 public void removeOnLocationEnabledChangedListener(UserSettingChangedListener listener) {
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700149 mLocationMode.addListener(listener);
150 }
151
152 /**
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700153 * Retrieve the background throttle interval.
154 */
155 public long getBackgroundThrottleIntervalMs() {
156 return mBackgroundThrottleIntervalMs.getValue(DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS);
157 }
158
159 /**
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800160 * Add a listener for changes to the background throttle interval. Callbacks occur on an
161 * unspecified thread.
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700162 */
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800163 public void addOnBackgroundThrottleIntervalChangedListener(
164 GlobalSettingChangedListener listener) {
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700165 mBackgroundThrottleIntervalMs.addListener(listener);
166 }
167
168 /**
169 * Remove a listener for changes to the background throttle interval.
170 */
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800171 public void removeOnBackgroundThrottleIntervalChangedListener(
172 GlobalSettingChangedListener listener) {
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700173 mBackgroundThrottleIntervalMs.removeListener(listener);
174 }
175
176 /**
177 * Check if the given package is blacklisted for location access.
178 */
179 public boolean isLocationPackageBlacklisted(int userId, String packageName) {
180 List<String> locationPackageBlacklist = mLocationPackageBlacklist.getValueForUser(userId);
181 if (locationPackageBlacklist.isEmpty()) {
182 return false;
183 }
184
185 List<String> locationPackageWhitelist = mLocationPackageWhitelist.getValueForUser(userId);
186 for (String locationWhitelistPackage : locationPackageWhitelist) {
187 if (packageName.startsWith(locationWhitelistPackage)) {
188 return false;
189 }
190 }
191
192 for (String locationBlacklistPackage : locationPackageBlacklist) {
193 if (packageName.startsWith(locationBlacklistPackage)) {
194 return true;
195 }
196 }
197
198 return false;
199 }
200
201 /**
202 * Retrieve the background throttle package whitelist.
203 */
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800204 public Set<String> getBackgroundThrottlePackageWhitelist() {
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700205 return mBackgroundThrottlePackageWhitelist.getValue();
206 }
207
208 /**
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800209 * Add a listener for changes to the background throttle package whitelist. Callbacks occur on
210 * an unspecified thread.
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700211 */
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800212 public void addOnBackgroundThrottlePackageWhitelistChangedListener(
213 GlobalSettingChangedListener listener) {
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700214 mBackgroundThrottlePackageWhitelist.addListener(listener);
215 }
216
217 /**
218 * Remove a listener for changes to the background throttle package whitelist.
219 */
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800220 public void removeOnBackgroundThrottlePackageWhitelistChangedListener(
221 GlobalSettingChangedListener listener) {
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700222 mBackgroundThrottlePackageWhitelist.removeListener(listener);
223 }
224
225 /**
226 * Retrieve the ignore settings package whitelist.
227 */
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800228 public Set<String> getIgnoreSettingsPackageWhitelist() {
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700229 return mIgnoreSettingsPackageWhitelist.getValue();
230 }
231
232 /**
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800233 * Add a listener for changes to the ignore settings package whitelist. Callbacks occur on an
234 * unspecified thread.
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700235 */
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800236 public void addOnIgnoreSettingsPackageWhitelistChangedListener(
237 GlobalSettingChangedListener listener) {
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700238 mIgnoreSettingsPackageWhitelist.addListener(listener);
239 }
240
241 /**
242 * Remove a listener for changes to the ignore settings package whitelist.
243 */
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800244 public void removeOnIgnoreSettingsPackageWhitelistChangedListener(
245 GlobalSettingChangedListener listener) {
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700246 mIgnoreSettingsPackageWhitelist.removeListener(listener);
247 }
248
249 /**
250 * Retrieve the background throttling proximity alert interval.
251 */
252 public long getBackgroundThrottleProximityAlertIntervalMs() {
253 return Settings.Global.getLong(mContext.getContentResolver(),
254 LOCATION_BACKGROUND_THROTTLE_PROXIMITY_ALERT_INTERVAL_MS,
255 DEFAULT_BACKGROUND_THROTTLE_PROXIMITY_ALERT_INTERVAL_MS);
256 }
257
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800258 /**
259 * Retrieve maximum age of the last location.
260 */
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700261 public long getMaxLastLocationAgeMs() {
262 return Settings.Global.getLong(
263 mContext.getContentResolver(),
264 LOCATION_LAST_LOCATION_MAX_AGE_MILLIS,
265 DEFAULT_MAX_LAST_LOCATION_AGE_MS);
266 }
267
268 /**
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800269 * Set a value for the deprecated LOCATION_PROVIDERS_ALLOWED setting. This is used purely for
270 * backwards compatibility for old clients, and may be removed in the future.
271 */
272 public void setLocationProviderAllowed(String provider, boolean enabled, int userId) {
273 // fused and passive provider never get public updates for legacy reasons
274 if (FUSED_PROVIDER.equals(provider) || PASSIVE_PROVIDER.equals(provider)) {
275 return;
276 }
277
278 long identity = Binder.clearCallingIdentity();
279 try {
280 // update LOCATION_PROVIDERS_ALLOWED for best effort backwards compatibility
281 Settings.Secure.putStringForUser(
282 mContext.getContentResolver(),
283 Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
284 (enabled ? "+" : "-") + provider,
285 userId);
286 } finally {
287 Binder.restoreCallingIdentity(identity);
288 }
289 }
290
291 /**
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700292 * Dump info for debugging.
293 */
294 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
295 IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
296 int userId = ActivityManager.getCurrentUser();
297
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700298 ipw.print("Location Enabled: ");
299 ipw.println(isLocationEnabled(userId));
300
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700301 List<String> locationPackageBlacklist = mLocationPackageBlacklist.getValueForUser(userId);
302 if (!locationPackageBlacklist.isEmpty()) {
303 ipw.println("Location Blacklisted Packages:");
304 ipw.increaseIndent();
305 for (String packageName : locationPackageBlacklist) {
306 ipw.println(packageName);
307 }
308 ipw.decreaseIndent();
309
310 List<String> locationPackageWhitelist = mLocationPackageWhitelist.getValueForUser(
311 userId);
312 if (!locationPackageWhitelist.isEmpty()) {
313 ipw.println("Location Whitelisted Packages:");
314 ipw.increaseIndent();
315 for (String packageName : locationPackageWhitelist) {
316 ipw.println(packageName);
317 }
318 ipw.decreaseIndent();
319 }
320 }
321
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800322 Set<String> backgroundThrottlePackageWhitelist =
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700323 mBackgroundThrottlePackageWhitelist.getValue();
324 if (!backgroundThrottlePackageWhitelist.isEmpty()) {
325 ipw.println("Throttling Whitelisted Packages:");
326 ipw.increaseIndent();
327 for (String packageName : backgroundThrottlePackageWhitelist) {
328 ipw.println(packageName);
329 }
330 ipw.decreaseIndent();
331 }
332
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800333 Set<String> ignoreSettingsPackageWhitelist = mIgnoreSettingsPackageWhitelist.getValue();
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700334 if (!ignoreSettingsPackageWhitelist.isEmpty()) {
335 ipw.println("Bypass Whitelisted Packages:");
336 ipw.increaseIndent();
337 for (String packageName : ignoreSettingsPackageWhitelist) {
338 ipw.println(packageName);
339 }
340 ipw.decreaseIndent();
341 }
342 }
343
344 private abstract static class ObservingSetting extends ContentObserver {
345
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800346 private final CopyOnWriteArrayList<UserSettingChangedListener> mListeners;
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800347
348 @GuardedBy("this")
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800349 private boolean mRegistered;
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700350
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800351 private ObservingSetting(Handler handler) {
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700352 super(handler);
353 mListeners = new CopyOnWriteArrayList<>();
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800354 }
355
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800356 protected synchronized boolean isRegistered() {
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800357 return mRegistered;
358 }
359
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800360 protected synchronized void register(Context context, Uri uri) {
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800361 if (mRegistered) {
362 return;
363 }
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700364
365 context.getContentResolver().registerContentObserver(
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800366 uri, false, this, UserHandle.USER_ALL);
367 mRegistered = true;
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700368 }
369
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800370 public void addListener(UserSettingChangedListener listener) {
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700371 mListeners.add(listener);
372 }
373
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800374 public void removeListener(UserSettingChangedListener listener) {
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700375 mListeners.remove(listener);
376 }
377
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700378 @Override
379 public void onChange(boolean selfChange, Uri uri, int userId) {
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800380 for (UserSettingChangedListener listener : mListeners) {
381 listener.onSettingChanged(userId);
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700382 }
383 }
384 }
385
386 private static class IntegerSecureSetting extends ObservingSetting {
387
388 private final Context mContext;
389 private final String mSettingName;
390
391 private IntegerSecureSetting(Context context, String settingName, Handler handler) {
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800392 super(handler);
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700393 mContext = context;
394 mSettingName = settingName;
395 }
396
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800397 private void register() {
398 register(mContext, Settings.Secure.getUriFor(mSettingName));
399 }
400
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700401 public int getValueForUser(int defaultValue, int userId) {
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800402 long identity = Binder.clearCallingIdentity();
403 try {
404 return Settings.Secure.getIntForUser(mContext.getContentResolver(), mSettingName,
405 defaultValue, userId);
406 } finally {
407 Binder.restoreCallingIdentity(identity);
408 }
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700409 }
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700410 }
411
412 private static class StringListCachedSecureSetting extends ObservingSetting {
413
414 private final Context mContext;
415 private final String mSettingName;
416
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800417 @GuardedBy("this")
418 private int mCachedUserId;
419 @GuardedBy("this")
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700420 private List<String> mCachedValue;
421
422 private StringListCachedSecureSetting(Context context, String settingName,
423 Handler handler) {
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800424 super(handler);
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700425 mContext = context;
426 mSettingName = settingName;
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800427
428 mCachedUserId = UserHandle.USER_NULL;
429 }
430
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800431 public void register() {
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800432 register(mContext, Settings.Secure.getUriFor(mSettingName));
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700433 }
434
435 public synchronized List<String> getValueForUser(int userId) {
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800436 Preconditions.checkArgument(userId != UserHandle.USER_NULL);
437
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800438 List<String> value = mCachedValue;
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700439 if (userId != mCachedUserId) {
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800440 long identity = Binder.clearCallingIdentity();
441 try {
442 String setting = Settings.Secure.getStringForUser(mContext.getContentResolver(),
443 mSettingName, userId);
444 if (TextUtils.isEmpty(setting)) {
445 value = Collections.emptyList();
446 } else {
447 value = Arrays.asList(setting.split(","));
448 }
449 } finally {
450 Binder.restoreCallingIdentity(identity);
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700451 }
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800452
453 if (isRegistered()) {
454 mCachedUserId = userId;
455 mCachedValue = value;
456 }
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700457 }
458
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800459 return value;
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700460 }
461
462 public synchronized void invalidateForUser(int userId) {
463 if (mCachedUserId == userId) {
464 mCachedUserId = UserHandle.USER_NULL;
465 mCachedValue = null;
466 }
467 }
468
469 @Override
470 public void onChange(boolean selfChange, Uri uri, int userId) {
471 invalidateForUser(userId);
472 super.onChange(selfChange, uri, userId);
473 }
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700474 }
475
476 private static class LongGlobalSetting extends ObservingSetting {
477
478 private final Context mContext;
479 private final String mSettingName;
480
481 private LongGlobalSetting(Context context, String settingName, Handler handler) {
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800482 super(handler);
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700483 mContext = context;
484 mSettingName = settingName;
485 }
486
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800487 public void register() {
488 register(mContext, Settings.Global.getUriFor(mSettingName));
489 }
490
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700491 public long getValue(long defaultValue) {
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800492 long identity = Binder.clearCallingIdentity();
493 try {
494 return Settings.Global.getLong(mContext.getContentResolver(), mSettingName,
495 defaultValue);
496 } finally {
497 Binder.restoreCallingIdentity(identity);
498 }
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700499 }
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700500 }
501
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800502 private static class StringSetCachedGlobalSetting extends ObservingSetting {
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700503
504 private final Context mContext;
505 private final String mSettingName;
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800506 private final Supplier<ArraySet<String>> mBaseValuesSupplier;
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700507
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800508 @GuardedBy("this")
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700509 private boolean mValid;
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800510 @GuardedBy("this")
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800511 private ArraySet<String> mCachedValue;
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700512
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800513 private StringSetCachedGlobalSetting(Context context, String settingName,
514 Supplier<ArraySet<String>> baseValuesSupplier, Handler handler) {
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800515 super(handler);
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700516 mContext = context;
517 mSettingName = settingName;
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800518 mBaseValuesSupplier = baseValuesSupplier;
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800519
520 mValid = false;
521 }
522
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800523 public void register() {
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800524 register(mContext, Settings.Global.getUriFor(mSettingName));
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700525 }
526
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800527 public synchronized Set<String> getValue() {
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800528 ArraySet<String> value = mCachedValue;
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700529 if (!mValid) {
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800530 long identity = Binder.clearCallingIdentity();
531 try {
532 value = new ArraySet<>(mBaseValuesSupplier.get());
533 String setting = Settings.Global.getString(mContext.getContentResolver(),
534 mSettingName);
535 if (!TextUtils.isEmpty(setting)) {
536 value.addAll(Arrays.asList(setting.split(",")));
537 }
538 } finally {
539 Binder.restoreCallingIdentity(identity);
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700540 }
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800541
542 if (isRegistered()) {
543 mValid = true;
544 mCachedValue = value;
545 }
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700546 }
547
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800548 return value;
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700549 }
550
551 public synchronized void invalidate() {
552 mValid = false;
553 mCachedValue = null;
554 }
555
556 @Override
557 public void onChange(boolean selfChange, Uri uri, int userId) {
558 invalidate();
559 super.onChange(selfChange, uri, userId);
560 }
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700561 }
562}