1 /* 2 * Copyright (C) 2018 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 android.provider; 18 19 import static android.Manifest.permission.READ_DEVICE_CONFIG; 20 import static android.Manifest.permission.WRITE_DEVICE_CONFIG; 21 22 import android.annotation.CallbackExecutor; 23 import android.annotation.NonNull; 24 import android.annotation.Nullable; 25 import android.annotation.RequiresPermission; 26 import android.annotation.SystemApi; 27 import android.annotation.TestApi; 28 import android.app.ActivityThread; 29 import android.content.ContentResolver; 30 import android.content.Context; 31 import android.content.pm.PackageManager; 32 import android.database.ContentObserver; 33 import android.net.Uri; 34 import android.provider.Settings.Config.SyncDisabledMode; 35 import android.provider.Settings.ResetMode; 36 import android.util.ArrayMap; 37 import android.util.Log; 38 import android.util.Pair; 39 40 import com.android.internal.annotations.GuardedBy; 41 import com.android.internal.util.Preconditions; 42 43 import java.util.Arrays; 44 import java.util.Collections; 45 import java.util.HashMap; 46 import java.util.List; 47 import java.util.Map; 48 import java.util.Set; 49 import java.util.concurrent.Executor; 50 51 /** 52 * Device level configuration parameters which can be tuned by a separate configuration service. 53 * Namespaces that end in "_native" such as {@link #NAMESPACE_NETD_NATIVE} are intended to be used 54 * by native code and should be pushed to system properties to make them accessible. 55 * 56 * @hide 57 */ 58 @SystemApi 59 public final class DeviceConfig { 60 /** 61 * The content:// style URL for the config table. 62 * 63 * @hide 64 */ 65 public static final Uri CONTENT_URI = Uri.parse("content://" + Settings.AUTHORITY + "/config"); 66 67 /** 68 * Namespace for activity manager related features. These features will be applied 69 * immediately upon change. 70 * 71 * @hide 72 */ 73 @SystemApi 74 public static final String NAMESPACE_ACTIVITY_MANAGER = "activity_manager"; 75 76 /** 77 * Namespace for all activity manager related features that are used at the native level. 78 * These features are applied at reboot. 79 * 80 * @hide 81 */ 82 @SystemApi 83 public static final String NAMESPACE_ACTIVITY_MANAGER_NATIVE_BOOT = 84 "activity_manager_native_boot"; 85 86 /** 87 * Namespace for AlarmManager configurations. 88 * 89 * @hide 90 */ 91 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 92 @TestApi 93 public static final String NAMESPACE_ALARM_MANAGER = "alarm_manager"; 94 95 /** 96 * Namespace for all app compat related features. These features will be applied 97 * immediately upon change. 98 * 99 * @hide 100 */ 101 @SystemApi 102 public static final String NAMESPACE_APP_COMPAT = "app_compat"; 103 104 /** 105 * Namespace for all app hibernation related features. 106 * @hide 107 */ 108 @SystemApi 109 public static final String NAMESPACE_APP_HIBERNATION = "app_hibernation"; 110 111 /** 112 * Namespace for all AppSearch related features. 113 * @hide 114 */ 115 @SystemApi 116 public static final String NAMESPACE_APPSEARCH = "appsearch"; 117 118 /** 119 * Namespace for app standby configurations. 120 * 121 * @hide 122 */ 123 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 124 public static final String NAMESPACE_APP_STANDBY = "app_standby"; 125 126 /** 127 * Namespace for AttentionManagerService related features. 128 * 129 * @hide 130 */ 131 @SystemApi 132 public static final String NAMESPACE_ATTENTION_MANAGER_SERVICE = "attention_manager_service"; 133 134 /** 135 * Namespace for autofill feature that provides suggestions across all apps when 136 * the user interacts with input fields. 137 * 138 * @hide 139 */ 140 @SystemApi 141 public static final String NAMESPACE_AUTOFILL = "autofill"; 142 143 /** 144 * Namespace for battery saver feature. 145 * 146 * @hide 147 */ 148 @SystemApi 149 public static final String NAMESPACE_BATTERY_SAVER = "battery_saver"; 150 151 /** 152 * Namespace for blobstore feature that allows apps to share data blobs. 153 * 154 * @hide 155 */ 156 @SystemApi 157 public static final String NAMESPACE_BLOBSTORE = "blobstore"; 158 159 /** 160 * Namespace for all Bluetooth related features. 161 * 162 * @hide 163 */ 164 @SystemApi 165 public static final String NAMESPACE_BLUETOOTH = "bluetooth"; 166 167 /** 168 * Namespace for features relating to clipboard. 169 * 170 * @hide 171 */ 172 @SystemApi 173 public static final String NAMESPACE_CLIPBOARD = "clipboard"; 174 175 /** 176 * Namespace for all networking connectivity related features. 177 * 178 * @hide 179 */ 180 @SystemApi 181 public static final String NAMESPACE_CONNECTIVITY = "connectivity"; 182 183 /** 184 * Namespace for content capture feature used by on-device machine intelligence 185 * to provide suggestions in a privacy-safe manner. 186 * 187 * @hide 188 */ 189 @SystemApi 190 public static final String NAMESPACE_CONTENT_CAPTURE = "content_capture"; 191 192 /** 193 * Namespace for device idle configurations. 194 * 195 * @hide 196 */ 197 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 198 @TestApi 199 public static final String NAMESPACE_DEVICE_IDLE = "device_idle"; 200 201 /** 202 * Namespace for how dex runs. The feature requires a reboot to reach a clean state. 203 * 204 * @deprecated No longer used 205 * @hide 206 */ 207 @Deprecated 208 @SystemApi 209 public static final String NAMESPACE_DEX_BOOT = "dex_boot"; 210 211 /** 212 * Namespace for display manager related features. The names to access the properties in this 213 * namespace should be defined in {@link android.hardware.display.DisplayManager}. 214 * 215 * @hide 216 */ 217 @SystemApi 218 public static final String NAMESPACE_DISPLAY_MANAGER = "display_manager"; 219 220 /** 221 * Namespace for all Game Driver features. 222 * 223 * @hide 224 */ 225 @SystemApi 226 public static final String NAMESPACE_GAME_DRIVER = "game_driver"; 227 228 /** 229 * Namespace for all input-related features that are used at the native level. 230 * These features are applied at reboot. 231 * 232 * @hide 233 */ 234 @SystemApi 235 public static final String NAMESPACE_INPUT_NATIVE_BOOT = "input_native_boot"; 236 237 /** 238 * Namespace for attention-based features provided by on-device machine intelligence. 239 * 240 * @hide 241 */ 242 @SystemApi 243 public static final String NAMESPACE_INTELLIGENCE_ATTENTION = "intelligence_attention"; 244 245 /** 246 * Definitions for properties related to Content Suggestions. 247 * 248 * @hide 249 */ 250 public static final String NAMESPACE_INTELLIGENCE_CONTENT_SUGGESTIONS = 251 "intelligence_content_suggestions"; 252 253 /** 254 * Namespace for JobScheduler configurations. 255 * @hide 256 */ 257 @TestApi 258 public static final String NAMESPACE_JOB_SCHEDULER = "jobscheduler"; 259 260 /** 261 * Namespace for all lmkd related features. 262 * 263 * @hide 264 */ 265 public static final String NAMESPACE_LMKD_NATIVE = "lmkd_native"; 266 267 /** 268 * Namespace for all location related features. 269 * 270 * @hide 271 */ 272 @SystemApi 273 public static final String NAMESPACE_LOCATION = "location"; 274 275 /** 276 * Namespace for all media related features. 277 * 278 * @hide 279 */ 280 @SystemApi 281 public static final String NAMESPACE_MEDIA = "media"; 282 283 /** 284 * Namespace for all media native related features. 285 * 286 * @hide 287 */ 288 @SystemApi 289 public static final String NAMESPACE_MEDIA_NATIVE = "media_native"; 290 291 /** 292 * Namespace for all netd related features. 293 * 294 * @hide 295 */ 296 @SystemApi 297 public static final String NAMESPACE_NETD_NATIVE = "netd_native"; 298 299 /** 300 * Namespace for features related to the Package Manager Service. 301 * 302 * @hide 303 */ 304 @SystemApi 305 public static final String NAMESPACE_PACKAGE_MANAGER_SERVICE = "package_manager_service"; 306 307 /** 308 * Namespace for features related to the Profcollect native Service. 309 * These features are applied at reboot. 310 * 311 * @hide 312 */ 313 @SystemApi 314 public static final String NAMESPACE_PROFCOLLECT_NATIVE_BOOT = "profcollect_native_boot"; 315 316 /** 317 * Namespace for features related to Reboot Readiness detection. 318 * 319 * @hide 320 */ 321 @SystemApi 322 public static final String NAMESPACE_REBOOT_READINESS = "reboot_readiness"; 323 324 /** 325 * Namespace for Rollback flags that are applied immediately. 326 * 327 * @hide 328 */ 329 @SystemApi 330 public static final String NAMESPACE_ROLLBACK = "rollback"; 331 332 /** 333 * Namespace for Rollback flags that are applied after a reboot. 334 * 335 * @hide 336 */ 337 @SystemApi 338 public static final String NAMESPACE_ROLLBACK_BOOT = "rollback_boot"; 339 340 /** 341 * Namespace for Rotation Resolver Manager Service. 342 * 343 * @hide 344 */ 345 public static final String NAMESPACE_ROTATION_RESOLVER = "rotation_resolver"; 346 347 /** 348 * Namespace for all runtime related features that don't require a reboot to become active. 349 * There are no feature flags using NAMESPACE_RUNTIME. 350 * 351 * @hide 352 */ 353 @SystemApi 354 public static final String NAMESPACE_RUNTIME = "runtime"; 355 356 /** 357 * Namespace for all runtime related features that require system properties for accessing 358 * the feature flags from C++ or Java language code. One example is the app image startup 359 * cache feature use_app_image_startup_cache. 360 * 361 * @hide 362 */ 363 @SystemApi 364 public static final String NAMESPACE_RUNTIME_NATIVE = "runtime_native"; 365 366 /** 367 * Namespace for all runtime native boot related features. Boot in this case refers to the 368 * fact that the properties only take affect after rebooting the device. 369 * 370 * @hide 371 */ 372 @SystemApi 373 public static final String NAMESPACE_RUNTIME_NATIVE_BOOT = "runtime_native_boot"; 374 375 /** 376 * Namespace for system scheduler related features. These features will be applied 377 * immediately upon change. 378 * 379 * @hide 380 */ 381 @SystemApi 382 public static final String NAMESPACE_SCHEDULER = "scheduler"; 383 384 /** 385 * Namespace for settings statistics features. 386 * 387 * @hide 388 */ 389 public static final String NAMESPACE_SETTINGS_STATS = "settings_stats"; 390 391 /** 392 * Namespace for all statsd java features that can be applied immediately. 393 * 394 * @hide 395 */ 396 @SystemApi 397 public static final String NAMESPACE_STATSD_JAVA = "statsd_java"; 398 399 /** 400 * Namespace for all statsd java features that are applied on boot. 401 * 402 * @hide 403 */ 404 @SystemApi 405 public static final String NAMESPACE_STATSD_JAVA_BOOT = "statsd_java_boot"; 406 407 /** 408 * Namespace for all statsd native features that can be applied immediately. 409 * 410 * @hide 411 */ 412 @SystemApi 413 public static final String NAMESPACE_STATSD_NATIVE = "statsd_native"; 414 415 /** 416 * Namespace for all statsd native features that are applied on boot. 417 * 418 * @hide 419 */ 420 @SystemApi 421 public static final String NAMESPACE_STATSD_NATIVE_BOOT = "statsd_native_boot"; 422 423 /** 424 * Namespace for storage-related features. 425 * 426 * @deprecated Replace storage namespace with storage_native_boot. 427 * @hide 428 */ 429 @Deprecated 430 @SystemApi 431 public static final String NAMESPACE_STORAGE = "storage"; 432 433 /** 434 * Namespace for storage-related features, including native and boot. 435 * 436 * @hide 437 */ 438 @SystemApi 439 public static final String NAMESPACE_STORAGE_NATIVE_BOOT = "storage_native_boot"; 440 441 /** 442 * Namespace for System UI related features. 443 * 444 * @hide 445 */ 446 @SystemApi 447 public static final String NAMESPACE_SYSTEMUI = "systemui"; 448 449 /** 450 * Namespace for system time and time zone detection related features / behavior. 451 * 452 * @hide 453 */ 454 @SystemApi 455 public static final String NAMESPACE_SYSTEM_TIME = "system_time"; 456 457 /** 458 * Telephony related properties. 459 * 460 * @hide 461 */ 462 @SystemApi 463 public static final String NAMESPACE_TELEPHONY = "telephony"; 464 465 /** 466 * Namespace for TextClassifier related features. 467 * 468 * @hide 469 * @see android.provider.Settings.Global.TEXT_CLASSIFIER_CONSTANTS 470 */ 471 @SystemApi 472 public static final String NAMESPACE_TEXTCLASSIFIER = "textclassifier"; 473 474 /** 475 * Namespace for contacts provider related features. 476 * 477 * @hide 478 */ 479 public static final String NAMESPACE_CONTACTS_PROVIDER = "contacts_provider"; 480 481 /** 482 * Namespace for settings ui related features 483 * 484 * @hide 485 */ 486 public static final String NAMESPACE_SETTINGS_UI = "settings_ui"; 487 488 /** 489 * Namespace for android related features, i.e. for flags that affect not just a single 490 * component, but the entire system. 491 * 492 * The keys for this namespace are defined in {@link AndroidDeviceConfig}. 493 * 494 * @hide 495 */ 496 @TestApi 497 public static final String NAMESPACE_ANDROID = "android"; 498 499 /** 500 * Namespace for window manager related features. 501 * 502 * @hide 503 */ 504 public static final String NAMESPACE_WINDOW_MANAGER = "window_manager"; 505 506 /** 507 * Namespace for window manager features accessible by native code and 508 * loaded once per boot. 509 * 510 * @hide 511 */ 512 @SystemApi 513 public static final String NAMESPACE_WINDOW_MANAGER_NATIVE_BOOT = "window_manager_native_boot"; 514 515 /** 516 * List of namespaces which can be read without READ_DEVICE_CONFIG permission 517 * 518 * @hide 519 */ 520 @NonNull 521 private static final List<String> PUBLIC_NAMESPACES = 522 Arrays.asList(NAMESPACE_TEXTCLASSIFIER, NAMESPACE_RUNTIME, NAMESPACE_STATSD_JAVA, 523 NAMESPACE_STATSD_JAVA_BOOT); 524 /** 525 * Privacy related properties definitions. 526 * 527 * @hide 528 */ 529 @SystemApi 530 public static final String NAMESPACE_PRIVACY = "privacy"; 531 532 /** 533 * Namespace for biometrics related features 534 * 535 * @hide 536 */ 537 @SystemApi 538 public static final String NAMESPACE_BIOMETRICS = "biometrics"; 539 540 /** 541 * Permission related properties definitions. 542 * 543 * @hide 544 */ 545 @SystemApi 546 public static final String NAMESPACE_PERMISSIONS = "permissions"; 547 548 /** 549 * Namespace for ota related features. 550 * 551 * @hide 552 */ 553 @SystemApi 554 public static final String NAMESPACE_OTA = "ota"; 555 556 /** 557 * Namespace for all widget related features. 558 * 559 * @hide 560 */ 561 public static final String NAMESPACE_WIDGET = "widget"; 562 563 /** 564 * Namespace for connectivity thermal power manager features. 565 * 566 * @hide 567 */ 568 public static final String NAMESPACE_CONNECTIVITY_THERMAL_POWER_MANAGER = 569 "connectivity_thermal_power_manager"; 570 571 /** 572 * Namespace for configuration related features. 573 * 574 * @hide 575 */ 576 public static final String NAMESPACE_CONFIGURATION = "configuration"; 577 578 /** 579 * LatencyTracker properties definitions. 580 * 581 * @hide 582 */ 583 public static final String NAMESPACE_LATENCY_TRACKER = "latency_tracker"; 584 585 /** 586 * InteractionJankMonitor properties definitions. 587 * 588 * @hide 589 */ 590 public static final String NAMESPACE_INTERACTION_JANK_MONITOR = "interaction_jank_monitor"; 591 592 /** 593 * Namespace for game overlay related features. 594 * 595 * @hide 596 */ 597 public static final String NAMESPACE_GAME_OVERLAY = "game_overlay"; 598 599 /** 600 * Namespace for Constrain Display APIs related features. 601 * 602 * @hide 603 */ 604 @TestApi 605 public static final String NAMESPACE_CONSTRAIN_DISPLAY_APIS = "constrain_display_apis"; 606 607 /** 608 * Namespace for App Compat Overrides related features. 609 * 610 * @hide 611 */ 612 @TestApi 613 public static final String NAMESPACE_APP_COMPAT_OVERRIDES = "app_compat_overrides"; 614 615 private static final Object sLock = new Object(); 616 @GuardedBy("sLock") 617 private static ArrayMap<OnPropertiesChangedListener, Pair<String, Executor>> sListeners = 618 new ArrayMap<>(); 619 @GuardedBy("sLock") 620 private static Map<String, Pair<ContentObserver, Integer>> sNamespaces = new HashMap<>(); 621 private static final String TAG = "DeviceConfig"; 622 623 // Should never be invoked DeviceConfig()624 private DeviceConfig() { 625 } 626 627 /** 628 * Look up the value of a property for a particular namespace. 629 * 630 * @param namespace The namespace containing the property to look up. 631 * @param name The name of the property to look up. 632 * @return the corresponding value, or null if not present. 633 * @hide 634 */ 635 @SystemApi 636 @RequiresPermission(READ_DEVICE_CONFIG) getProperty(@onNull String namespace, @NonNull String name)637 public static String getProperty(@NonNull String namespace, @NonNull String name) { 638 // Fetch all properties for the namespace at once and cache them in the local process, so we 639 // incur the cost of the IPC less often. Lookups happen much more frequently than updates, 640 // and we want to optimize the former. 641 return getProperties(namespace, name).getString(name, null); 642 } 643 644 /** 645 * Look up the values of multiple properties for a particular namespace. The lookup is atomic, 646 * such that the values of these properties cannot change between the time when the first is 647 * fetched and the time when the last is fetched. 648 * <p> 649 * Each call to {@link #setProperties(Properties)} is also atomic and ensures that either none 650 * or all of the change is picked up here, but never only part of it. 651 * 652 * @param namespace The namespace containing the properties to look up. 653 * @param names The names of properties to look up, or empty to fetch all properties for the 654 * given namespace. 655 * @return {@link Properties} object containing the requested properties. This reflects the 656 * state of these properties at the time of the lookup, and is not updated to reflect any 657 * future changes. The keyset of this Properties object will contain only the intersection 658 * of properties already set and properties requested via the names parameter. Properties 659 * that are already set but were not requested will not be contained here. Properties that 660 * are not set, but were requested will not be contained here either. 661 * @hide 662 */ 663 @SystemApi 664 @NonNull 665 @RequiresPermission(READ_DEVICE_CONFIG) getProperties(@onNull String namespace, @NonNull String ... names)666 public static Properties getProperties(@NonNull String namespace, @NonNull String ... names) { 667 ContentResolver contentResolver = ActivityThread.currentApplication().getContentResolver(); 668 return new Properties(namespace, 669 Settings.Config.getStrings(contentResolver, namespace, Arrays.asList(names))); 670 } 671 672 /** 673 * Look up the String value of a property for a particular namespace. 674 * 675 * @param namespace The namespace containing the property to look up. 676 * @param name The name of the property to look up. 677 * @param defaultValue The value to return if the property does not exist or has no non-null 678 * value. 679 * @return the corresponding value, or defaultValue if none exists. 680 * @hide 681 */ 682 @SystemApi 683 @RequiresPermission(READ_DEVICE_CONFIG) getString(@onNull String namespace, @NonNull String name, @Nullable String defaultValue)684 public static String getString(@NonNull String namespace, @NonNull String name, 685 @Nullable String defaultValue) { 686 String value = getProperty(namespace, name); 687 return value != null ? value : defaultValue; 688 } 689 690 /** 691 * Look up the boolean value of a property for a particular namespace. 692 * 693 * @param namespace The namespace containing the property to look up. 694 * @param name The name of the property to look up. 695 * @param defaultValue The value to return if the property does not exist or has no non-null 696 * value. 697 * @return the correspondfing value, or defaultValue if none exists. 698 * @hide 699 */ 700 @SystemApi 701 @RequiresPermission(READ_DEVICE_CONFIG) getBoolean(@onNull String namespace, @NonNull String name, boolean defaultValue)702 public static boolean getBoolean(@NonNull String namespace, @NonNull String name, 703 boolean defaultValue) { 704 String value = getProperty(namespace, name); 705 return value != null ? Boolean.parseBoolean(value) : defaultValue; 706 } 707 708 /** 709 * Look up the int value of a property for a particular namespace. 710 * 711 * @param namespace The namespace containing the property to look up. 712 * @param name The name of the property to look up. 713 * @param defaultValue The value to return if the property does not exist, has no non-null 714 * value, or fails to parse into an int. 715 * @return the corresponding value, or defaultValue if either none exists or it does not parse. 716 * @hide 717 */ 718 @SystemApi 719 @RequiresPermission(READ_DEVICE_CONFIG) getInt(@onNull String namespace, @NonNull String name, int defaultValue)720 public static int getInt(@NonNull String namespace, @NonNull String name, int defaultValue) { 721 String value = getProperty(namespace, name); 722 if (value == null) { 723 return defaultValue; 724 } 725 try { 726 return Integer.parseInt(value); 727 } catch (NumberFormatException e) { 728 Log.e(TAG, "Parsing integer failed for " + namespace + ":" + name); 729 return defaultValue; 730 } 731 } 732 733 /** 734 * Look up the long value of a property for a particular namespace. 735 * 736 * @param namespace The namespace containing the property to look up. 737 * @param name The name of the property to look up. 738 * @param defaultValue The value to return if the property does not exist, has no non-null 739 * value, or fails to parse into a long. 740 * @return the corresponding value, or defaultValue if either none exists or it does not parse. 741 * @hide 742 */ 743 @SystemApi 744 @RequiresPermission(READ_DEVICE_CONFIG) getLong(@onNull String namespace, @NonNull String name, long defaultValue)745 public static long getLong(@NonNull String namespace, @NonNull String name, long defaultValue) { 746 String value = getProperty(namespace, name); 747 if (value == null) { 748 return defaultValue; 749 } 750 try { 751 return Long.parseLong(value); 752 } catch (NumberFormatException e) { 753 Log.e(TAG, "Parsing long failed for " + namespace + ":" + name); 754 return defaultValue; 755 } 756 } 757 758 /** 759 * Look up the float value of a property for a particular namespace. 760 * 761 * @param namespace The namespace containing the property to look up. 762 * @param name The name of the property to look up. 763 * @param defaultValue The value to return if the property does not exist, has no non-null 764 * value, or fails to parse into a float. 765 * @return the corresponding value, or defaultValue if either none exists or it does not parse. 766 * @hide 767 */ 768 @SystemApi 769 @RequiresPermission(READ_DEVICE_CONFIG) getFloat(@onNull String namespace, @NonNull String name, float defaultValue)770 public static float getFloat(@NonNull String namespace, @NonNull String name, 771 float defaultValue) { 772 String value = getProperty(namespace, name); 773 if (value == null) { 774 return defaultValue; 775 } 776 try { 777 return Float.parseFloat(value); 778 } catch (NumberFormatException e) { 779 Log.e(TAG, "Parsing float failed for " + namespace + ":" + name); 780 return defaultValue; 781 } 782 } 783 784 /** 785 * Create a new property with the the provided name and value in the provided namespace, or 786 * update the value of such a property if it already exists. The same name can exist in multiple 787 * namespaces and might have different values in any or all namespaces. 788 * <p> 789 * The method takes an argument indicating whether to make the value the default for this 790 * property. 791 * <p> 792 * All properties stored for a particular scope can be reverted to their default values 793 * by passing the namespace to {@link #resetToDefaults(int, String)}. 794 * 795 * @param namespace The namespace containing the property to create or update. 796 * @param name The name of the property to create or update. 797 * @param value The value to store for the property. 798 * @param makeDefault Whether to make the new value the default one. 799 * @return True if the value was set, false if the storage implementation throws errors. 800 * @hide 801 * @see #resetToDefaults(int, String). 802 */ 803 @SystemApi 804 @RequiresPermission(WRITE_DEVICE_CONFIG) setProperty(@onNull String namespace, @NonNull String name, @Nullable String value, boolean makeDefault)805 public static boolean setProperty(@NonNull String namespace, @NonNull String name, 806 @Nullable String value, boolean makeDefault) { 807 ContentResolver contentResolver = ActivityThread.currentApplication().getContentResolver(); 808 return Settings.Config.putString(contentResolver, namespace, name, value, makeDefault); 809 } 810 811 /** 812 * Set all of the properties for a specific namespace. Pre-existing properties will be updated 813 * and new properties will be added if necessary. Any pre-existing properties for the specific 814 * namespace which are not part of the provided {@link Properties} object will be deleted from 815 * the namespace. These changes are all applied atomically, such that no calls to read or reset 816 * these properties can happen in the middle of this update. 817 * <p> 818 * Each call to {@link #getProperties(String, String...)} is also atomic and ensures that either 819 * none or all of this update is picked up, but never only part of it. 820 * 821 * @param properties the complete set of properties to set for a specific namespace. 822 * @throws BadConfigException if the provided properties are banned by RescueParty. 823 * @return True if the values were set, false otherwise. 824 * @hide 825 */ 826 @SystemApi 827 @RequiresPermission(WRITE_DEVICE_CONFIG) setProperties(@onNull Properties properties)828 public static boolean setProperties(@NonNull Properties properties) throws BadConfigException { 829 ContentResolver contentResolver = ActivityThread.currentApplication().getContentResolver(); 830 return Settings.Config.setStrings(contentResolver, properties.getNamespace(), 831 properties.mMap); 832 } 833 834 /** 835 * Reset properties to their default values by removing the underlying values. 836 * <p> 837 * The method accepts an optional namespace parameter. If provided, only properties set within 838 * that namespace will be reset. Otherwise, all properties will be reset. 839 * <p> 840 * Note: This method should only be used by {@link com.android.server.RescueParty}. It was 841 * designed to be used in the event of boot or crash loops caused by flag changes. It does not 842 * revert flag values to defaults - instead it removes the property entirely which causes the 843 * consumer of the flag to use hardcoded defaults upon retrieval. 844 * <p> 845 * To clear values for a namespace without removing the underlying properties, construct a 846 * {@link Properties} object with the caller's namespace and either an empty flag map, or some 847 * snapshot of flag values. Then use {@link #setProperties(Properties)} to remove all flags 848 * under the namespace, or set them to the values in the snapshot. 849 * <p> 850 * To revert values for testing, one should mock DeviceConfig using 851 * {@link com.android.server.testables.TestableDeviceConfig} where possible. Otherwise, fallback 852 * to using {@link #setProperties(Properties)} as outlined above. 853 * 854 * @param resetMode The reset mode to use. 855 * @param namespace Optionally, the specific namespace which resets will be limited to. 856 * @hide 857 * @see #setProperty(String, String, String, boolean) 858 */ 859 @SystemApi 860 @RequiresPermission(WRITE_DEVICE_CONFIG) resetToDefaults(@esetMode int resetMode, @Nullable String namespace)861 public static void resetToDefaults(@ResetMode int resetMode, @Nullable String namespace) { 862 ContentResolver contentResolver = ActivityThread.currentApplication().getContentResolver(); 863 Settings.Config.resetToDefaults(contentResolver, resetMode, namespace); 864 } 865 866 /** 867 * Disables or re-enables bulk modifications ({@link #setProperties(Properties)}) to device 868 * config values. This is intended for use during tests to prevent a sync operation clearing 869 * config values, which could influence the outcome of the tests, i.e. by changing behavior. 870 * 871 * @param syncDisabledMode the mode to use, see {@link Settings.Config#SYNC_DISABLED_MODE_NONE}, 872 * {@link Settings.Config#SYNC_DISABLED_MODE_PERSISTENT} and {@link 873 * Settings.Config#SYNC_DISABLED_MODE_UNTIL_REBOOT} 874 * 875 * @see #isSyncDisabled() 876 * @hide 877 */ 878 @RequiresPermission(WRITE_DEVICE_CONFIG) setSyncDisabled(@yncDisabledMode int syncDisabledMode)879 public static void setSyncDisabled(@SyncDisabledMode int syncDisabledMode) { 880 ContentResolver contentResolver = ActivityThread.currentApplication().getContentResolver(); 881 Settings.Config.setSyncDisabled(contentResolver, syncDisabledMode); 882 } 883 884 /** 885 * Returns the current state of sync disabling, {@code true} when disabled, {@code false} 886 * otherwise. 887 * 888 * @see #setSyncDisabled(int) 889 * @hide 890 */ 891 @RequiresPermission(WRITE_DEVICE_CONFIG) isSyncDisabled()892 public static boolean isSyncDisabled() { 893 ContentResolver contentResolver = ActivityThread.currentApplication().getContentResolver(); 894 return Settings.Config.isSyncDisabled(contentResolver); 895 } 896 897 /** 898 * Add a listener for property changes. 899 * <p> 900 * This listener will be called whenever properties in the specified namespace change. Callbacks 901 * will be made on the specified executor. Future calls to this method with the same listener 902 * will replace the old namespace and executor. Remove the listener entirely by calling 903 * {@link #removeOnPropertiesChangedListener(OnPropertiesChangedListener)}. 904 * 905 * @param namespace The namespace containing properties to monitor. 906 * @param executor The executor which will be used to run callbacks. 907 * @param onPropertiesChangedListener The listener to add. 908 * @hide 909 * @see #removeOnPropertiesChangedListener(OnPropertiesChangedListener) 910 */ 911 @SystemApi 912 @RequiresPermission(READ_DEVICE_CONFIG) addOnPropertiesChangedListener( @onNull String namespace, @NonNull @CallbackExecutor Executor executor, @NonNull OnPropertiesChangedListener onPropertiesChangedListener)913 public static void addOnPropertiesChangedListener( 914 @NonNull String namespace, 915 @NonNull @CallbackExecutor Executor executor, 916 @NonNull OnPropertiesChangedListener onPropertiesChangedListener) { 917 enforceReadPermission(ActivityThread.currentApplication().getApplicationContext(), 918 namespace); 919 synchronized (sLock) { 920 Pair<String, Executor> oldNamespace = sListeners.get(onPropertiesChangedListener); 921 if (oldNamespace == null) { 922 // Brand new listener, add it to the list. 923 sListeners.put(onPropertiesChangedListener, new Pair<>(namespace, executor)); 924 incrementNamespace(namespace); 925 } else if (namespace.equals(oldNamespace.first)) { 926 // Listener is already registered for this namespace, update executor just in case. 927 sListeners.put(onPropertiesChangedListener, new Pair<>(namespace, executor)); 928 } else { 929 // Update this listener from an old namespace to the new one. 930 decrementNamespace(sListeners.get(onPropertiesChangedListener).first); 931 sListeners.put(onPropertiesChangedListener, new Pair<>(namespace, executor)); 932 incrementNamespace(namespace); 933 } 934 } 935 } 936 937 /** 938 * Remove a listener for property changes. The listener will receive no further notification of 939 * property changes. 940 * 941 * @param onPropertiesChangedListener The listener to remove. 942 * @hide 943 * @see #addOnPropertiesChangedListener(String, Executor, OnPropertiesChangedListener) 944 */ 945 @SystemApi removeOnPropertiesChangedListener( @onNull OnPropertiesChangedListener onPropertiesChangedListener)946 public static void removeOnPropertiesChangedListener( 947 @NonNull OnPropertiesChangedListener onPropertiesChangedListener) { 948 Preconditions.checkNotNull(onPropertiesChangedListener); 949 synchronized (sLock) { 950 if (sListeners.containsKey(onPropertiesChangedListener)) { 951 decrementNamespace(sListeners.get(onPropertiesChangedListener).first); 952 sListeners.remove(onPropertiesChangedListener); 953 } 954 } 955 } 956 createNamespaceUri(@onNull String namespace)957 private static Uri createNamespaceUri(@NonNull String namespace) { 958 Preconditions.checkNotNull(namespace); 959 return CONTENT_URI.buildUpon().appendPath(namespace).build(); 960 } 961 962 /** 963 * Increment the count used to represent the number of listeners subscribed to the given 964 * namespace. If this is the first (i.e. incrementing from 0 to 1) for the given namespace, a 965 * ContentObserver is registered. 966 * 967 * @param namespace The namespace to increment the count for. 968 */ 969 @GuardedBy("sLock") incrementNamespace(@onNull String namespace)970 private static void incrementNamespace(@NonNull String namespace) { 971 Preconditions.checkNotNull(namespace); 972 Pair<ContentObserver, Integer> namespaceCount = sNamespaces.get(namespace); 973 if (namespaceCount != null) { 974 sNamespaces.put(namespace, new Pair<>(namespaceCount.first, namespaceCount.second + 1)); 975 } else { 976 // This is a new namespace, register a ContentObserver for it. 977 ContentObserver contentObserver = new ContentObserver(null) { 978 @Override 979 public void onChange(boolean selfChange, Uri uri) { 980 if (uri != null) { 981 handleChange(uri); 982 } 983 } 984 }; 985 ActivityThread.currentApplication().getContentResolver() 986 .registerContentObserver(createNamespaceUri(namespace), true, contentObserver); 987 sNamespaces.put(namespace, new Pair<>(contentObserver, 1)); 988 } 989 } 990 991 /** 992 * Decrement the count used to represent the number of listeners subscribed to the given 993 * namespace. If this is the final decrement call (i.e. decrementing from 1 to 0) for the given 994 * namespace, the ContentObserver that had been tracking it will be removed. 995 * 996 * @param namespace The namespace to decrement the count for. 997 */ 998 @GuardedBy("sLock") decrementNamespace(@onNull String namespace)999 private static void decrementNamespace(@NonNull String namespace) { 1000 Preconditions.checkNotNull(namespace); 1001 Pair<ContentObserver, Integer> namespaceCount = sNamespaces.get(namespace); 1002 if (namespaceCount == null) { 1003 // This namespace is not registered and does not need to be decremented 1004 return; 1005 } else if (namespaceCount.second > 1) { 1006 sNamespaces.put(namespace, new Pair<>(namespaceCount.first, namespaceCount.second - 1)); 1007 } else { 1008 // Decrementing a namespace to zero means we no longer need its ContentObserver. 1009 ActivityThread.currentApplication().getContentResolver() 1010 .unregisterContentObserver(namespaceCount.first); 1011 sNamespaces.remove(namespace); 1012 } 1013 } 1014 handleChange(@onNull Uri uri)1015 private static void handleChange(@NonNull Uri uri) { 1016 Preconditions.checkNotNull(uri); 1017 List<String> pathSegments = uri.getPathSegments(); 1018 // pathSegments(0) is "config" 1019 final String namespace = pathSegments.get(1); 1020 Properties.Builder propBuilder = new Properties.Builder(namespace); 1021 try { 1022 Properties allProperties = getProperties(namespace); 1023 for (int i = 2; i < pathSegments.size(); ++i) { 1024 String key = pathSegments.get(i); 1025 propBuilder.setString(key, allProperties.getString(key, null)); 1026 } 1027 } catch (SecurityException e) { 1028 // Silently failing to not crash binder or listener threads. 1029 Log.e(TAG, "OnPropertyChangedListener update failed: permission violation."); 1030 return; 1031 } 1032 Properties properties = propBuilder.build(); 1033 1034 synchronized (sLock) { 1035 for (int i = 0; i < sListeners.size(); i++) { 1036 if (namespace.equals(sListeners.valueAt(i).first)) { 1037 final OnPropertiesChangedListener listener = sListeners.keyAt(i); 1038 sListeners.valueAt(i).second.execute(() -> { 1039 listener.onPropertiesChanged(properties); 1040 }); 1041 } 1042 } 1043 } 1044 } 1045 1046 /** 1047 * Enforces READ_DEVICE_CONFIG permission if namespace is not one of public namespaces. 1048 * @hide 1049 */ enforceReadPermission(Context context, String namespace)1050 public static void enforceReadPermission(Context context, String namespace) { 1051 if (context.checkCallingOrSelfPermission(READ_DEVICE_CONFIG) 1052 != PackageManager.PERMISSION_GRANTED) { 1053 if (!PUBLIC_NAMESPACES.contains(namespace)) { 1054 throw new SecurityException("Permission denial: reading from settings requires:" 1055 + READ_DEVICE_CONFIG); 1056 } 1057 } 1058 } 1059 1060 /** 1061 * Returns list of namespaces that can be read without READ_DEVICE_CONFIG_PERMISSION; 1062 * @hide 1063 */ getPublicNamespaces()1064 public static @NonNull List<String> getPublicNamespaces() { 1065 return PUBLIC_NAMESPACES; 1066 } 1067 1068 /** 1069 * Interface for monitoring changes to properties. Implementations will receive callbacks when 1070 * properties change, including a {@link Properties} object which contains a single namespace 1071 * and all of the properties which changed for that namespace. This includes properties which 1072 * were added, updated, or deleted. This is not necessarily a complete list of all properties 1073 * belonging to the namespace, as properties which don't change are omitted. 1074 * <p> 1075 * Override {@link #onPropertiesChanged(Properties)} to handle callbacks for changes. 1076 * 1077 * @hide 1078 */ 1079 @SystemApi 1080 public interface OnPropertiesChangedListener { 1081 /** 1082 * Called when one or more properties have changed, providing a Properties object with all 1083 * of the changed properties. This object will contain only properties which have changed, 1084 * not the complete set of all properties belonging to the namespace. 1085 * 1086 * @param properties Contains the complete collection of properties which have changed for a 1087 * single namespace. This includes only those which were added, updated, 1088 * or deleted. 1089 */ onPropertiesChanged(@onNull Properties properties)1090 void onPropertiesChanged(@NonNull Properties properties); 1091 } 1092 1093 /** 1094 * Thrown by {@link #setProperties(Properties)} when a configuration is rejected. This 1095 * happens if RescueParty has identified a bad configuration and reset the namespace. 1096 * 1097 * @hide 1098 */ 1099 @SystemApi 1100 public static class BadConfigException extends Exception {} 1101 1102 /** 1103 * A mapping of properties to values, as well as a single namespace which they all belong to. 1104 * 1105 * @hide 1106 */ 1107 @SystemApi 1108 public static class Properties { 1109 private final String mNamespace; 1110 private final HashMap<String, String> mMap; 1111 private Set<String> mKeyset; 1112 1113 /** 1114 * Create a mapping of properties to values and the namespace they belong to. 1115 * 1116 * @param namespace The namespace these properties belong to. 1117 * @param keyValueMap A map between property names and property values. 1118 * @hide 1119 */ Properties(@onNull String namespace, @Nullable Map<String, String> keyValueMap)1120 public Properties(@NonNull String namespace, @Nullable Map<String, String> keyValueMap) { 1121 Preconditions.checkNotNull(namespace); 1122 mNamespace = namespace; 1123 mMap = new HashMap(); 1124 if (keyValueMap != null) { 1125 mMap.putAll(keyValueMap); 1126 } 1127 } 1128 1129 /** 1130 * @return the namespace all properties within this instance belong to. 1131 */ 1132 @NonNull getNamespace()1133 public String getNamespace() { 1134 return mNamespace; 1135 } 1136 1137 /** 1138 * @return the non-null set of property names. 1139 */ 1140 @NonNull getKeyset()1141 public Set<String> getKeyset() { 1142 if (mKeyset == null) { 1143 mKeyset = Collections.unmodifiableSet(mMap.keySet()); 1144 } 1145 return mKeyset; 1146 } 1147 1148 /** 1149 * Look up the String value of a property. 1150 * 1151 * @param name The name of the property to look up. 1152 * @param defaultValue The value to return if the property has not been defined. 1153 * @return the corresponding value, or defaultValue if none exists. 1154 */ 1155 @Nullable getString(@onNull String name, @Nullable String defaultValue)1156 public String getString(@NonNull String name, @Nullable String defaultValue) { 1157 Preconditions.checkNotNull(name); 1158 String value = mMap.get(name); 1159 return value != null ? value : defaultValue; 1160 } 1161 1162 /** 1163 * Look up the boolean value of a property. 1164 * 1165 * @param name The name of the property to look up. 1166 * @param defaultValue The value to return if the property has not been defined. 1167 * @return the corresponding value, or defaultValue if none exists. 1168 */ getBoolean(@onNull String name, boolean defaultValue)1169 public boolean getBoolean(@NonNull String name, boolean defaultValue) { 1170 Preconditions.checkNotNull(name); 1171 String value = mMap.get(name); 1172 return value != null ? Boolean.parseBoolean(value) : defaultValue; 1173 } 1174 1175 /** 1176 * Look up the int value of a property. 1177 * 1178 * @param name The name of the property to look up. 1179 * @param defaultValue The value to return if the property has not been defined or fails to 1180 * parse into an int. 1181 * @return the corresponding value, or defaultValue if no valid int is available. 1182 */ getInt(@onNull String name, int defaultValue)1183 public int getInt(@NonNull String name, int defaultValue) { 1184 Preconditions.checkNotNull(name); 1185 String value = mMap.get(name); 1186 if (value == null) { 1187 return defaultValue; 1188 } 1189 try { 1190 return Integer.parseInt(value); 1191 } catch (NumberFormatException e) { 1192 Log.e(TAG, "Parsing int failed for " + name); 1193 return defaultValue; 1194 } 1195 } 1196 1197 /** 1198 * Look up the long value of a property. 1199 * 1200 * @param name The name of the property to look up. 1201 * @param defaultValue The value to return if the property has not been defined. or fails to 1202 * parse into a long. 1203 * @return the corresponding value, or defaultValue if no valid long is available. 1204 */ getLong(@onNull String name, long defaultValue)1205 public long getLong(@NonNull String name, long defaultValue) { 1206 Preconditions.checkNotNull(name); 1207 String value = mMap.get(name); 1208 if (value == null) { 1209 return defaultValue; 1210 } 1211 try { 1212 return Long.parseLong(value); 1213 } catch (NumberFormatException e) { 1214 Log.e(TAG, "Parsing long failed for " + name); 1215 return defaultValue; 1216 } 1217 } 1218 1219 /** 1220 * Look up the int value of a property. 1221 * 1222 * @param name The name of the property to look up. 1223 * @param defaultValue The value to return if the property has not been defined. or fails to 1224 * parse into a float. 1225 * @return the corresponding value, or defaultValue if no valid float is available. 1226 */ getFloat(@onNull String name, float defaultValue)1227 public float getFloat(@NonNull String name, float defaultValue) { 1228 Preconditions.checkNotNull(name); 1229 String value = mMap.get(name); 1230 if (value == null) { 1231 return defaultValue; 1232 } 1233 try { 1234 return Float.parseFloat(value); 1235 } catch (NumberFormatException e) { 1236 Log.e(TAG, "Parsing float failed for " + name); 1237 return defaultValue; 1238 } 1239 } 1240 1241 /** 1242 * Builder class for the construction of {@link Properties} objects. 1243 */ 1244 public static final class Builder { 1245 @NonNull 1246 private final String mNamespace; 1247 @NonNull 1248 private final Map<String, String> mKeyValues = new HashMap<>(); 1249 1250 /** 1251 * Create a new Builders for the specified namespace. 1252 * @param namespace non null namespace. 1253 */ Builder(@onNull String namespace)1254 public Builder(@NonNull String namespace) { 1255 mNamespace = namespace; 1256 } 1257 1258 /** 1259 * Add a new property with the specified key and value. 1260 * @param name non null name of the property. 1261 * @param value nullable string value of the property. 1262 * @return this Builder object 1263 */ 1264 @NonNull setString(@onNull String name, @Nullable String value)1265 public Builder setString(@NonNull String name, @Nullable String value) { 1266 mKeyValues.put(name, value); 1267 return this; 1268 } 1269 1270 /** 1271 * Add a new property with the specified key and value. 1272 * @param name non null name of the property. 1273 * @param value nullable string value of the property. 1274 * @return this Builder object 1275 */ 1276 @NonNull setBoolean(@onNull String name, boolean value)1277 public Builder setBoolean(@NonNull String name, boolean value) { 1278 mKeyValues.put(name, Boolean.toString(value)); 1279 return this; 1280 } 1281 1282 /** 1283 * Add a new property with the specified key and value. 1284 * @param name non null name of the property. 1285 * @param value int value of the property. 1286 * @return this Builder object 1287 */ 1288 @NonNull setInt(@onNull String name, int value)1289 public Builder setInt(@NonNull String name, int value) { 1290 mKeyValues.put(name, Integer.toString(value)); 1291 return this; 1292 } 1293 1294 /** 1295 * Add a new property with the specified key and value. 1296 * @param name non null name of the property. 1297 * @param value long value of the property. 1298 * @return this Builder object 1299 */ 1300 @NonNull setLong(@onNull String name, long value)1301 public Builder setLong(@NonNull String name, long value) { 1302 mKeyValues.put(name, Long.toString(value)); 1303 return this; 1304 } 1305 1306 /** 1307 * Add a new property with the specified key and value. 1308 * @param name non null name of the property. 1309 * @param value float value of the property. 1310 * @return this Builder object 1311 */ 1312 @NonNull setFloat(@onNull String name, float value)1313 public Builder setFloat(@NonNull String name, float value) { 1314 mKeyValues.put(name, Float.toString(value)); 1315 return this; 1316 } 1317 1318 /** 1319 * Create a new {@link Properties} object. 1320 * @return non null Properties. 1321 */ 1322 @NonNull build()1323 public Properties build() { 1324 return new Properties(mNamespace, mKeyValues); 1325 } 1326 } 1327 } 1328 1329 } 1330