1 /* 2 * Copyright (C) 2020 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 17 package com.android.systemui.util.settings; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.annotation.UserIdInt; 22 import android.content.ContentResolver; 23 import android.database.ContentObserver; 24 import android.net.Uri; 25 import android.os.UserHandle; 26 import android.provider.Settings; 27 28 import com.android.systemui.settings.UserTracker; 29 30 /** 31 * Used to interact with Settings.Secure, Settings.Global, and Settings.System. 32 * 33 * This interface can be implemented to give instance method (instead of static method) versions 34 * of Settings.Secure, Settings.Global, and Settings.System. It can be injected into class 35 * constructors and then faked or mocked as needed in tests. 36 * 37 * You can ask for {@link SecureSettings}, {@link GlobalSettings}, or {@link SystemSettings} to be 38 * injected as needed. 39 * 40 * This class also provides {@link #registerContentObserver(String, ContentObserver)} methods, 41 * normally found on {@link ContentResolver} instances, unifying setting related actions in one 42 * place. 43 */ 44 public interface SettingsProxy { 45 46 /** 47 * Returns the {@link ContentResolver} this instance was constructed with. 48 */ getContentResolver()49 ContentResolver getContentResolver(); 50 51 /** 52 * Returns that {@link UserTracker} this instance was constructed with. 53 */ getUserTracker()54 UserTracker getUserTracker(); 55 56 /** 57 * Returns the user id for the associated {@link ContentResolver}. 58 */ getUserId()59 default int getUserId() { 60 return getContentResolver().getUserId(); 61 } 62 63 /** 64 * Returns the actual current user handle when querying with the current user. Otherwise, 65 * returns the passed in user id. 66 */ getRealUserHandle(int userHandle)67 default int getRealUserHandle(int userHandle) { 68 if (userHandle != UserHandle.USER_CURRENT) { 69 return userHandle; 70 } 71 return getUserTracker().getUserId(); 72 } 73 74 /** 75 * Construct the content URI for a particular name/value pair, 76 * useful for monitoring changes with a ContentObserver. 77 * @param name to look up in the table 78 * @return the corresponding content URI, or null if not present 79 */ getUriFor(String name)80 Uri getUriFor(String name); 81 82 /** 83 * Convenience wrapper around 84 * {@link ContentResolver#registerContentObserver(Uri, boolean, ContentObserver)}.' 85 * 86 * Implicitly calls {@link #getUriFor(String)} on the passed in name. 87 */ registerContentObserver(String name, ContentObserver settingsObserver)88 default void registerContentObserver(String name, ContentObserver settingsObserver) { 89 registerContentObserver(getUriFor(name), settingsObserver); 90 } 91 92 /** 93 * Convenience wrapper around 94 * {@link ContentResolver#registerContentObserver(Uri, boolean, ContentObserver)}.' 95 */ registerContentObserver(Uri uri, ContentObserver settingsObserver)96 default void registerContentObserver(Uri uri, ContentObserver settingsObserver) { 97 registerContentObserverForUser(uri, settingsObserver, getUserId()); 98 } 99 100 /** 101 * Convenience wrapper around 102 * {@link ContentResolver#registerContentObserver(Uri, boolean, ContentObserver)}.' 103 * 104 * Implicitly calls {@link #getUriFor(String)} on the passed in name. 105 */ registerContentObserver(String name, boolean notifyForDescendants, ContentObserver settingsObserver)106 default void registerContentObserver(String name, boolean notifyForDescendants, 107 ContentObserver settingsObserver) { 108 registerContentObserver(getUriFor(name), notifyForDescendants, settingsObserver); 109 } 110 111 /** 112 * Convenience wrapper around 113 * {@link ContentResolver#registerContentObserver(Uri, boolean, ContentObserver)}.' 114 */ registerContentObserver(Uri uri, boolean notifyForDescendants, ContentObserver settingsObserver)115 default void registerContentObserver(Uri uri, boolean notifyForDescendants, 116 ContentObserver settingsObserver) { 117 registerContentObserverForUser(uri, notifyForDescendants, settingsObserver, getUserId()); 118 } 119 120 /** 121 * Convenience wrapper around 122 * {@link ContentResolver#registerContentObserver(Uri, boolean, ContentObserver, int)} 123 * 124 * Implicitly calls {@link #getUriFor(String)} on the passed in name. 125 */ registerContentObserverForUser( String name, ContentObserver settingsObserver, int userHandle)126 default void registerContentObserverForUser( 127 String name, ContentObserver settingsObserver, int userHandle) { 128 registerContentObserverForUser( 129 getUriFor(name), settingsObserver, userHandle); 130 } 131 132 /** 133 * Convenience wrapper around 134 * {@link ContentResolver#registerContentObserver(Uri, boolean, ContentObserver, int)} 135 */ registerContentObserverForUser( Uri uri, ContentObserver settingsObserver, int userHandle)136 default void registerContentObserverForUser( 137 Uri uri, ContentObserver settingsObserver, int userHandle) { 138 registerContentObserverForUser( 139 uri, false, settingsObserver, userHandle); 140 } 141 142 /** 143 * Convenience wrapper around 144 * {@link ContentResolver#registerContentObserver(Uri, boolean, ContentObserver, int)} 145 * 146 * Implicitly calls {@link #getUriFor(String)} on the passed in name. 147 */ registerContentObserverForUser( String name, boolean notifyForDescendants, ContentObserver settingsObserver, int userHandle)148 default void registerContentObserverForUser( 149 String name, boolean notifyForDescendants, ContentObserver settingsObserver, 150 int userHandle) { 151 registerContentObserverForUser( 152 getUriFor(name), notifyForDescendants, settingsObserver, userHandle); 153 } 154 155 /** 156 * Convenience wrapper around 157 * {@link ContentResolver#registerContentObserver(Uri, boolean, ContentObserver, int)} 158 */ registerContentObserverForUser( Uri uri, boolean notifyForDescendants, ContentObserver settingsObserver, int userHandle)159 default void registerContentObserverForUser( 160 Uri uri, boolean notifyForDescendants, ContentObserver settingsObserver, 161 int userHandle) { 162 getContentResolver().registerContentObserver( 163 uri, notifyForDescendants, settingsObserver, getRealUserHandle(userHandle)); 164 } 165 166 /** See {@link ContentResolver#unregisterContentObserver(ContentObserver)}. */ unregisterContentObserver(ContentObserver settingsObserver)167 default void unregisterContentObserver(ContentObserver settingsObserver) { 168 getContentResolver().unregisterContentObserver(settingsObserver); 169 } 170 171 /** 172 * Look up a name in the database. 173 * @param name to look up in the table 174 * @return the corresponding value, or null if not present 175 */ getString(String name)176 default String getString(String name) { 177 return getStringForUser(name, getUserId()); 178 } 179 180 /**See {@link #getString(String)}. */ getStringForUser(String name, int userHandle)181 String getStringForUser(String name, int userHandle); 182 183 /** 184 * Store a name/value pair into the database. Values written by this method will be 185 * overridden if a restore happens in the future. 186 * 187 * @param name to store 188 * @param value to associate with the name 189 * @return true if the value was set, false on database errors 190 */ putString(String name, String value, boolean overrideableByRestore)191 boolean putString(String name, String value, boolean overrideableByRestore); 192 193 /** 194 * Store a name/value pair into the database. 195 * @param name to store 196 * @param value to associate with the name 197 * @return true if the value was set, false on database errors 198 */ putString(String name, String value)199 default boolean putString(String name, String value) { 200 return putStringForUser(name, value, getUserId()); 201 } 202 203 /** See {@link #putString(String, String)}. */ putStringForUser(String name, String value, int userHandle)204 boolean putStringForUser(String name, String value, int userHandle); 205 206 /** See {@link #putString(String, String)}. */ putStringForUser(@onNull String name, @Nullable String value, @Nullable String tag, boolean makeDefault, @UserIdInt int userHandle, boolean overrideableByRestore)207 boolean putStringForUser(@NonNull String name, @Nullable String value, @Nullable String tag, 208 boolean makeDefault, @UserIdInt int userHandle, boolean overrideableByRestore); 209 210 /** 211 * Store a name/value pair into the database. 212 * <p> 213 * The method takes an optional tag to associate with the setting 214 * which can be used to clear only settings made by your package and 215 * associated with this tag by passing the tag to {@link 216 * #resetToDefaults(String)}. Anyone can override 217 * the current tag. Also if another package changes the setting 218 * then the tag will be set to the one specified in the set call 219 * which can be null. Also any of the settings setters that do not 220 * take a tag as an argument effectively clears the tag. 221 * </p><p> 222 * For example, if you set settings A and B with tags T1 and T2 and 223 * another app changes setting A (potentially to the same value), it 224 * can assign to it a tag T3 (note that now the package that changed 225 * the setting is not yours). Now if you reset your changes for T1 and 226 * T2 only setting B will be reset and A not (as it was changed by 227 * another package) but since A did not change you are in the desired 228 * initial state. Now if the other app changes the value of A (assuming 229 * you registered an observer in the beginning) you would detect that 230 * the setting was changed by another app and handle this appropriately 231 * (ignore, set back to some value, etc). 232 * </p><p> 233 * Also the method takes an argument whether to make the value the 234 * default for this setting. If the system already specified a default 235 * value, then the one passed in here will <strong>not</strong> 236 * be set as the default. 237 * </p> 238 * 239 * @param name to store. 240 * @param value to associate with the name. 241 * @param tag to associate with the setting. 242 * @param makeDefault whether to make the value the default one. 243 * @return true if the value was set, false on database errors. 244 * 245 * @see #resetToDefaults(String) 246 * 247 */ putString(@onNull String name, @Nullable String value, @Nullable String tag, boolean makeDefault)248 boolean putString(@NonNull String name, @Nullable String value, @Nullable String tag, 249 boolean makeDefault); 250 251 /** 252 * Convenience function for retrieving a single secure settings value 253 * as an integer. Note that internally setting values are always 254 * stored as strings; this function converts the string to an integer 255 * for you. The default value will be returned if the setting is 256 * not defined or not an integer. 257 * 258 * @param name The name of the setting to retrieve. 259 * @param def Value to return if the setting is not defined. 260 * 261 * @return The setting's current value, or 'def' if it is not defined 262 * or not a valid integer. 263 */ getInt(String name, int def)264 default int getInt(String name, int def) { 265 return getIntForUser(name, def, getUserId()); 266 } 267 268 /** See {@link #getInt(String, int)}. */ getIntForUser(String name, int def, int userHandle)269 default int getIntForUser(String name, int def, int userHandle) { 270 String v = getStringForUser(name, userHandle); 271 try { 272 return v != null ? Integer.parseInt(v) : def; 273 } catch (NumberFormatException e) { 274 return def; 275 } 276 } 277 278 /** 279 * Convenience function for retrieving a single secure settings value 280 * as an integer. Note that internally setting values are always 281 * stored as strings; this function converts the string to an integer 282 * for you. 283 * <p> 284 * This version does not take a default value. If the setting has not 285 * been set, or the string value is not a number, 286 * it throws {@link Settings.SettingNotFoundException}. 287 * 288 * @param name The name of the setting to retrieve. 289 * 290 * @throws Settings.SettingNotFoundException Thrown if a setting by the given 291 * name can't be found or the setting value is not an integer. 292 * 293 * @return The setting's current value. 294 */ getInt(String name)295 default int getInt(String name) throws Settings.SettingNotFoundException { 296 return getIntForUser(name, getUserId()); 297 } 298 299 /** See {@link #getInt(String)}. */ getIntForUser(String name, int userHandle)300 default int getIntForUser(String name, int userHandle) 301 throws Settings.SettingNotFoundException { 302 String v = getStringForUser(name, userHandle); 303 try { 304 return Integer.parseInt(v); 305 } catch (NumberFormatException e) { 306 throw new Settings.SettingNotFoundException(name); 307 } 308 } 309 310 /** 311 * Convenience function for updating a single settings value as an 312 * integer. This will either create a new entry in the table if the 313 * given name does not exist, or modify the value of the existing row 314 * with that name. Note that internally setting values are always 315 * stored as strings, so this function converts the given value to a 316 * string before storing it. 317 * 318 * @param name The name of the setting to modify. 319 * @param value The new value for the setting. 320 * @return true if the value was set, false on database errors 321 */ putInt(String name, int value)322 default boolean putInt(String name, int value) { 323 return putIntForUser(name, value, getUserId()); 324 } 325 326 /** See {@link #putInt(String, int)}. */ putIntForUser(String name, int value, int userHandle)327 default boolean putIntForUser(String name, int value, int userHandle) { 328 return putStringForUser(name, Integer.toString(value), userHandle); 329 } 330 331 /** 332 * Convenience function for retrieving a single secure settings value 333 * as a boolean. Note that internally setting values are always 334 * stored as strings; this function converts the string to a boolean 335 * for you. The default value will be returned if the setting is 336 * not defined or not a boolean. 337 * 338 * @param name The name of the setting to retrieve. 339 * @param def Value to return if the setting is not defined. 340 * 341 * @return The setting's current value, or 'def' if it is not defined 342 * or not a valid boolean. 343 */ getBool(String name, boolean def)344 default boolean getBool(String name, boolean def) { 345 return getBoolForUser(name, def, getUserId()); 346 } 347 348 /** See {@link #getBool(String, boolean)}. */ getBoolForUser(String name, boolean def, int userHandle)349 default boolean getBoolForUser(String name, boolean def, int userHandle) { 350 return getIntForUser(name, def ? 1 : 0, userHandle) != 0; 351 } 352 353 /** 354 * Convenience function for retrieving a single secure settings value 355 * as a boolean. Note that internally setting values are always 356 * stored as strings; this function converts the string to a boolean 357 * for you. 358 * <p> 359 * This version does not take a default value. If the setting has not 360 * been set, or the string value is not a number, 361 * it throws {@link Settings.SettingNotFoundException}. 362 * 363 * @param name The name of the setting to retrieve. 364 * 365 * @throws Settings.SettingNotFoundException Thrown if a setting by the given 366 * name can't be found or the setting value is not a boolean. 367 * 368 * @return The setting's current value. 369 */ getBool(String name)370 default boolean getBool(String name) throws Settings.SettingNotFoundException { 371 return getBoolForUser(name, getUserId()); 372 } 373 374 /** See {@link #getBool(String)}. */ getBoolForUser(String name, int userHandle)375 default boolean getBoolForUser(String name, int userHandle) 376 throws Settings.SettingNotFoundException { 377 return getIntForUser(name, userHandle) != 0; 378 } 379 380 /** 381 * Convenience function for updating a single settings value as a 382 * boolean. This will either create a new entry in the table if the 383 * given name does not exist, or modify the value of the existing row 384 * with that name. Note that internally setting values are always 385 * stored as strings, so this function converts the given value to a 386 * string before storing it. 387 * 388 * @param name The name of the setting to modify. 389 * @param value The new value for the setting. 390 * @return true if the value was set, false on database errors 391 */ putBool(String name, boolean value)392 default boolean putBool(String name, boolean value) { 393 return putBoolForUser(name, value, getUserId()); 394 } 395 396 /** See {@link #putBool(String, boolean)}. */ putBoolForUser(String name, boolean value, int userHandle)397 default boolean putBoolForUser(String name, boolean value, int userHandle) { 398 return putIntForUser(name, value ? 1 : 0, userHandle); 399 } 400 401 /** 402 * Convenience function for retrieving a single secure settings value 403 * as a {@code long}. Note that internally setting values are always 404 * stored as strings; this function converts the string to a {@code long} 405 * for you. The default value will be returned if the setting is 406 * not defined or not a {@code long}. 407 * 408 * @param name The name of the setting to retrieve. 409 * @param def Value to return if the setting is not defined. 410 * 411 * @return The setting's current value, or 'def' if it is not defined 412 * or not a valid {@code long}. 413 */ getLong(String name, long def)414 default long getLong(String name, long def) { 415 return getLongForUser(name, def, getUserId()); 416 } 417 418 /** See {@link #getLong(String, long)}. */ getLongForUser(String name, long def, int userHandle)419 default long getLongForUser(String name, long def, int userHandle) { 420 String valString = getStringForUser(name, userHandle); 421 long value; 422 try { 423 value = valString != null ? Long.parseLong(valString) : def; 424 } catch (NumberFormatException e) { 425 value = def; 426 } 427 return value; 428 } 429 430 /** 431 * Convenience function for retrieving a single secure settings value 432 * as a {@code long}. Note that internally setting values are always 433 * stored as strings; this function converts the string to a {@code long} 434 * for you. 435 * <p> 436 * This version does not take a default value. If the setting has not 437 * been set, or the string value is not a number, 438 * it throws {@link Settings.SettingNotFoundException}. 439 * 440 * @param name The name of the setting to retrieve. 441 * 442 * @return The setting's current value. 443 * @throws Settings.SettingNotFoundException Thrown if a setting by the given 444 * name can't be found or the setting value is not an integer. 445 */ getLong(String name)446 default long getLong(String name) throws Settings.SettingNotFoundException { 447 return getLongForUser(name, getUserId()); 448 } 449 450 /** See {@link #getLong(String)}. */ getLongForUser(String name, int userHandle)451 default long getLongForUser(String name, int userHandle) 452 throws Settings.SettingNotFoundException { 453 String valString = getStringForUser(name, userHandle); 454 try { 455 return Long.parseLong(valString); 456 } catch (NumberFormatException e) { 457 throw new Settings.SettingNotFoundException(name); 458 } 459 } 460 461 /** 462 * Convenience function for updating a secure settings value as a long 463 * integer. This will either create a new entry in the table if the 464 * given name does not exist, or modify the value of the existing row 465 * with that name. Note that internally setting values are always 466 * stored as strings, so this function converts the given value to a 467 * string before storing it. 468 * 469 * @param name The name of the setting to modify. 470 * @param value The new value for the setting. 471 * @return true if the value was set, false on database errors 472 */ putLong(String name, long value)473 default boolean putLong(String name, long value) { 474 return putLongForUser(name, value, getUserId()); 475 } 476 477 /** See {@link #putLong(String, long)}. */ putLongForUser(String name, long value, int userHandle)478 default boolean putLongForUser(String name, long value, int userHandle) { 479 return putStringForUser(name, Long.toString(value), userHandle); 480 } 481 482 /** 483 * Convenience function for retrieving a single secure settings value 484 * as a floating point number. Note that internally setting values are 485 * always stored as strings; this function converts the string to an 486 * float for you. The default value will be returned if the setting 487 * is not defined or not a valid float. 488 * 489 * @param name The name of the setting to retrieve. 490 * @param def Value to return if the setting is not defined. 491 * 492 * @return The setting's current value, or 'def' if it is not defined 493 * or not a valid float. 494 */ getFloat(String name, float def)495 default float getFloat(String name, float def) { 496 return getFloatForUser(name, def, getUserId()); 497 } 498 499 /** See {@link #getFloat(String)}. */ getFloatForUser(String name, float def, int userHandle)500 default float getFloatForUser(String name, float def, int userHandle) { 501 String v = getStringForUser(name, userHandle); 502 try { 503 return v != null ? Float.parseFloat(v) : def; 504 } catch (NumberFormatException e) { 505 return def; 506 } 507 } 508 509 /** 510 * Convenience function for retrieving a single secure settings value 511 * as a float. Note that internally setting values are always 512 * stored as strings; this function converts the string to a float 513 * for you. 514 * <p> 515 * This version does not take a default value. If the setting has not 516 * been set, or the string value is not a number, 517 * it throws {@link Settings.SettingNotFoundException}. 518 * 519 * @param name The name of the setting to retrieve. 520 * 521 * @throws Settings.SettingNotFoundException Thrown if a setting by the given 522 * name can't be found or the setting value is not a float. 523 * 524 * @return The setting's current value. 525 */ getFloat(String name)526 default float getFloat(String name) throws Settings.SettingNotFoundException { 527 return getFloatForUser(name, getUserId()); 528 } 529 530 /** See {@link #getFloat(String, float)}. */ getFloatForUser(String name, int userHandle)531 default float getFloatForUser(String name, int userHandle) 532 throws Settings.SettingNotFoundException { 533 String v = getStringForUser(name, userHandle); 534 if (v == null) { 535 throw new Settings.SettingNotFoundException(name); 536 } 537 try { 538 return Float.parseFloat(v); 539 } catch (NumberFormatException e) { 540 throw new Settings.SettingNotFoundException(name); 541 } 542 } 543 544 /** 545 * Convenience function for updating a single settings value as a 546 * floating point number. This will either create a new entry in the 547 * table if the given name does not exist, or modify the value of the 548 * existing row with that name. Note that internally setting values 549 * are always stored as strings, so this function converts the given 550 * value to a string before storing it. 551 * 552 * @param name The name of the setting to modify. 553 * @param value The new value for the setting. 554 * @return true if the value was set, false on database errors 555 */ putFloat(String name, float value)556 default boolean putFloat(String name, float value) { 557 return putFloatForUser(name, value, getUserId()); 558 } 559 560 /** See {@link #putFloat(String, float)} */ putFloatForUser(String name, float value, int userHandle)561 default boolean putFloatForUser(String name, float value, int userHandle) { 562 return putStringForUser(name, Float.toString(value), userHandle); 563 } 564 } 565