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 private static final Object sLock = new Object(); 608 @GuardedBy("sLock") 609 private static ArrayMap<OnPropertiesChangedListener, Pair<String, Executor>> sListeners = 610 new ArrayMap<>(); 611 @GuardedBy("sLock") 612 private static Map<String, Pair<ContentObserver, Integer>> sNamespaces = new HashMap<>(); 613 private static final String TAG = "DeviceConfig"; 614 615 // Should never be invoked DeviceConfig()616 private DeviceConfig() { 617 } 618 619 /** 620 * Look up the value of a property for a particular namespace. 621 * 622 * @param namespace The namespace containing the property to look up. 623 * @param name The name of the property to look up. 624 * @return the corresponding value, or null if not present. 625 * @hide 626 */ 627 @SystemApi 628 @RequiresPermission(READ_DEVICE_CONFIG) getProperty(@onNull String namespace, @NonNull String name)629 public static String getProperty(@NonNull String namespace, @NonNull String name) { 630 // Fetch all properties for the namespace at once and cache them in the local process, so we 631 // incur the cost of the IPC less often. Lookups happen much more frequently than updates, 632 // and we want to optimize the former. 633 return getProperties(namespace, name).getString(name, null); 634 } 635 636 /** 637 * Look up the values of multiple properties for a particular namespace. The lookup is atomic, 638 * such that the values of these properties cannot change between the time when the first is 639 * fetched and the time when the last is fetched. 640 * <p> 641 * Each call to {@link #setProperties(Properties)} is also atomic and ensures that either none 642 * or all of the change is picked up here, but never only part of it. 643 * 644 * @param namespace The namespace containing the properties to look up. 645 * @param names The names of properties to look up, or empty to fetch all properties for the 646 * given namespace. 647 * @return {@link Properties} object containing the requested properties. This reflects the 648 * state of these properties at the time of the lookup, and is not updated to reflect any 649 * future changes. The keyset of this Properties object will contain only the intersection 650 * of properties already set and properties requested via the names parameter. Properties 651 * that are already set but were not requested will not be contained here. Properties that 652 * are not set, but were requested will not be contained here either. 653 * @hide 654 */ 655 @SystemApi 656 @NonNull 657 @RequiresPermission(READ_DEVICE_CONFIG) getProperties(@onNull String namespace, @NonNull String ... names)658 public static Properties getProperties(@NonNull String namespace, @NonNull String ... names) { 659 ContentResolver contentResolver = ActivityThread.currentApplication().getContentResolver(); 660 return new Properties(namespace, 661 Settings.Config.getStrings(contentResolver, namespace, Arrays.asList(names))); 662 } 663 664 /** 665 * Look up the String value of a property for a particular namespace. 666 * 667 * @param namespace The namespace containing the property to look up. 668 * @param name The name of the property to look up. 669 * @param defaultValue The value to return if the property does not exist or has no non-null 670 * value. 671 * @return the corresponding value, or defaultValue if none exists. 672 * @hide 673 */ 674 @SystemApi 675 @RequiresPermission(READ_DEVICE_CONFIG) getString(@onNull String namespace, @NonNull String name, @Nullable String defaultValue)676 public static String getString(@NonNull String namespace, @NonNull String name, 677 @Nullable String defaultValue) { 678 String value = getProperty(namespace, name); 679 return value != null ? value : defaultValue; 680 } 681 682 /** 683 * Look up the boolean value of a property for a particular namespace. 684 * 685 * @param namespace The namespace containing the property to look up. 686 * @param name The name of the property to look up. 687 * @param defaultValue The value to return if the property does not exist or has no non-null 688 * value. 689 * @return the correspondfing value, or defaultValue if none exists. 690 * @hide 691 */ 692 @SystemApi 693 @RequiresPermission(READ_DEVICE_CONFIG) getBoolean(@onNull String namespace, @NonNull String name, boolean defaultValue)694 public static boolean getBoolean(@NonNull String namespace, @NonNull String name, 695 boolean defaultValue) { 696 String value = getProperty(namespace, name); 697 return value != null ? Boolean.parseBoolean(value) : defaultValue; 698 } 699 700 /** 701 * Look up the int value of a property for a particular namespace. 702 * 703 * @param namespace The namespace containing the property to look up. 704 * @param name The name of the property to look up. 705 * @param defaultValue The value to return if the property does not exist, has no non-null 706 * value, or fails to parse into an int. 707 * @return the corresponding value, or defaultValue if either none exists or it does not parse. 708 * @hide 709 */ 710 @SystemApi 711 @RequiresPermission(READ_DEVICE_CONFIG) getInt(@onNull String namespace, @NonNull String name, int defaultValue)712 public static int getInt(@NonNull String namespace, @NonNull String name, int defaultValue) { 713 String value = getProperty(namespace, name); 714 if (value == null) { 715 return defaultValue; 716 } 717 try { 718 return Integer.parseInt(value); 719 } catch (NumberFormatException e) { 720 Log.e(TAG, "Parsing integer failed for " + namespace + ":" + name); 721 return defaultValue; 722 } 723 } 724 725 /** 726 * Look up the long value of a property for a particular namespace. 727 * 728 * @param namespace The namespace containing the property to look up. 729 * @param name The name of the property to look up. 730 * @param defaultValue The value to return if the property does not exist, has no non-null 731 * value, or fails to parse into a long. 732 * @return the corresponding value, or defaultValue if either none exists or it does not parse. 733 * @hide 734 */ 735 @SystemApi 736 @RequiresPermission(READ_DEVICE_CONFIG) getLong(@onNull String namespace, @NonNull String name, long defaultValue)737 public static long getLong(@NonNull String namespace, @NonNull String name, long defaultValue) { 738 String value = getProperty(namespace, name); 739 if (value == null) { 740 return defaultValue; 741 } 742 try { 743 return Long.parseLong(value); 744 } catch (NumberFormatException e) { 745 Log.e(TAG, "Parsing long failed for " + namespace + ":" + name); 746 return defaultValue; 747 } 748 } 749 750 /** 751 * Look up the float value of a property for a particular namespace. 752 * 753 * @param namespace The namespace containing the property to look up. 754 * @param name The name of the property to look up. 755 * @param defaultValue The value to return if the property does not exist, has no non-null 756 * value, or fails to parse into a float. 757 * @return the corresponding value, or defaultValue if either none exists or it does not parse. 758 * @hide 759 */ 760 @SystemApi 761 @RequiresPermission(READ_DEVICE_CONFIG) getFloat(@onNull String namespace, @NonNull String name, float defaultValue)762 public static float getFloat(@NonNull String namespace, @NonNull String name, 763 float defaultValue) { 764 String value = getProperty(namespace, name); 765 if (value == null) { 766 return defaultValue; 767 } 768 try { 769 return Float.parseFloat(value); 770 } catch (NumberFormatException e) { 771 Log.e(TAG, "Parsing float failed for " + namespace + ":" + name); 772 return defaultValue; 773 } 774 } 775 776 /** 777 * Create a new property with the the provided name and value in the provided namespace, or 778 * update the value of such a property if it already exists. The same name can exist in multiple 779 * namespaces and might have different values in any or all namespaces. 780 * <p> 781 * The method takes an argument indicating whether to make the value the default for this 782 * property. 783 * <p> 784 * All properties stored for a particular scope can be reverted to their default values 785 * by passing the namespace to {@link #resetToDefaults(int, String)}. 786 * 787 * @param namespace The namespace containing the property to create or update. 788 * @param name The name of the property to create or update. 789 * @param value The value to store for the property. 790 * @param makeDefault Whether to make the new value the default one. 791 * @return True if the value was set, false if the storage implementation throws errors. 792 * @hide 793 * @see #resetToDefaults(int, String). 794 */ 795 @SystemApi 796 @RequiresPermission(WRITE_DEVICE_CONFIG) setProperty(@onNull String namespace, @NonNull String name, @Nullable String value, boolean makeDefault)797 public static boolean setProperty(@NonNull String namespace, @NonNull String name, 798 @Nullable String value, boolean makeDefault) { 799 ContentResolver contentResolver = ActivityThread.currentApplication().getContentResolver(); 800 return Settings.Config.putString(contentResolver, namespace, name, value, makeDefault); 801 } 802 803 /** 804 * Set all of the properties for a specific namespace. Pre-existing properties will be updated 805 * and new properties will be added if necessary. Any pre-existing properties for the specific 806 * namespace which are not part of the provided {@link Properties} object will be deleted from 807 * the namespace. These changes are all applied atomically, such that no calls to read or reset 808 * these properties can happen in the middle of this update. 809 * <p> 810 * Each call to {@link #getProperties(String, String...)} is also atomic and ensures that either 811 * none or all of this update is picked up, but never only part of it. 812 * 813 * @param properties the complete set of properties to set for a specific namespace. 814 * @throws BadConfigException if the provided properties are banned by RescueParty. 815 * @return True if the values were set, false otherwise. 816 * @hide 817 */ 818 @SystemApi 819 @RequiresPermission(WRITE_DEVICE_CONFIG) setProperties(@onNull Properties properties)820 public static boolean setProperties(@NonNull Properties properties) throws BadConfigException { 821 ContentResolver contentResolver = ActivityThread.currentApplication().getContentResolver(); 822 return Settings.Config.setStrings(contentResolver, properties.getNamespace(), 823 properties.mMap); 824 } 825 826 /** 827 * Reset properties to their default values by removing the underlying values. 828 * <p> 829 * The method accepts an optional namespace parameter. If provided, only properties set within 830 * that namespace will be reset. Otherwise, all properties will be reset. 831 * <p> 832 * Note: This method should only be used by {@link com.android.server.RescueParty}. It was 833 * designed to be used in the event of boot or crash loops caused by flag changes. It does not 834 * revert flag values to defaults - instead it removes the property entirely which causes the 835 * consumer of the flag to use hardcoded defaults upon retrieval. 836 * <p> 837 * To clear values for a namespace without removing the underlying properties, construct a 838 * {@link Properties} object with the caller's namespace and either an empty flag map, or some 839 * snapshot of flag values. Then use {@link #setProperties(Properties)} to remove all flags 840 * under the namespace, or set them to the values in the snapshot. 841 * <p> 842 * To revert values for testing, one should mock DeviceConfig using 843 * {@link com.android.server.testables.TestableDeviceConfig} where possible. Otherwise, fallback 844 * to using {@link #setProperties(Properties)} as outlined above. 845 * 846 * @param resetMode The reset mode to use. 847 * @param namespace Optionally, the specific namespace which resets will be limited to. 848 * @hide 849 * @see #setProperty(String, String, String, boolean) 850 */ 851 @SystemApi 852 @RequiresPermission(WRITE_DEVICE_CONFIG) resetToDefaults(@esetMode int resetMode, @Nullable String namespace)853 public static void resetToDefaults(@ResetMode int resetMode, @Nullable String namespace) { 854 ContentResolver contentResolver = ActivityThread.currentApplication().getContentResolver(); 855 Settings.Config.resetToDefaults(contentResolver, resetMode, namespace); 856 } 857 858 /** 859 * Disables or re-enables bulk modifications ({@link #setProperties(Properties)}) to device 860 * config values. This is intended for use during tests to prevent a sync operation clearing 861 * config values, which could influence the outcome of the tests, i.e. by changing behavior. 862 * 863 * @param syncDisabledMode the mode to use, see {@link Settings.Config#SYNC_DISABLED_MODE_NONE}, 864 * {@link Settings.Config#SYNC_DISABLED_MODE_PERSISTENT} and {@link 865 * Settings.Config#SYNC_DISABLED_MODE_UNTIL_REBOOT} 866 * 867 * @see #isSyncDisabled() 868 * @hide 869 */ 870 @RequiresPermission(WRITE_DEVICE_CONFIG) setSyncDisabled(@yncDisabledMode int syncDisabledMode)871 public static void setSyncDisabled(@SyncDisabledMode int syncDisabledMode) { 872 ContentResolver contentResolver = ActivityThread.currentApplication().getContentResolver(); 873 Settings.Config.setSyncDisabled(contentResolver, syncDisabledMode); 874 } 875 876 /** 877 * Returns the current state of sync disabling, {@code true} when disabled, {@code false} 878 * otherwise. 879 * 880 * @see #setSyncDisabled(int) 881 * @hide 882 */ 883 @RequiresPermission(WRITE_DEVICE_CONFIG) isSyncDisabled()884 public static boolean isSyncDisabled() { 885 ContentResolver contentResolver = ActivityThread.currentApplication().getContentResolver(); 886 return Settings.Config.isSyncDisabled(contentResolver); 887 } 888 889 /** 890 * Add a listener for property changes. 891 * <p> 892 * This listener will be called whenever properties in the specified namespace change. Callbacks 893 * will be made on the specified executor. Future calls to this method with the same listener 894 * will replace the old namespace and executor. Remove the listener entirely by calling 895 * {@link #removeOnPropertiesChangedListener(OnPropertiesChangedListener)}. 896 * 897 * @param namespace The namespace containing properties to monitor. 898 * @param executor The executor which will be used to run callbacks. 899 * @param onPropertiesChangedListener The listener to add. 900 * @hide 901 * @see #removeOnPropertiesChangedListener(OnPropertiesChangedListener) 902 */ 903 @SystemApi 904 @RequiresPermission(READ_DEVICE_CONFIG) addOnPropertiesChangedListener( @onNull String namespace, @NonNull @CallbackExecutor Executor executor, @NonNull OnPropertiesChangedListener onPropertiesChangedListener)905 public static void addOnPropertiesChangedListener( 906 @NonNull String namespace, 907 @NonNull @CallbackExecutor Executor executor, 908 @NonNull OnPropertiesChangedListener onPropertiesChangedListener) { 909 enforceReadPermission(ActivityThread.currentApplication().getApplicationContext(), 910 namespace); 911 synchronized (sLock) { 912 Pair<String, Executor> oldNamespace = sListeners.get(onPropertiesChangedListener); 913 if (oldNamespace == null) { 914 // Brand new listener, add it to the list. 915 sListeners.put(onPropertiesChangedListener, new Pair<>(namespace, executor)); 916 incrementNamespace(namespace); 917 } else if (namespace.equals(oldNamespace.first)) { 918 // Listener is already registered for this namespace, update executor just in case. 919 sListeners.put(onPropertiesChangedListener, new Pair<>(namespace, executor)); 920 } else { 921 // Update this listener from an old namespace to the new one. 922 decrementNamespace(sListeners.get(onPropertiesChangedListener).first); 923 sListeners.put(onPropertiesChangedListener, new Pair<>(namespace, executor)); 924 incrementNamespace(namespace); 925 } 926 } 927 } 928 929 /** 930 * Remove a listener for property changes. The listener will receive no further notification of 931 * property changes. 932 * 933 * @param onPropertiesChangedListener The listener to remove. 934 * @hide 935 * @see #addOnPropertiesChangedListener(String, Executor, OnPropertiesChangedListener) 936 */ 937 @SystemApi removeOnPropertiesChangedListener( @onNull OnPropertiesChangedListener onPropertiesChangedListener)938 public static void removeOnPropertiesChangedListener( 939 @NonNull OnPropertiesChangedListener onPropertiesChangedListener) { 940 Preconditions.checkNotNull(onPropertiesChangedListener); 941 synchronized (sLock) { 942 if (sListeners.containsKey(onPropertiesChangedListener)) { 943 decrementNamespace(sListeners.get(onPropertiesChangedListener).first); 944 sListeners.remove(onPropertiesChangedListener); 945 } 946 } 947 } 948 createNamespaceUri(@onNull String namespace)949 private static Uri createNamespaceUri(@NonNull String namespace) { 950 Preconditions.checkNotNull(namespace); 951 return CONTENT_URI.buildUpon().appendPath(namespace).build(); 952 } 953 954 /** 955 * Increment the count used to represent the number of listeners subscribed to the given 956 * namespace. If this is the first (i.e. incrementing from 0 to 1) for the given namespace, a 957 * ContentObserver is registered. 958 * 959 * @param namespace The namespace to increment the count for. 960 */ 961 @GuardedBy("sLock") incrementNamespace(@onNull String namespace)962 private static void incrementNamespace(@NonNull String namespace) { 963 Preconditions.checkNotNull(namespace); 964 Pair<ContentObserver, Integer> namespaceCount = sNamespaces.get(namespace); 965 if (namespaceCount != null) { 966 sNamespaces.put(namespace, new Pair<>(namespaceCount.first, namespaceCount.second + 1)); 967 } else { 968 // This is a new namespace, register a ContentObserver for it. 969 ContentObserver contentObserver = new ContentObserver(null) { 970 @Override 971 public void onChange(boolean selfChange, Uri uri) { 972 if (uri != null) { 973 handleChange(uri); 974 } 975 } 976 }; 977 ActivityThread.currentApplication().getContentResolver() 978 .registerContentObserver(createNamespaceUri(namespace), true, contentObserver); 979 sNamespaces.put(namespace, new Pair<>(contentObserver, 1)); 980 } 981 } 982 983 /** 984 * Decrement the count used to represent the number of listeners subscribed to the given 985 * namespace. If this is the final decrement call (i.e. decrementing from 1 to 0) for the given 986 * namespace, the ContentObserver that had been tracking it will be removed. 987 * 988 * @param namespace The namespace to decrement the count for. 989 */ 990 @GuardedBy("sLock") decrementNamespace(@onNull String namespace)991 private static void decrementNamespace(@NonNull String namespace) { 992 Preconditions.checkNotNull(namespace); 993 Pair<ContentObserver, Integer> namespaceCount = sNamespaces.get(namespace); 994 if (namespaceCount == null) { 995 // This namespace is not registered and does not need to be decremented 996 return; 997 } else if (namespaceCount.second > 1) { 998 sNamespaces.put(namespace, new Pair<>(namespaceCount.first, namespaceCount.second - 1)); 999 } else { 1000 // Decrementing a namespace to zero means we no longer need its ContentObserver. 1001 ActivityThread.currentApplication().getContentResolver() 1002 .unregisterContentObserver(namespaceCount.first); 1003 sNamespaces.remove(namespace); 1004 } 1005 } 1006 handleChange(@onNull Uri uri)1007 private static void handleChange(@NonNull Uri uri) { 1008 Preconditions.checkNotNull(uri); 1009 List<String> pathSegments = uri.getPathSegments(); 1010 // pathSegments(0) is "config" 1011 final String namespace = pathSegments.get(1); 1012 Properties.Builder propBuilder = new Properties.Builder(namespace); 1013 try { 1014 Properties allProperties = getProperties(namespace); 1015 for (int i = 2; i < pathSegments.size(); ++i) { 1016 String key = pathSegments.get(i); 1017 propBuilder.setString(key, allProperties.getString(key, null)); 1018 } 1019 } catch (SecurityException e) { 1020 // Silently failing to not crash binder or listener threads. 1021 Log.e(TAG, "OnPropertyChangedListener update failed: permission violation."); 1022 return; 1023 } 1024 Properties properties = propBuilder.build(); 1025 1026 synchronized (sLock) { 1027 for (int i = 0; i < sListeners.size(); i++) { 1028 if (namespace.equals(sListeners.valueAt(i).first)) { 1029 final OnPropertiesChangedListener listener = sListeners.keyAt(i); 1030 sListeners.valueAt(i).second.execute(() -> { 1031 listener.onPropertiesChanged(properties); 1032 }); 1033 } 1034 } 1035 } 1036 } 1037 1038 /** 1039 * Enforces READ_DEVICE_CONFIG permission if namespace is not one of public namespaces. 1040 * @hide 1041 */ enforceReadPermission(Context context, String namespace)1042 public static void enforceReadPermission(Context context, String namespace) { 1043 if (context.checkCallingOrSelfPermission(READ_DEVICE_CONFIG) 1044 != PackageManager.PERMISSION_GRANTED) { 1045 if (!PUBLIC_NAMESPACES.contains(namespace)) { 1046 throw new SecurityException("Permission denial: reading from settings requires:" 1047 + READ_DEVICE_CONFIG); 1048 } 1049 } 1050 } 1051 1052 /** 1053 * Returns list of namespaces that can be read without READ_DEVICE_CONFIG_PERMISSION; 1054 * @hide 1055 */ getPublicNamespaces()1056 public static @NonNull List<String> getPublicNamespaces() { 1057 return PUBLIC_NAMESPACES; 1058 } 1059 1060 /** 1061 * Interface for monitoring changes to properties. Implementations will receive callbacks when 1062 * properties change, including a {@link Properties} object which contains a single namespace 1063 * and all of the properties which changed for that namespace. This includes properties which 1064 * were added, updated, or deleted. This is not necessarily a complete list of all properties 1065 * belonging to the namespace, as properties which don't change are omitted. 1066 * <p> 1067 * Override {@link #onPropertiesChanged(Properties)} to handle callbacks for changes. 1068 * 1069 * @hide 1070 */ 1071 @SystemApi 1072 public interface OnPropertiesChangedListener { 1073 /** 1074 * Called when one or more properties have changed, providing a Properties object with all 1075 * of the changed properties. This object will contain only properties which have changed, 1076 * not the complete set of all properties belonging to the namespace. 1077 * 1078 * @param properties Contains the complete collection of properties which have changed for a 1079 * single namespace. This includes only those which were added, updated, 1080 * or deleted. 1081 */ onPropertiesChanged(@onNull Properties properties)1082 void onPropertiesChanged(@NonNull Properties properties); 1083 } 1084 1085 /** 1086 * Thrown by {@link #setProperties(Properties)} when a configuration is rejected. This 1087 * happens if RescueParty has identified a bad configuration and reset the namespace. 1088 * 1089 * @hide 1090 */ 1091 @SystemApi 1092 public static class BadConfigException extends Exception {} 1093 1094 /** 1095 * A mapping of properties to values, as well as a single namespace which they all belong to. 1096 * 1097 * @hide 1098 */ 1099 @SystemApi 1100 public static class Properties { 1101 private final String mNamespace; 1102 private final HashMap<String, String> mMap; 1103 private Set<String> mKeyset; 1104 1105 /** 1106 * Create a mapping of properties to values and the namespace they belong to. 1107 * 1108 * @param namespace The namespace these properties belong to. 1109 * @param keyValueMap A map between property names and property values. 1110 * @hide 1111 */ Properties(@onNull String namespace, @Nullable Map<String, String> keyValueMap)1112 public Properties(@NonNull String namespace, @Nullable Map<String, String> keyValueMap) { 1113 Preconditions.checkNotNull(namespace); 1114 mNamespace = namespace; 1115 mMap = new HashMap(); 1116 if (keyValueMap != null) { 1117 mMap.putAll(keyValueMap); 1118 } 1119 } 1120 1121 /** 1122 * @return the namespace all properties within this instance belong to. 1123 */ 1124 @NonNull getNamespace()1125 public String getNamespace() { 1126 return mNamespace; 1127 } 1128 1129 /** 1130 * @return the non-null set of property names. 1131 */ 1132 @NonNull getKeyset()1133 public Set<String> getKeyset() { 1134 if (mKeyset == null) { 1135 mKeyset = Collections.unmodifiableSet(mMap.keySet()); 1136 } 1137 return mKeyset; 1138 } 1139 1140 /** 1141 * Look up the String value of a property. 1142 * 1143 * @param name The name of the property to look up. 1144 * @param defaultValue The value to return if the property has not been defined. 1145 * @return the corresponding value, or defaultValue if none exists. 1146 */ 1147 @Nullable getString(@onNull String name, @Nullable String defaultValue)1148 public String getString(@NonNull String name, @Nullable String defaultValue) { 1149 Preconditions.checkNotNull(name); 1150 String value = mMap.get(name); 1151 return value != null ? value : defaultValue; 1152 } 1153 1154 /** 1155 * Look up the boolean value of a property. 1156 * 1157 * @param name The name of the property to look up. 1158 * @param defaultValue The value to return if the property has not been defined. 1159 * @return the corresponding value, or defaultValue if none exists. 1160 */ getBoolean(@onNull String name, boolean defaultValue)1161 public boolean getBoolean(@NonNull String name, boolean defaultValue) { 1162 Preconditions.checkNotNull(name); 1163 String value = mMap.get(name); 1164 return value != null ? Boolean.parseBoolean(value) : defaultValue; 1165 } 1166 1167 /** 1168 * Look up the int value of a property. 1169 * 1170 * @param name The name of the property to look up. 1171 * @param defaultValue The value to return if the property has not been defined or fails to 1172 * parse into an int. 1173 * @return the corresponding value, or defaultValue if no valid int is available. 1174 */ getInt(@onNull String name, int defaultValue)1175 public int getInt(@NonNull String name, int defaultValue) { 1176 Preconditions.checkNotNull(name); 1177 String value = mMap.get(name); 1178 if (value == null) { 1179 return defaultValue; 1180 } 1181 try { 1182 return Integer.parseInt(value); 1183 } catch (NumberFormatException e) { 1184 Log.e(TAG, "Parsing int failed for " + name); 1185 return defaultValue; 1186 } 1187 } 1188 1189 /** 1190 * Look up the long value of a property. 1191 * 1192 * @param name The name of the property to look up. 1193 * @param defaultValue The value to return if the property has not been defined. or fails to 1194 * parse into a long. 1195 * @return the corresponding value, or defaultValue if no valid long is available. 1196 */ getLong(@onNull String name, long defaultValue)1197 public long getLong(@NonNull String name, long defaultValue) { 1198 Preconditions.checkNotNull(name); 1199 String value = mMap.get(name); 1200 if (value == null) { 1201 return defaultValue; 1202 } 1203 try { 1204 return Long.parseLong(value); 1205 } catch (NumberFormatException e) { 1206 Log.e(TAG, "Parsing long failed for " + name); 1207 return defaultValue; 1208 } 1209 } 1210 1211 /** 1212 * Look up the int value of a property. 1213 * 1214 * @param name The name of the property to look up. 1215 * @param defaultValue The value to return if the property has not been defined. or fails to 1216 * parse into a float. 1217 * @return the corresponding value, or defaultValue if no valid float is available. 1218 */ getFloat(@onNull String name, float defaultValue)1219 public float getFloat(@NonNull String name, float defaultValue) { 1220 Preconditions.checkNotNull(name); 1221 String value = mMap.get(name); 1222 if (value == null) { 1223 return defaultValue; 1224 } 1225 try { 1226 return Float.parseFloat(value); 1227 } catch (NumberFormatException e) { 1228 Log.e(TAG, "Parsing float failed for " + name); 1229 return defaultValue; 1230 } 1231 } 1232 1233 /** 1234 * Builder class for the construction of {@link Properties} objects. 1235 */ 1236 public static final class Builder { 1237 @NonNull 1238 private final String mNamespace; 1239 @NonNull 1240 private final Map<String, String> mKeyValues = new HashMap<>(); 1241 1242 /** 1243 * Create a new Builders for the specified namespace. 1244 * @param namespace non null namespace. 1245 */ Builder(@onNull String namespace)1246 public Builder(@NonNull String namespace) { 1247 mNamespace = namespace; 1248 } 1249 1250 /** 1251 * Add a new property with the specified key and value. 1252 * @param name non null name of the property. 1253 * @param value nullable string value of the property. 1254 * @return this Builder object 1255 */ 1256 @NonNull setString(@onNull String name, @Nullable String value)1257 public Builder setString(@NonNull String name, @Nullable String value) { 1258 mKeyValues.put(name, value); 1259 return this; 1260 } 1261 1262 /** 1263 * Add a new property with the specified key and value. 1264 * @param name non null name of the property. 1265 * @param value nullable string value of the property. 1266 * @return this Builder object 1267 */ 1268 @NonNull setBoolean(@onNull String name, boolean value)1269 public Builder setBoolean(@NonNull String name, boolean value) { 1270 mKeyValues.put(name, Boolean.toString(value)); 1271 return this; 1272 } 1273 1274 /** 1275 * Add a new property with the specified key and value. 1276 * @param name non null name of the property. 1277 * @param value int value of the property. 1278 * @return this Builder object 1279 */ 1280 @NonNull setInt(@onNull String name, int value)1281 public Builder setInt(@NonNull String name, int value) { 1282 mKeyValues.put(name, Integer.toString(value)); 1283 return this; 1284 } 1285 1286 /** 1287 * Add a new property with the specified key and value. 1288 * @param name non null name of the property. 1289 * @param value long value of the property. 1290 * @return this Builder object 1291 */ 1292 @NonNull setLong(@onNull String name, long value)1293 public Builder setLong(@NonNull String name, long value) { 1294 mKeyValues.put(name, Long.toString(value)); 1295 return this; 1296 } 1297 1298 /** 1299 * Add a new property with the specified key and value. 1300 * @param name non null name of the property. 1301 * @param value float value of the property. 1302 * @return this Builder object 1303 */ 1304 @NonNull setFloat(@onNull String name, float value)1305 public Builder setFloat(@NonNull String name, float value) { 1306 mKeyValues.put(name, Float.toString(value)); 1307 return this; 1308 } 1309 1310 /** 1311 * Create a new {@link Properties} object. 1312 * @return non null Properties. 1313 */ 1314 @NonNull build()1315 public Properties build() { 1316 return new Properties(mNamespace, mKeyValues); 1317 } 1318 } 1319 } 1320 1321 } 1322