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.WRITE_ALLOWLISTED_DEVICE_CONFIG; 20 import static android.Manifest.permission.READ_DEVICE_CONFIG; 21 import static android.Manifest.permission.WRITE_DEVICE_CONFIG; 22 import static android.Manifest.permission.READ_WRITE_SYNC_DISABLED_MODE_CONFIG; 23 import static android.Manifest.permission.DUMP; 24 25 import android.Manifest; 26 import android.annotation.CallbackExecutor; 27 import android.annotation.FlaggedApi; 28 import android.annotation.IntDef; 29 import android.annotation.NonNull; 30 import android.annotation.Nullable; 31 import android.annotation.RequiresPermission; 32 import android.annotation.SuppressLint; 33 import android.annotation.SystemApi; 34 import android.content.ContentResolver; 35 import android.database.ContentObserver; 36 import android.net.Uri; 37 import android.os.Binder; 38 import android.os.IBinder; 39 import android.os.ParcelFileDescriptor; 40 import android.provider.DeviceConfigServiceManager; 41 import android.provider.DeviceConfigInitializer; 42 import android.provider.aidl.IDeviceConfigManager; 43 import android.provider.flags.Flags; 44 import android.ravenwood.annotation.RavenwoodKeepWholeClass; 45 import android.ravenwood.annotation.RavenwoodRedirect; 46 import android.ravenwood.annotation.RavenwoodRedirectionClass; 47 import android.ravenwood.annotation.RavenwoodThrow; 48 import android.util.ArrayMap; 49 import android.util.ArraySet; 50 import android.util.Log; 51 import android.util.Pair; 52 import android.util.Slog; 53 54 import com.android.internal.annotations.GuardedBy; 55 import com.android.modules.utils.build.SdkLevel; 56 57 import java.io.FileDescriptor; 58 import java.io.PrintWriter; 59 import java.lang.annotation.ElementType; 60 import java.lang.annotation.Retention; 61 import java.lang.annotation.RetentionPolicy; 62 import java.lang.annotation.Target; 63 64 import java.util.Arrays; 65 import java.util.Collections; 66 import java.util.Comparator; 67 import java.util.HashMap; 68 import java.util.HashSet; 69 import java.util.List; 70 import java.util.Map; 71 import java.util.Objects; 72 import java.util.Set; 73 import java.util.TreeMap; 74 import java.util.TreeSet; 75 import java.util.concurrent.Executor; 76 77 /** 78 * Device level configuration parameters which can be tuned by a separate configuration service. 79 * Namespaces that end in "_native" such as {@link #NAMESPACE_NETD_NATIVE} are intended to be used 80 * by native code and should be pushed to system properties to make them accessible. 81 * 82 * @hide 83 */ 84 @SystemApi 85 @RavenwoodKeepWholeClass 86 @RavenwoodRedirectionClass("DeviceConfig_host") 87 public final class DeviceConfig { 88 89 /** 90 * The name of the service that provides the logic to these APIs 91 * 92 * @hide 93 */ 94 public static final String SERVICE_NAME = "device_config_updatable"; 95 96 /** 97 * Namespace for all accessibility related features. 98 * 99 * @hide 100 */ 101 @SystemApi 102 public static final String NAMESPACE_ACCESSIBILITY = "accessibility"; 103 104 /** 105 * Namespace for activity manager related features. These features will be applied 106 * immediately upon change. 107 * 108 * @hide 109 */ 110 @SystemApi 111 public static final String NAMESPACE_ACTIVITY_MANAGER = "activity_manager"; 112 113 /** 114 * Namespace for activity manager, specific to the "component alias" feature. We needed a 115 * different namespace in order to avoid phonetype from resetting it. 116 * @hide 117 */ 118 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 119 public static final String NAMESPACE_ACTIVITY_MANAGER_COMPONENT_ALIAS = "activity_manager_ca"; 120 121 /** 122 * Namespace for features related to auto pin confirmation. 123 * 124 * @hide 125 */ 126 @SystemApi 127 public static final String NAMESPACE_AUTO_PIN_CONFIRMATION = "auto_pin_confirmation"; 128 129 /** 130 * Namespace for all activity manager related features that are used at the native level. 131 * These features are applied at reboot. 132 * 133 * @hide 134 */ 135 @SystemApi 136 public static final String NAMESPACE_ACTIVITY_MANAGER_NATIVE_BOOT = 137 "activity_manager_native_boot"; 138 139 /** 140 * Namespace for AlarmManager configurations. 141 * 142 * @hide 143 */ 144 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 145 public static final String NAMESPACE_ALARM_MANAGER = "alarm_manager"; 146 147 /** 148 * Namespace for all app compat related features. These features will be applied 149 * immediately upon change. 150 * 151 * @hide 152 */ 153 @SystemApi 154 public static final String NAMESPACE_APP_COMPAT = "app_compat"; 155 156 /** 157 * Namespace for all app hibernation related features. 158 * @hide 159 */ 160 @SystemApi 161 public static final String NAMESPACE_APP_HIBERNATION = "app_hibernation"; 162 163 /** 164 * Namespace for all AppSearch related features. 165 * @hide 166 */ 167 @SystemApi 168 public static final String NAMESPACE_APPSEARCH = "appsearch"; 169 170 /** 171 * Namespace for app standby configurations. 172 * 173 * @hide 174 */ 175 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 176 public static final String NAMESPACE_APP_STANDBY = "app_standby"; 177 178 /** 179 * Namespace for all App Cloning related features. 180 * @hide 181 */ 182 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 183 public static final String NAMESPACE_APP_CLONING = "app_cloning"; 184 185 /** 186 * Namespace for AttentionManagerService related features. 187 * 188 * @hide 189 */ 190 @SystemApi 191 public static final String NAMESPACE_ATTENTION_MANAGER_SERVICE = "attention_manager_service"; 192 193 /** 194 * Namespace for autofill feature that provides suggestions across all apps when 195 * the user interacts with input fields. 196 * 197 * @hide 198 */ 199 @SystemApi 200 public static final String NAMESPACE_AUTOFILL = "autofill"; 201 202 /** 203 * Namespace for battery saver feature. 204 * 205 * @hide 206 */ 207 @SystemApi 208 public static final String NAMESPACE_BATTERY_SAVER = "battery_saver"; 209 210 /** 211 * Namespace for holding battery stats configuration. 212 * 213 * @hide 214 */ 215 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 216 public static final String NAMESPACE_BATTERY_STATS = "battery_stats"; 217 218 /** 219 * Namespace for blobstore feature that allows apps to share data blobs. 220 * 221 * @hide 222 */ 223 @SystemApi 224 public static final String NAMESPACE_BLOBSTORE = "blobstore"; 225 226 /** 227 * Namespace for all Bluetooth related features. 228 * 229 * @hide 230 */ 231 @SystemApi 232 public static final String NAMESPACE_BLUETOOTH = "bluetooth"; 233 234 /** 235 * Namespace for features relating to android core experiments team internal usage. 236 * 237 * @hide 238 */ 239 @SystemApi 240 public static final String NAMESPACE_CORE_EXPERIMENTS_TEAM_INTERNAL = "core_experiments_team_internal"; 241 242 /** 243 * Namespace for all camera-related features that are used at the native level. 244 * 245 * @hide 246 */ 247 @SystemApi 248 public static final String NAMESPACE_CAMERA_NATIVE = "camera_native"; 249 250 /** 251 * Namespace for cellular security related features. 252 * 253 * @hide 254 */ 255 @SystemApi 256 public static final String NAMESPACE_CELLULAR_SECURITY = "cellular_security"; 257 258 /** 259 * Namespace for features relating to clipboard. 260 * 261 * @hide 262 */ 263 @SystemApi 264 public static final String NAMESPACE_CLIPBOARD = "clipboard"; 265 266 /** 267 * Namespace for all networking connectivity related features. 268 * 269 * @hide 270 */ 271 @SystemApi 272 public static final String NAMESPACE_CONNECTIVITY = "connectivity"; 273 274 /** 275 * Namespace for CaptivePortalLogin module. 276 * 277 * @hide 278 */ 279 @SystemApi 280 public static final String NAMESPACE_CAPTIVEPORTALLOGIN = "captive_portal_login"; 281 282 /** 283 * Namespace for all EdgeTpu related features. 284 * 285 * @hide 286 */ 287 @SystemApi 288 public static final String NAMESPACE_EDGETPU_NATIVE = "edgetpu_native"; 289 290 /** 291 * Namespace for all HealthFitness related features. 292 * 293 * @hide 294 */ 295 @SystemApi 296 public static final String NAMESPACE_HEALTH_FITNESS = "health_fitness"; 297 298 /** 299 * Namespace for Tethering module. 300 * 301 * @hide 302 */ 303 @SystemApi 304 public static final String NAMESPACE_TETHERING = "tethering"; 305 306 307 /** 308 * Namespace for Nearby module. 309 * 310 * @hide 311 */ 312 @SystemApi 313 public static final String NAMESPACE_NEARBY = "nearby"; 314 315 /** 316 * Namespace for content capture feature used by on-device machine intelligence 317 * to provide suggestions in a privacy-safe manner. 318 * 319 * @hide 320 */ 321 @SystemApi 322 public static final String NAMESPACE_CONTENT_CAPTURE = "content_capture"; 323 324 /** 325 * Namespace for credential manager. 326 * 327 * @hide 328 */ 329 @SystemApi 330 public static final String NAMESPACE_CREDENTIAL = "credential_manager"; 331 332 /** 333 * Namespace for device idle configurations. 334 * 335 * @hide 336 */ 337 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 338 public static final String NAMESPACE_DEVICE_IDLE = "device_idle"; 339 340 /** 341 * Namespace for how dex runs. The feature requires a reboot to reach a clean state. 342 * 343 * @deprecated No longer used 344 * @hide 345 */ 346 @Deprecated 347 @SystemApi 348 public static final String NAMESPACE_DEX_BOOT = "dex_boot"; 349 350 /** 351 * Namespace for display manager related features. The names to access the properties in this 352 * namespace should be defined in {@link android.hardware.display.DisplayManager}. 353 * 354 * @hide 355 */ 356 @SystemApi 357 public static final String NAMESPACE_DISPLAY_MANAGER = "display_manager"; 358 359 /** 360 * Namespace for all Game Driver features. 361 * 362 * @hide 363 */ 364 @SystemApi 365 public static final String NAMESPACE_GAME_DRIVER = "game_driver"; 366 367 /** 368 * Namespace for all HDMI Control features. 369 * 370 * @hide 371 */ 372 @SystemApi 373 public static final String NAMESPACE_HDMI_CONTROL = "hdmi_control"; 374 375 /** 376 * Namespace for all input-related features that are used at the native level. 377 * These features are applied at reboot. 378 * 379 * @hide 380 */ 381 @SystemApi 382 public static final String NAMESPACE_INPUT_NATIVE_BOOT = "input_native_boot"; 383 384 /** 385 * Namespace for attention-based features provided by on-device machine intelligence. 386 * 387 * @hide 388 */ 389 @SystemApi 390 public static final String NAMESPACE_INTELLIGENCE_ATTENTION = "intelligence_attention"; 391 392 /** 393 * Definitions for properties related to Content Suggestions. 394 * 395 * @hide 396 */ 397 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 398 public static final String NAMESPACE_INTELLIGENCE_CONTENT_SUGGESTIONS = 399 "intelligence_content_suggestions"; 400 401 /** 402 * Namespace for JobScheduler configurations. 403 * @hide 404 */ 405 @SystemApi 406 public static final String NAMESPACE_JOB_SCHEDULER = "jobscheduler"; 407 408 /** 409 * Namespace for all lmkd related features. 410 * 411 * @hide 412 */ 413 @SystemApi 414 public static final String NAMESPACE_LMKD_NATIVE = "lmkd_native"; 415 416 /** 417 * Namespace for all location related features. 418 * 419 * @hide 420 */ 421 @SystemApi 422 public static final String NAMESPACE_LOCATION = "location"; 423 424 /** 425 * Namespace for all media related features. 426 * 427 * @hide 428 */ 429 @SystemApi 430 public static final String NAMESPACE_MEDIA = "media"; 431 432 /** 433 * Namespace for all media native related features. 434 * 435 * @hide 436 */ 437 @SystemApi 438 public static final String NAMESPACE_MEDIA_NATIVE = "media_native"; 439 440 /** 441 * Namespace for all Kernel Multi-Gen LRU feature. 442 * 443 * @hide 444 */ 445 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 446 public static final String NAMESPACE_MGLRU_NATIVE = "mglru_native"; 447 448 /** 449 * Namespace for all memory management related features. 450 * 451 * @hide 452 */ 453 @SystemApi 454 @FlaggedApi(Flags.FLAG_MMD_DEVICE_CONFIG) 455 public static final String NAMESPACE_MM = "mm"; 456 457 /** 458 * Namespace for all mmd native related features. 459 * 460 * @hide 461 */ 462 @SystemApi 463 @FlaggedApi(Flags.FLAG_MMD_DEVICE_CONFIG) 464 public static final String NAMESPACE_MMD_NATIVE = "mmd_native"; 465 466 /** 467 * Namespace for all netd related features. 468 * 469 * @hide 470 */ 471 @SystemApi 472 public static final String NAMESPACE_NETD_NATIVE = "netd_native"; 473 474 /** 475 * Namespace for all Android NNAPI related features. 476 * 477 * @hide 478 */ 479 @SystemApi 480 public static final String NAMESPACE_NNAPI_NATIVE = "nnapi_native"; 481 482 /** 483 * Namespace for all OnDevicePersonalization related feature. 484 * @hide 485 */ 486 @SystemApi 487 public static final String NAMESPACE_ON_DEVICE_PERSONALIZATION = "on_device_personalization"; 488 489 /** 490 * Namespace for features related to the Package Manager Service. 491 * 492 * @hide 493 */ 494 @SystemApi 495 public static final String NAMESPACE_PACKAGE_MANAGER_SERVICE = "package_manager_service"; 496 497 /** 498 * Namespace for features related to the Profcollect native Service. 499 * These features are applied at reboot. 500 * 501 * @hide 502 */ 503 @SystemApi 504 public static final String NAMESPACE_PROFCOLLECT_NATIVE_BOOT = "profcollect_native_boot"; 505 506 /** 507 * Namespace for features related to Reboot Readiness detection. 508 * 509 * @hide 510 */ 511 @SystemApi 512 public static final String NAMESPACE_REBOOT_READINESS = "reboot_readiness"; 513 514 /** 515 * Namespace for Remote Key Provisioning related features. 516 * 517 * @hide 518 */ 519 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 520 public static final String NAMESPACE_REMOTE_KEY_PROVISIONING_NATIVE = 521 "remote_key_provisioning_native"; 522 523 /** 524 * Namespace for Rollback flags that are applied immediately. 525 * 526 * @hide 527 */ 528 @SystemApi 529 public static final String NAMESPACE_ROLLBACK = "rollback"; 530 531 /** 532 * Namespace for Rollback flags that are applied after a reboot. 533 * 534 * @hide 535 */ 536 @SystemApi 537 public static final String NAMESPACE_ROLLBACK_BOOT = "rollback_boot"; 538 539 /** 540 * Namespace for Rotation Resolver Manager Service. 541 * 542 * @hide 543 */ 544 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 545 public static final String NAMESPACE_ROTATION_RESOLVER = "rotation_resolver"; 546 547 /** 548 * Namespace for all runtime related features that don't require a reboot to become active. 549 * There are no feature flags using NAMESPACE_RUNTIME. 550 * 551 * @hide 552 */ 553 @SystemApi 554 public static final String NAMESPACE_RUNTIME = "runtime"; 555 556 /** 557 * Namespace for all runtime related features that require system properties for accessing 558 * the feature flags from C++ or Java language code. One example is the app image startup 559 * cache feature use_app_image_startup_cache. 560 * 561 * @hide 562 */ 563 @SystemApi 564 public static final String NAMESPACE_RUNTIME_NATIVE = "runtime_native"; 565 566 /** 567 * Namespace for all runtime native boot related features. Boot in this case refers to the 568 * fact that the properties only take effect after rebooting the device. 569 * 570 * @hide 571 */ 572 @SystemApi 573 public static final String NAMESPACE_RUNTIME_NATIVE_BOOT = "runtime_native_boot"; 574 575 /** 576 * Namespace for system scheduler related features. These features will be applied 577 * immediately upon change. 578 * 579 * @hide 580 */ 581 @SystemApi 582 public static final String NAMESPACE_SCHEDULER = "scheduler"; 583 584 /** 585 * Namespace for all SdkSandbox related features. 586 * @hide 587 */ 588 @SystemApi 589 public static final String NAMESPACE_SDK_SANDBOX = "sdk_sandbox"; 590 591 /** 592 * Namespace for settings statistics features. 593 * 594 * @hide 595 */ 596 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 597 public static final String NAMESPACE_SETTINGS_STATS = "settings_stats"; 598 599 /** 600 * Namespace for all statsd java features that can be applied immediately. 601 * 602 * @hide 603 */ 604 @SystemApi 605 public static final String NAMESPACE_STATSD_JAVA = "statsd_java"; 606 607 /** 608 * Namespace for all statsd java features that are applied on boot. 609 * 610 * @hide 611 */ 612 @SystemApi 613 public static final String NAMESPACE_STATSD_JAVA_BOOT = "statsd_java_boot"; 614 615 /** 616 * Namespace for all statsd native features that can be applied immediately. 617 * 618 * @hide 619 */ 620 @SystemApi 621 public static final String NAMESPACE_STATSD_NATIVE = "statsd_native"; 622 623 /** 624 * Namespace for all statsd native features that are applied on boot. 625 * 626 * @hide 627 */ 628 @SystemApi 629 public static final String NAMESPACE_STATSD_NATIVE_BOOT = "statsd_native_boot"; 630 631 /** 632 * Namespace for storage-related features. 633 * 634 * @deprecated Replace storage namespace with storage_native_boot. 635 * @hide 636 */ 637 @Deprecated 638 @SystemApi 639 public static final String NAMESPACE_STORAGE = "storage"; 640 641 /** 642 * Namespace for storage-related features, including native and boot. 643 * 644 * @hide 645 */ 646 @SystemApi 647 public static final String NAMESPACE_STORAGE_NATIVE_BOOT = "storage_native_boot"; 648 649 /** 650 * Namespace for all AdServices related features. 651 * @hide 652 */ 653 @SystemApi 654 public static final String NAMESPACE_ADSERVICES = "adservices"; 655 656 /** 657 * Namespace for all SurfaceFlinger features that are used at the native level. 658 * These features are applied on boot or after reboot. 659 * 660 * @hide 661 */ 662 @SystemApi 663 public static final String NAMESPACE_SURFACE_FLINGER_NATIVE_BOOT = 664 "surface_flinger_native_boot"; 665 666 /** 667 * Namespace for swcodec native related features. 668 * 669 * @hide 670 */ 671 @SystemApi 672 public static final String NAMESPACE_SWCODEC_NATIVE = "swcodec_native"; 673 674 675 /** 676 * Namespace for System UI related features. 677 * 678 * @hide 679 */ 680 @SystemApi 681 public static final String NAMESPACE_SYSTEMUI = "systemui"; 682 683 /** 684 * Namespace for system time and time zone detection related features / behavior. 685 * 686 * @hide 687 */ 688 @SystemApi 689 public static final String NAMESPACE_SYSTEM_TIME = "system_time"; 690 691 /** 692 * Namespace for TARE configurations. 693 * 694 * @hide 695 */ 696 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 697 public static final String NAMESPACE_TARE = "tare"; 698 699 /** 700 * Telephony related properties. 701 * 702 * @hide 703 */ 704 @SystemApi 705 public static final String NAMESPACE_TELEPHONY = "telephony"; 706 707 /** 708 * Namespace for TextClassifier related features. 709 * 710 * @hide 711 * @see android.provider.Settings.Global.TEXT_CLASSIFIER_CONSTANTS 712 */ 713 @SystemApi 714 public static final String NAMESPACE_TEXTCLASSIFIER = "textclassifier"; 715 716 /** 717 * Namespace for contacts provider related features. 718 * 719 * @hide 720 */ 721 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 722 public static final String NAMESPACE_CONTACTS_PROVIDER = "contacts_provider"; 723 724 /** 725 * Namespace for settings ui related features 726 * 727 * @hide 728 */ 729 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 730 public static final String NAMESPACE_SETTINGS_UI = "settings_ui"; 731 732 /** 733 * Namespace for android related features, i.e. for flags that affect not just a single 734 * component, but the entire system. 735 * 736 * The keys for this namespace are defined in {@link AndroidDeviceConfig}. 737 * 738 * @hide 739 */ 740 @SystemApi 741 public static final String NAMESPACE_ANDROID = "android"; 742 743 /** 744 * Namespace for window manager related features. 745 * 746 * @hide 747 */ 748 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 749 public static final String NAMESPACE_WINDOW_MANAGER = "window_manager"; 750 751 /** 752 * Namespace for window manager features accessible by native code and 753 * loaded once per boot. 754 * 755 * @hide 756 */ 757 @SystemApi 758 public static final String NAMESPACE_WINDOW_MANAGER_NATIVE_BOOT = "window_manager_native_boot"; 759 760 /** 761 * Definitions for selection toolbar related functions. 762 * 763 * @hide 764 */ 765 @SystemApi 766 public static final String NAMESPACE_SELECTION_TOOLBAR = "selection_toolbar"; 767 768 /** 769 * Definitions for voice interaction related functions. 770 * 771 * @hide 772 */ 773 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 774 public static final String NAMESPACE_VOICE_INTERACTION = "voice_interaction"; 775 776 /** 777 * Namespace for DevicePolicyManager related features. 778 * 779 * @hide 780 */ 781 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 782 public static final String NAMESPACE_DEVICE_POLICY_MANAGER = 783 "device_policy_manager"; 784 785 /** 786 * List of namespaces which can be read without READ_DEVICE_CONFIG permission 787 * 788 * @hide 789 */ 790 @NonNull 791 private static final List<String> PUBLIC_NAMESPACES = 792 Arrays.asList(NAMESPACE_TEXTCLASSIFIER, NAMESPACE_RUNTIME, NAMESPACE_STATSD_JAVA, 793 NAMESPACE_STATSD_JAVA_BOOT, NAMESPACE_SELECTION_TOOLBAR, NAMESPACE_AUTOFILL, 794 NAMESPACE_DEVICE_POLICY_MANAGER, NAMESPACE_CONTENT_CAPTURE); 795 /** 796 * Privacy related properties definitions. 797 * 798 * @hide 799 */ 800 @SystemApi 801 public static final String NAMESPACE_PRIVACY = "privacy"; 802 803 /** 804 * Namespace for biometrics related features 805 * 806 * @hide 807 */ 808 @SystemApi 809 public static final String NAMESPACE_BIOMETRICS = "biometrics"; 810 811 /** 812 * Permission related properties definitions. 813 * 814 * @hide 815 */ 816 @SystemApi 817 public static final String NAMESPACE_PERMISSIONS = "permissions"; 818 819 /** 820 * Namespace for ota related features. 821 * 822 * @hide 823 */ 824 @SystemApi 825 public static final String NAMESPACE_OTA = "ota"; 826 827 /** 828 * Namespace for all widget related features. 829 * 830 * @hide 831 */ 832 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 833 public static final String NAMESPACE_WIDGET = "widget"; 834 835 /** 836 * Namespace for connectivity thermal power manager features. 837 * 838 * @hide 839 */ 840 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 841 public static final String NAMESPACE_CONNECTIVITY_THERMAL_POWER_MANAGER = 842 "connectivity_thermal_power_manager"; 843 844 /** 845 * Namespace for configuration related features. 846 * 847 * @hide 848 */ 849 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 850 public static final String NAMESPACE_CONFIGURATION = "configuration"; 851 852 /** 853 * LatencyTracker properties definitions. 854 * 855 * @hide 856 */ 857 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 858 public static final String NAMESPACE_LATENCY_TRACKER = "latency_tracker"; 859 860 /** 861 * InteractionJankMonitor properties definitions. 862 * 863 * @hide 864 */ 865 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 866 @SuppressLint("IntentName") 867 public static final String NAMESPACE_INTERACTION_JANK_MONITOR = "interaction_jank_monitor"; 868 869 /** 870 * Namespace for game overlay related features. 871 * 872 * @hide 873 */ 874 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 875 public static final String NAMESPACE_GAME_OVERLAY = "game_overlay"; 876 877 /** 878 * Namespace for Android Virtualization Framework related features accessible by native code. 879 * 880 * @hide 881 */ 882 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 883 public static final String NAMESPACE_VIRTUALIZATION_FRAMEWORK_NATIVE = 884 "virtualization_framework_native"; 885 886 /** 887 * Namespace for Constrain Display APIs related features. 888 * 889 * @hide 890 */ 891 @SystemApi 892 public static final String NAMESPACE_CONSTRAIN_DISPLAY_APIS = "constrain_display_apis"; 893 894 /** 895 * Namespace for App Compat Overrides related features. 896 * 897 * @hide 898 */ 899 @SystemApi 900 public static final String NAMESPACE_APP_COMPAT_OVERRIDES = "app_compat_overrides"; 901 902 /** 903 * Namespace for all ultra wideband (uwb) related features. 904 * 905 * @hide 906 */ 907 @SystemApi 908 public static final String NAMESPACE_UWB = "uwb"; 909 910 /** 911 * Namespace for AmbientContextEventManagerService related features. 912 * 913 * @hide 914 */ 915 @SystemApi 916 public static final String NAMESPACE_AMBIENT_CONTEXT_MANAGER_SERVICE = 917 "ambient_context_manager_service"; 918 919 /** 920 * Namespace for WearableSensingManagerService related features. 921 * 922 * @hide 923 */ 924 @SystemApi 925 public static final String NAMESPACE_WEARABLE_SENSING = 926 "wearable_sensing"; 927 928 /** 929 * Namespace for Vendor System Native related features. 930 * 931 * @hide 932 */ 933 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 934 public static final String NAMESPACE_VENDOR_SYSTEM_NATIVE = "vendor_system_native"; 935 936 /** 937 * Namespace for Vendor System Native Boot related features. 938 * 939 * @hide 940 */ 941 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 942 public static final String NAMESPACE_VENDOR_SYSTEM_NATIVE_BOOT = "vendor_system_native_boot"; 943 944 /** 945 * Namespace for memory safety related features (e.g. MTE) that need a reboot to be applied 946 * 947 * @hide 948 */ 949 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 950 public static final String NAMESPACE_MEMORY_SAFETY_NATIVE_BOOT = "memory_safety_native_boot"; 951 952 /** 953 * Namespace for memory safety related features (e.g. MTE) 954 * 955 * @hide 956 */ 957 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 958 public static final String NAMESPACE_MEMORY_SAFETY_NATIVE = "memory_safety_native"; 959 960 /** 961 * Namespace for wear OS platform features. 962 * 963 * @hide 964 */ 965 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 966 public static final String NAMESPACE_WEAR = "wear"; 967 968 /** 969 * Namespace for the input method manager platform features. 970 * 971 * @hide 972 */ 973 @SystemApi 974 public static final String NAMESPACE_INPUT_METHOD_MANAGER = "input_method_manager"; 975 976 /** 977 * Namespace for backup and restore service related features. 978 * 979 * @hide 980 */ 981 @SystemApi 982 public static final String NAMESPACE_BACKUP_AND_RESTORE = "backup_and_restore"; 983 984 /** 985 * Namespace for ARC App Compat related features. 986 * 987 * @hide 988 */ 989 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 990 public static final String NAMESPACE_ARC_APP_COMPAT = "arc_app_compat"; 991 992 /** 993 * Namespace for remote authentication features. 994 * 995 * @hide 996 */ 997 @SystemApi 998 public static final String NAMESPACE_REMOTE_AUTH = "remote_auth"; 999 1000 1001 /** 1002 * Namespace for tethering module native features. 1003 * Flags defined in this namespace are only usable on 1004 * {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} and newer. 1005 * On older Android releases, they will not be propagated to native code. 1006 * 1007 * @hide 1008 */ 1009 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 1010 public static final String NAMESPACE_TETHERING_NATIVE = 1011 "tethering_u_or_later_native"; 1012 1013 /** 1014 * Namespace for all near field communication (nfc) related features. 1015 * 1016 * @hide 1017 */ 1018 @SystemApi 1019 public static final String NAMESPACE_NFC = "nfc"; 1020 1021 /** 1022 * The modes that can be used when disabling syncs to the 'config' settings. 1023 * @hide 1024 */ 1025 @IntDef(prefix = "SYNC_DISABLED_MODE_", 1026 value = { SYNC_DISABLED_MODE_NONE, SYNC_DISABLED_MODE_PERSISTENT, 1027 SYNC_DISABLED_MODE_UNTIL_REBOOT }) 1028 @Retention(RetentionPolicy.SOURCE) 1029 @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE}) 1030 public @interface SyncDisabledMode {} 1031 1032 /** 1033 * Sync is not disabled. 1034 * 1035 * @hide 1036 */ 1037 @SystemApi 1038 public static final int SYNC_DISABLED_MODE_NONE = 0; 1039 1040 /** 1041 * Disabling of Config bulk update / syncing is persistent, i.e. it survives a device 1042 * reboot. 1043 * 1044 * @hide 1045 */ 1046 @SystemApi 1047 public static final int SYNC_DISABLED_MODE_PERSISTENT = 1; 1048 1049 /** 1050 * Disabling of Config bulk update / syncing is not persistent, i.e. it will 1051 * not survive a device reboot. 1052 * 1053 * @hide 1054 */ 1055 @SystemApi 1056 public static final int SYNC_DISABLED_MODE_UNTIL_REBOOT = 2; 1057 1058 1059 // NOTE: this API is only used by the framework code, but using MODULE_LIBRARIES causes a 1060 // build-time error on CtsDeviceConfigTestCases, so it's using PRIVILEGED_APPS. 1061 /** 1062 * Optional argument to {@link #dump(ParcelFileDescriptor, PrintWriter, String, String[])} to 1063 * indicate that the next argument is a namespace. How {@code dump()} will handle that 1064 * argument is documented there. 1065 * 1066 * @hide 1067 */ 1068 @SystemApi(client = SystemApi.Client.PRIVILEGED_APPS) 1069 @FlaggedApi(Flags.FLAG_DUMP_IMPROVEMENTS) 1070 public static final String DUMP_ARG_NAMESPACE = "--namespace"; 1071 1072 private static final Object sLock = new Object(); 1073 @GuardedBy("sLock") 1074 private static ArrayMap<OnPropertiesChangedListener, Pair<String, Executor>> sListeners = 1075 new ArrayMap<>(); 1076 @GuardedBy("sLock") 1077 private static Map<String, Pair<ContentObserver, Integer>> sNamespaces = new HashMap<>(); 1078 private static final String TAG = "DeviceConfig"; 1079 private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); 1080 1081 private static final DeviceConfigDataStore sDataStore = newDataStore(); 1082 1083 @RavenwoodRedirect newDataStore()1084 private static DeviceConfigDataStore newDataStore() { 1085 return new SettingsConfigDataStore(); 1086 } 1087 1088 private static final String DEVICE_CONFIG_OVERRIDES_NAMESPACE = 1089 "device_config_overrides"; 1090 1091 /** 1092 * Interface for monitoring callback functions. 1093 * 1094 * @hide 1095 */ 1096 @SystemApi 1097 public interface MonitorCallback { 1098 /** 1099 * Callback for updating a namespace. 1100 * Reports that a config in the given namespace has changed. 1101 * Isn't called for {@link DeviceConfig#getPublicNamespaces() public namespaces}. 1102 * 1103 * @param updatedNamespace the namespace, within which at least one config has changed. 1104 * @hide 1105 */ 1106 @SystemApi onNamespaceUpdate(@onNull String updatedNamespace)1107 void onNamespaceUpdate(@NonNull String updatedNamespace); 1108 1109 /** 1110 * Callback for accessing device config. 1111 * Reports an access to a the given namespace and the given calling package. 1112 * Isn't called for {@link DeviceConfig#getPublicNamespaces() public namespaces}. 1113 * 1114 * @param callingPackage the calling package id. 1115 * @param namespace the namespace, within which one of its config has been accessed. 1116 * @hide 1117 */ 1118 @SystemApi onDeviceConfigAccess(@onNull String callingPackage, @NonNull String namespace)1119 void onDeviceConfigAccess(@NonNull String callingPackage, @NonNull String namespace); 1120 } 1121 1122 // Should never be invoked DeviceConfig()1123 private DeviceConfig() { 1124 } 1125 1126 /** 1127 * Look up the value of a property for a particular namespace. 1128 * 1129 * @param namespace The namespace containing the property to look up. 1130 * @param name The name of the property to look up. 1131 * @return the corresponding value, or null if not present. 1132 * @hide 1133 */ 1134 @SystemApi 1135 @Nullable getProperty(@onNull String namespace, @NonNull String name)1136 public static String getProperty(@NonNull String namespace, @NonNull String name) { 1137 // Fetch all properties for the namespace at once and cache them in the local process, so we 1138 // incur the cost of the IPC less often. Lookups happen much more frequently than updates, 1139 // and we want to optimize the former. 1140 return getProperties(namespace, name).getString(name, null); 1141 } 1142 1143 /** 1144 * Look up the values of multiple properties for a particular namespace. The lookup is atomic, 1145 * such that the values of these properties cannot change between the time when the first is 1146 * fetched and the time when the last is fetched. 1147 * <p> 1148 * Each call to {@link #setProperties(Properties)} is also atomic and ensures that either none 1149 * or all of the change is picked up here, but never only part of it. 1150 * 1151 * If there are any local overrides applied, they will take precedence over underlying values. 1152 * 1153 * @param namespace The namespace containing the properties to look up. 1154 * @param names The names of properties to look up, or empty to fetch all properties for the 1155 * given namespace. 1156 * @return {@link Properties} object containing the requested properties. This reflects the 1157 * state of these properties at the time of the lookup, and is not updated to reflect any 1158 * future changes. The keyset of this Properties object will contain only the intersection 1159 * of properties already set and properties requested via the names parameter. Properties 1160 * that are already set but were not requested will not be contained here. Properties that 1161 * are not set, but were requested will not be contained here either. 1162 * @hide 1163 */ 1164 @SystemApi 1165 @NonNull 1166 @RequiresPermission(READ_DEVICE_CONFIG) getProperties(@onNull String namespace, @NonNull String... names)1167 public static Properties getProperties(@NonNull String namespace, @NonNull String... names) { 1168 Properties properties = getPropertiesWithoutOverrides(namespace, names); 1169 if (SdkLevel.isAtLeastV()) { 1170 applyOverrides(properties); 1171 } 1172 return properties; 1173 } 1174 1175 @NonNull getPropertiesWithoutOverrides(@onNull String namespace, @NonNull String... names)1176 private static Properties getPropertiesWithoutOverrides(@NonNull String namespace, 1177 @NonNull String... names) { 1178 return sDataStore.getProperties(namespace, names); 1179 } 1180 applyOverrides(@onNull Properties properties)1181 private static void applyOverrides(@NonNull Properties properties) { 1182 Properties overrides = 1183 getPropertiesWithoutOverrides(DEVICE_CONFIG_OVERRIDES_NAMESPACE); 1184 1185 final String prefix = properties.getNamespace() + ':'; 1186 final int prefixLength = prefix.length(); 1187 1188 for (var override : overrides.getMap().entrySet()) { 1189 String fullKey = override.getKey(); 1190 String value = override.getValue(); 1191 if (value != null && fullKey.startsWith(prefix)) { 1192 properties.setString(fullKey.substring(prefixLength), value); 1193 } 1194 } 1195 } 1196 1197 /** 1198 * List all stored flags. 1199 * 1200 * The keys take the form {@code namespace/name}, and the values are the flag values. 1201 * 1202 * @hide 1203 */ 1204 @SystemApi 1205 @NonNull getAllProperties()1206 public static Set<Properties> getAllProperties() { 1207 Map<String, String> properties = sDataStore.getAllProperties(); 1208 Map<String, Map<String, String>> propertyMaps = new HashMap<>(); 1209 for (String flag : properties.keySet()) { 1210 String[] namespaceAndFlag = flag.split("/"); 1211 String namespace = namespaceAndFlag[0]; 1212 String flagName = namespaceAndFlag[1]; 1213 String override = 1214 getProperty(DEVICE_CONFIG_OVERRIDES_NAMESPACE, namespace + ":" + flagName); 1215 1216 String value = override != null ? override : properties.get(flag); 1217 1218 if (!propertyMaps.containsKey(namespace)) { 1219 propertyMaps.put(namespace, new HashMap<>()); 1220 } 1221 propertyMaps.get(namespace).put(flagName, value); 1222 } 1223 1224 HashSet<Properties> result = new HashSet<>(); 1225 for (Map.Entry<String, Map<String, String>> entry : propertyMaps.entrySet()) { 1226 result.add(new Properties(entry.getKey(), entry.getValue())); 1227 } 1228 return result; 1229 } 1230 1231 /** 1232 * Look up the String value of a property for a particular namespace. 1233 * 1234 * @param namespace The namespace containing the property to look up. 1235 * @param name The name of the property to look up. 1236 * @param defaultValue The value to return if the property does not exist or has no non-null 1237 * value. 1238 * @return the corresponding value, or defaultValue if none exists. 1239 * @hide 1240 */ 1241 @SystemApi 1242 @RequiresPermission(READ_DEVICE_CONFIG) 1243 @Nullable getString(@onNull String namespace, @NonNull String name, @Nullable String defaultValue)1244 public static String getString(@NonNull String namespace, @NonNull String name, 1245 @Nullable String defaultValue) { 1246 String value = getProperty(namespace, name); 1247 return value != null ? value : defaultValue; 1248 } 1249 1250 /** 1251 * Look up the boolean value of a property for a particular namespace. 1252 * 1253 * @param namespace The namespace containing the property to look up. 1254 * @param name The name of the property to look up. 1255 * @param defaultValue The value to return if the property does not exist or has no non-null 1256 * value. 1257 * @return the corresponding value, or defaultValue if none exists. 1258 * @hide 1259 */ 1260 @SystemApi getBoolean(@onNull String namespace, @NonNull String name, boolean defaultValue)1261 public static boolean getBoolean(@NonNull String namespace, @NonNull String name, 1262 boolean defaultValue) { 1263 String value = getProperty(namespace, name); 1264 return value != null ? Boolean.parseBoolean(value) : defaultValue; 1265 } 1266 1267 /** 1268 * Look up the int value of a property for a particular namespace. 1269 * 1270 * @param namespace The namespace containing the property to look up. 1271 * @param name The name of the property to look up. 1272 * @param defaultValue The value to return if the property does not exist, has no non-null 1273 * value, or fails to parse into an int. 1274 * @return the corresponding value, or defaultValue if either none exists or it does not parse. 1275 * @hide 1276 */ 1277 @SystemApi 1278 @RequiresPermission(READ_DEVICE_CONFIG) getInt(@onNull String namespace, @NonNull String name, int defaultValue)1279 public static int getInt(@NonNull String namespace, @NonNull String name, int defaultValue) { 1280 String value = getProperty(namespace, name); 1281 if (value == null) { 1282 return defaultValue; 1283 } 1284 try { 1285 return Integer.parseInt(value); 1286 } catch (NumberFormatException e) { 1287 Slog.e(TAG, "Parsing integer failed for " + namespace + ":" + name); 1288 return defaultValue; 1289 } 1290 } 1291 1292 /** 1293 * Look up the long value of a property for a particular namespace. 1294 * 1295 * @param namespace The namespace containing the property to look up. 1296 * @param name The name of the property to look up. 1297 * @param defaultValue The value to return if the property does not exist, has no non-null 1298 * value, or fails to parse into a long. 1299 * @return the corresponding value, or defaultValue if either none exists or it does not parse. 1300 * @hide 1301 */ 1302 @SystemApi 1303 @RequiresPermission(READ_DEVICE_CONFIG) getLong(@onNull String namespace, @NonNull String name, long defaultValue)1304 public static long getLong(@NonNull String namespace, @NonNull String name, long defaultValue) { 1305 String value = getProperty(namespace, name); 1306 if (value == null) { 1307 return defaultValue; 1308 } 1309 try { 1310 return Long.parseLong(value); 1311 } catch (NumberFormatException e) { 1312 Slog.e(TAG, "Parsing long failed for " + namespace + ":" + name); 1313 return defaultValue; 1314 } 1315 } 1316 1317 /** 1318 * Look up the float value of a property for a particular namespace. 1319 * 1320 * @param namespace The namespace containing the property to look up. 1321 * @param name The name of the property to look up. 1322 * @param defaultValue The value to return if the property does not exist, has no non-null 1323 * value, or fails to parse into a float. 1324 * @return the corresponding value, or defaultValue if either none exists or it does not parse. 1325 * @hide 1326 */ 1327 @SystemApi 1328 @RequiresPermission(READ_DEVICE_CONFIG) getFloat(@onNull String namespace, @NonNull String name, float defaultValue)1329 public static float getFloat(@NonNull String namespace, @NonNull String name, 1330 float defaultValue) { 1331 String value = getProperty(namespace, name); 1332 if (value == null) { 1333 return defaultValue; 1334 } 1335 try { 1336 return Float.parseFloat(value); 1337 } catch (NumberFormatException e) { 1338 Slog.e(TAG, "Parsing float failed for " + namespace + ":" + name); 1339 return defaultValue; 1340 } 1341 } 1342 1343 /** 1344 * Set flag {@code namespace/name} to {@code value}, and ignores server-updates for this flag. 1345 * 1346 * Can still be called even if there is no underlying value set. 1347 * 1348 * Returns {@code true} if successful, or {@code false} if the storage implementation throws 1349 * errors. 1350 * 1351 * @hide 1352 */ 1353 @SystemApi 1354 @RequiresPermission(WRITE_DEVICE_CONFIG) setLocalOverride(@onNull String namespace, @NonNull String name, @NonNull String value)1355 public static boolean setLocalOverride(@NonNull String namespace, @NonNull String name, 1356 @NonNull String value) { 1357 return setProperty(DEVICE_CONFIG_OVERRIDES_NAMESPACE, namespace + ":" + name, value, false); 1358 } 1359 1360 /** 1361 * Clear all local sticky overrides. 1362 * 1363 * @hide 1364 */ 1365 @SystemApi 1366 @RequiresPermission(WRITE_DEVICE_CONFIG) clearAllLocalOverrides()1367 public static void clearAllLocalOverrides() { 1368 Properties overrides = getProperties(DEVICE_CONFIG_OVERRIDES_NAMESPACE); 1369 for (String overrideName : overrides.getKeyset()) { 1370 deleteProperty(DEVICE_CONFIG_OVERRIDES_NAMESPACE, overrideName); 1371 } 1372 } 1373 1374 /** 1375 * Clear local sticky override for flag {@code namespace/name}. 1376 * 1377 * @hide 1378 */ 1379 @SystemApi 1380 @RequiresPermission(WRITE_DEVICE_CONFIG) clearLocalOverride(@onNull String namespace, @NonNull String name)1381 public static void clearLocalOverride(@NonNull String namespace, 1382 @NonNull String name) { 1383 deleteProperty(DEVICE_CONFIG_OVERRIDES_NAMESPACE, namespace + ":" + name); 1384 } 1385 1386 /** 1387 * Return a map containing all flags that have been overridden. 1388 * 1389 * The keys of the outer map are namespaces. They keys of the inner maps are 1390 * flag names. The values of the inner maps are the underlying flag values 1391 * (not to be confused with their overridden values). 1392 * 1393 * @hide 1394 */ 1395 @NonNull 1396 @SystemApi getUnderlyingValuesForOverriddenFlags()1397 public static Map<String, Map<String, String>> getUnderlyingValuesForOverriddenFlags() { 1398 Properties overrides = getProperties(DEVICE_CONFIG_OVERRIDES_NAMESPACE); 1399 HashMap<String, Map<String, String>> result = new HashMap<>(); 1400 for (Map.Entry<String, String> entry : overrides.getPropertyValues().entrySet()) { 1401 String[] namespaceAndFlag = entry.getKey().split(":"); 1402 String namespace = namespaceAndFlag[0]; 1403 String flag = namespaceAndFlag[1]; 1404 1405 String actualValue = 1406 getPropertiesWithoutOverrides(namespace, flag) 1407 .getString(flag, null); 1408 if (result.get(namespace) != null) { 1409 result.get(namespace).put(flag, actualValue); 1410 } else { 1411 HashMap<String, String> innerMap = new HashMap<>(); 1412 innerMap.put(flag, actualValue); 1413 result.put(namespace, innerMap); 1414 } 1415 } 1416 return result; 1417 } 1418 1419 /** 1420 * Create a new property with the provided name and value in the provided namespace, or 1421 * update the value of such a property if it already exists. The same name can exist in multiple 1422 * namespaces and might have different values in any or all namespaces. 1423 * <p> 1424 * The method takes an argument indicating whether to make the value the default for this 1425 * property. 1426 * <p> 1427 * All properties stored for a particular scope can be reverted to their default values 1428 * by passing the namespace to {@link #resetToDefaults(int, String)}. 1429 * 1430 * @param namespace The namespace containing the property to create or update. 1431 * @param name The name of the property to create or update. 1432 * @param value The value to store for the property. 1433 * @param makeDefault Whether to make the new value the default one. 1434 * @return {@code true} if the value was set, {@code false} if the storage implementation throws 1435 * errors. 1436 * @hide 1437 * @see #resetToDefaults(int, String). 1438 */ 1439 @SystemApi 1440 @RequiresPermission(anyOf = {WRITE_DEVICE_CONFIG, WRITE_ALLOWLISTED_DEVICE_CONFIG}) setProperty(@onNull String namespace, @NonNull String name, @Nullable String value, boolean makeDefault)1441 public static boolean setProperty(@NonNull String namespace, @NonNull String name, 1442 @Nullable String value, boolean makeDefault) { 1443 return sDataStore.setProperty(namespace, name, value, makeDefault); 1444 } 1445 1446 /** 1447 * Set all of the properties for a specific namespace. Pre-existing properties will be updated 1448 * and new properties will be added if necessary. Any pre-existing properties for the specific 1449 * namespace which are not part of the provided {@link Properties} object will be deleted from 1450 * the namespace. These changes are all applied atomically, such that no calls to read or reset 1451 * these properties can happen in the middle of this update. 1452 * <p> 1453 * Each call to {@link #getProperties(String, String...)} is also atomic and ensures that either 1454 * none or all of this update is picked up, but never only part of it. 1455 * 1456 * @param properties the complete set of properties to set for a specific namespace. 1457 * @throws BadConfigException if the provided properties are banned by RescueParty. 1458 * @return {@code true} if the values were set, {@code false} otherwise. 1459 * @hide 1460 */ 1461 @SystemApi 1462 @RequiresPermission(anyOf = {WRITE_DEVICE_CONFIG, WRITE_ALLOWLISTED_DEVICE_CONFIG}) setProperties(@onNull Properties properties)1463 public static boolean setProperties(@NonNull Properties properties) throws BadConfigException { 1464 return sDataStore.setProperties(properties); 1465 } 1466 1467 /** 1468 * Delete a property with the provided name and value in the provided namespace 1469 * 1470 * @param namespace The namespace containing the property to delete. 1471 * @param name The name of the property to delete. 1472 * @return {@code true} if the property was deleted or it did not exist in the first place. 1473 * Return {@code false} if the storage implementation throws errors. 1474 * @hide 1475 */ 1476 @SystemApi 1477 @RequiresPermission(anyOf = {WRITE_DEVICE_CONFIG, WRITE_ALLOWLISTED_DEVICE_CONFIG}) deleteProperty(@onNull String namespace, @NonNull String name)1478 public static boolean deleteProperty(@NonNull String namespace, @NonNull String name) { 1479 return sDataStore.deleteProperty(namespace, name); 1480 } 1481 1482 /** 1483 * Reset properties to their default values by removing the underlying values. 1484 * <p> 1485 * The method accepts an optional namespace parameter. If provided, only properties set within 1486 * that namespace will be reset. Otherwise, all properties will be reset. 1487 * <p> 1488 * Note: This method should only be used by {@link com.android.server.RescueParty}. It was 1489 * designed to be used in the event of boot or crash loops caused by flag changes. It does not 1490 * revert flag values to defaults - instead it removes the property entirely which causes the 1491 * consumer of the flag to use hardcoded defaults upon retrieval. 1492 * <p> 1493 * To clear values for a namespace without removing the underlying properties, construct a 1494 * {@link Properties} object with the caller's namespace and either an empty flag map, or some 1495 * snapshot of flag values. Then use {@link #setProperties(Properties)} to remove all flags 1496 * under the namespace, or set them to the values in the snapshot. 1497 * <p> 1498 * To revert values for testing, one should mock DeviceConfig using 1499 * {@link com.android.server.testables.TestableDeviceConfig} where possible. Otherwise, fallback 1500 * to using {@link #setProperties(Properties)} as outlined above. 1501 * 1502 * @param resetMode The reset mode to use. 1503 * @param namespace Optionally, the specific namespace which resets will be limited to. 1504 * @hide 1505 * @see #setProperty(String, String, String, boolean) 1506 */ 1507 @SystemApi 1508 @RavenwoodThrow 1509 @RequiresPermission(anyOf = {WRITE_DEVICE_CONFIG, WRITE_ALLOWLISTED_DEVICE_CONFIG}) resetToDefaults(int resetMode, @Nullable String namespace)1510 public static void resetToDefaults(int resetMode, @Nullable String namespace) { 1511 sDataStore.resetToDefaults(resetMode, namespace); 1512 } 1513 1514 /** 1515 * Disables or re-enables bulk modifications ({@link #setProperties(Properties)}) to device 1516 * config values. This is intended for use during tests to prevent a sync operation clearing 1517 * config values which could influence the outcome of the tests, i.e. by changing behavior. 1518 * 1519 * @param syncDisabledMode the mode to use, see {@link Settings.Config#SYNC_DISABLED_MODE_NONE}, 1520 * {@link Settings.Config#SYNC_DISABLED_MODE_PERSISTENT} and {@link 1521 * Settings.Config#SYNC_DISABLED_MODE_UNTIL_REBOOT} 1522 * 1523 * @see #getSyncDisabledMode() 1524 * @hide 1525 */ 1526 @SystemApi 1527 @RequiresPermission(anyOf = {WRITE_DEVICE_CONFIG, READ_WRITE_SYNC_DISABLED_MODE_CONFIG}) setSyncDisabledMode(int syncDisabledMode)1528 public static void setSyncDisabledMode(int syncDisabledMode) { 1529 sDataStore.setSyncDisabledMode(syncDisabledMode); 1530 } 1531 1532 /** 1533 * Returns the current mode of sync disabling. 1534 * 1535 * @see #setSyncDisabledMode(int) 1536 * @hide 1537 */ 1538 @SystemApi 1539 @RequiresPermission(anyOf = {WRITE_DEVICE_CONFIG, READ_WRITE_SYNC_DISABLED_MODE_CONFIG}) getSyncDisabledMode()1540 public static int getSyncDisabledMode() { 1541 return sDataStore.getSyncDisabledMode(); 1542 } 1543 1544 /** 1545 * Add a listener for property changes. 1546 * <p> 1547 * This listener will be called whenever properties in the specified namespace change. Callbacks 1548 * will be made on the specified executor. Future calls to this method with the same listener 1549 * will replace the old namespace and executor. Remove the listener entirely by calling 1550 * {@link #removeOnPropertiesChangedListener(OnPropertiesChangedListener)}. 1551 * 1552 * @param namespace The namespace containing properties to monitor. 1553 * @param executor The executor which will be used to run callbacks. 1554 * @param onPropertiesChangedListener The listener to add. 1555 * @hide 1556 * @see #removeOnPropertiesChangedListener(OnPropertiesChangedListener) 1557 */ 1558 @SystemApi addOnPropertiesChangedListener( @onNull String namespace, @NonNull @CallbackExecutor Executor executor, @NonNull OnPropertiesChangedListener onPropertiesChangedListener)1559 public static void addOnPropertiesChangedListener( 1560 @NonNull String namespace, 1561 @NonNull @CallbackExecutor Executor executor, 1562 @NonNull OnPropertiesChangedListener onPropertiesChangedListener) { 1563 synchronized (sLock) { 1564 Pair<String, Executor> oldNamespace = sListeners.get(onPropertiesChangedListener); 1565 if (oldNamespace == null) { 1566 // Brand new listener, add it to the list. 1567 sListeners.put(onPropertiesChangedListener, new Pair<>(namespace, executor)); 1568 incrementNamespace(namespace); 1569 } else if (namespace.equals(oldNamespace.first)) { 1570 // Listener is already registered for this namespace, update executor just in case. 1571 sListeners.put(onPropertiesChangedListener, new Pair<>(namespace, executor)); 1572 } else { 1573 // Update this listener from an old namespace to the new one. 1574 decrementNamespace(sListeners.get(onPropertiesChangedListener).first); 1575 sListeners.put(onPropertiesChangedListener, new Pair<>(namespace, executor)); 1576 incrementNamespace(namespace); 1577 } 1578 } 1579 } 1580 1581 // NOTE: this API is only used by the framework code, but using MODULE_LIBRARIES causes a 1582 // build-time error on CtsDeviceConfigTestCases, so it's using PRIVILEGED_APPS. 1583 /** 1584 * Dumps internal state into the given {@code fd} or {@code printWriter}. 1585 * 1586 * <p><b>Note:</b> Currently the only supported argument is {@link #DUMP_ARG_NAMESPACE} which 1587 * will filter the output using a substring of the next argument. But other arguments might be 1588 * dynamically added in the future, without documentation - this method is meant only for 1589 * debugging purposes, and should not be used as a formal API. 1590 * 1591 * @param printWriter print writer that will output the dump state. 1592 * @param prefix prefix added to each line 1593 * @param args (optional) arguments passed by {@code dumpsys}. 1594 * 1595 * @hide 1596 */ 1597 @SystemApi(client = SystemApi.Client.PRIVILEGED_APPS) 1598 @FlaggedApi(Flags.FLAG_DUMP_IMPROVEMENTS) dump(@onNull PrintWriter printWriter, @NonNull String dumpPrefix, @Nullable String[] args)1599 public static void dump(@NonNull PrintWriter printWriter, @NonNull String dumpPrefix, 1600 @Nullable String[] args) { 1601 if (DEBUG) { 1602 Slog.d(TAG, "dump(): args=" + Arrays.toString(args)); 1603 } 1604 Objects.requireNonNull(printWriter, "printWriter cannot be null"); 1605 1606 Comparator<OnPropertiesChangedListener> comparator = (o1, o2) -> o1.toString() 1607 .compareTo(o2.toString()); 1608 TreeMap<String, Set<OnPropertiesChangedListener>> listenersByNamespace = 1609 new TreeMap<>(); 1610 ArraySet<OnPropertiesChangedListener> uniqueListeners = new ArraySet<>(); 1611 String filter = null; 1612 if (args.length > 0) { 1613 switch (args[0]) { 1614 case DUMP_ARG_NAMESPACE: 1615 if (args.length < 2) { 1616 throw new IllegalArgumentException( 1617 "argument " + DUMP_ARG_NAMESPACE + " requires an extra argument"); 1618 } 1619 filter = args[1]; 1620 if (DEBUG) { 1621 Slog.d(TAG, "dump(): setting filter as " + filter); 1622 } 1623 break; 1624 default: 1625 Slog.w(TAG, "dump(): ignoring invalid arguments: " + Arrays.toString(args)); 1626 break; 1627 } 1628 } 1629 int listenersSize; 1630 synchronized (sLock) { 1631 listenersSize = sListeners.size(); 1632 for (int i = 0; i < listenersSize; i++) { 1633 var namespace = sListeners.valueAt(i).first; 1634 if (filter != null && !namespace.contains(filter)) { 1635 continue; 1636 } 1637 var listener = sListeners.keyAt(i); 1638 var listeners = listenersByNamespace.get(namespace); 1639 if (listeners == null) { 1640 // Life would be so much easier if Android provided a MultiMap implementation... 1641 listeners = new TreeSet<>(comparator); 1642 listenersByNamespace.put(namespace, listeners); 1643 } 1644 listeners.add(listener); 1645 uniqueListeners.add(listener); 1646 } 1647 } 1648 printWriter.printf("%s%d listeners for %d namespaces:\n", dumpPrefix, uniqueListeners.size(), 1649 listenersByNamespace.size()); 1650 for (var entry : listenersByNamespace.entrySet()) { 1651 var namespace = entry.getKey(); 1652 var listeners = entry.getValue(); 1653 printWriter.printf("%s%s: %d listeners\n", dumpPrefix, namespace, listeners.size()); 1654 for (var listener : listeners) { 1655 printWriter.printf("%s%s%s\n", dumpPrefix, dumpPrefix, listener); 1656 } 1657 } 1658 } 1659 1660 /** 1661 * Remove a listener for property changes. The listener will receive no further notification of 1662 * property changes. 1663 * 1664 * @param onPropertiesChangedListener The listener to remove. 1665 * @hide 1666 * @see #addOnPropertiesChangedListener(String, Executor, OnPropertiesChangedListener) 1667 */ 1668 @SystemApi removeOnPropertiesChangedListener( @onNull OnPropertiesChangedListener onPropertiesChangedListener)1669 public static void removeOnPropertiesChangedListener( 1670 @NonNull OnPropertiesChangedListener onPropertiesChangedListener) { 1671 Objects.requireNonNull(onPropertiesChangedListener); 1672 synchronized (sLock) { 1673 if (sListeners.containsKey(onPropertiesChangedListener)) { 1674 decrementNamespace(sListeners.get(onPropertiesChangedListener).first); 1675 sListeners.remove(onPropertiesChangedListener); 1676 } 1677 } 1678 } 1679 1680 /** 1681 * Setter callback for monitoring Config table. 1682 * 1683 * @param executor the {@link Executor} on which to invoke the callback 1684 * @param callback callback to set 1685 * 1686 * @hide 1687 */ 1688 @SystemApi 1689 @RavenwoodThrow 1690 @RequiresPermission(Manifest.permission.MONITOR_DEVICE_CONFIG_ACCESS) setMonitorCallback( @onNull ContentResolver resolver, @NonNull @CallbackExecutor Executor executor, @NonNull MonitorCallback callback)1691 public static void setMonitorCallback( 1692 @NonNull ContentResolver resolver, 1693 @NonNull @CallbackExecutor Executor executor, 1694 @NonNull MonitorCallback callback) { 1695 sDataStore.setMonitorCallback(resolver, executor, callback); 1696 } 1697 1698 /** 1699 * Clear callback for monitoring Config table. 1700 * this may only be used to clear callback function registered by 1701 * {@link DeviceConfig#setMonitorCallback} 1702 * @hide 1703 */ 1704 @SystemApi 1705 @RavenwoodThrow 1706 @RequiresPermission(Manifest.permission.MONITOR_DEVICE_CONFIG_ACCESS) clearMonitorCallback(@onNull ContentResolver resolver)1707 public static void clearMonitorCallback(@NonNull ContentResolver resolver) { 1708 sDataStore.clearMonitorCallback(resolver); 1709 } 1710 1711 /** 1712 * Increment the count used to represent the number of listeners subscribed to the given 1713 * namespace. If this is the first (i.e. incrementing from 0 to 1) for the given namespace, a 1714 * ContentObserver is registered. 1715 * 1716 * @param namespace The namespace to increment the count for. 1717 */ 1718 @GuardedBy("sLock") incrementNamespace(@onNull String namespace)1719 private static void incrementNamespace(@NonNull String namespace) { 1720 Objects.requireNonNull(namespace); 1721 Pair<ContentObserver, Integer> namespaceCount = sNamespaces.get(namespace); 1722 if (namespaceCount != null) { 1723 sNamespaces.put(namespace, new Pair<>(namespaceCount.first, namespaceCount.second + 1)); 1724 } else { 1725 // This is a new namespace, register a ContentObserver for it. 1726 ContentObserver contentObserver = new ContentObserver(null) { 1727 @Override 1728 public void onChange(boolean selfChange, Uri uri) { 1729 if (uri != null) { 1730 handleChange(uri); 1731 } 1732 } 1733 }; 1734 sDataStore 1735 .registerContentObserver(namespace, true, contentObserver); 1736 sNamespaces.put(namespace, new Pair<>(contentObserver, 1)); 1737 } 1738 } 1739 1740 /** 1741 * Decrement the count used to represent the number of listeners subscribed to the given 1742 * namespace. If this is the final decrement call (i.e. decrementing from 1 to 0) for the given 1743 * namespace, the ContentObserver that had been tracking it will be removed. 1744 * 1745 * @param namespace The namespace to decrement the count for. 1746 */ 1747 @GuardedBy("sLock") decrementNamespace(@onNull String namespace)1748 private static void decrementNamespace(@NonNull String namespace) { 1749 Objects.requireNonNull(namespace); 1750 Pair<ContentObserver, Integer> namespaceCount = sNamespaces.get(namespace); 1751 if (namespaceCount == null) { 1752 // This namespace is not registered and does not need to be decremented 1753 return; 1754 } else if (namespaceCount.second > 1) { 1755 sNamespaces.put(namespace, new Pair<>(namespaceCount.first, namespaceCount.second - 1)); 1756 } else { 1757 // Decrementing a namespace to zero means we no longer need its ContentObserver. 1758 sDataStore.unregisterContentObserver(namespaceCount.first); 1759 sNamespaces.remove(namespace); 1760 } 1761 } 1762 handleChange(@onNull Uri uri)1763 private static void handleChange(@NonNull Uri uri) { 1764 Objects.requireNonNull(uri); 1765 List<String> pathSegments = uri.getPathSegments(); 1766 // pathSegments(0) is "config" 1767 final String namespace = pathSegments.get(1); 1768 final Properties properties; 1769 if (pathSegments.size() > 2) { 1770 String[] keys = new String[pathSegments.size() - 2]; 1771 for (int i = 2; i < pathSegments.size(); ++i) { 1772 keys[i - 2] = pathSegments.get(i); 1773 } 1774 1775 try { 1776 properties = getProperties(namespace, keys); 1777 } catch (SecurityException e) { 1778 // Silently failing to not crash binder or listener threads. 1779 Slog.e(TAG, "OnPropertyChangedListener update failed: permission violation."); 1780 return; 1781 } 1782 1783 // Make sure all keys are present. 1784 for (String key : keys) { 1785 properties.setString(key, properties.getString(key, null)); 1786 } 1787 } else { 1788 properties = new Properties.Builder(namespace).build(); 1789 } 1790 1791 synchronized (sLock) { 1792 for (int i = 0; i < sListeners.size(); i++) { 1793 if (namespace.equals(sListeners.valueAt(i).first)) { 1794 final OnPropertiesChangedListener listener = sListeners.keyAt(i); 1795 sListeners.valueAt(i).second.execute(() -> { 1796 listener.onPropertiesChanged(properties); 1797 }); 1798 } 1799 } 1800 } 1801 } 1802 1803 /** 1804 * Returns list of namespaces that can be read without READ_DEVICE_CONFIG_PERMISSION; 1805 * @hide 1806 */ 1807 @SystemApi getPublicNamespaces()1808 public static @NonNull List<String> getPublicNamespaces() { 1809 return PUBLIC_NAMESPACES; 1810 } 1811 1812 /** 1813 * Returns list of flags that can be written with adb as non-root. 1814 * @hide 1815 */ 1816 @SystemApi getAdbWritableFlags()1817 public static @NonNull Set<String> getAdbWritableFlags() { 1818 return WritableFlags.ALLOWLIST; 1819 } 1820 1821 /** 1822 * Returns the list of namespaces in which all flags can be written with adb as non-root. 1823 * @hide 1824 */ 1825 @SystemApi 1826 @FlaggedApi(Flags.FLAG_DEVICE_CONFIG_WRITABLE_NAMESPACES_API) getAdbWritableNamespaces()1827 public static @NonNull Set<String> getAdbWritableNamespaces() { 1828 return WritableNamespaces.ALLOWLIST; 1829 } 1830 1831 /** 1832 * Interface for monitoring changes to properties. Implementations will receive callbacks when 1833 * properties change, including a {@link Properties} object which contains a single namespace 1834 * and all of the properties which changed for that namespace. This includes properties which 1835 * were added, updated, or deleted. This is not necessarily a complete list of all properties 1836 * belonging to the namespace, as properties which don't change are omitted. 1837 * <p> 1838 * Override {@link #onPropertiesChanged(Properties)} to handle callbacks for changes. 1839 * 1840 * @hide 1841 */ 1842 @SystemApi 1843 public interface OnPropertiesChangedListener { 1844 /** 1845 * Called when one or more properties have changed, providing a Properties object with all 1846 * of the changed properties. This object will contain only properties which have changed, 1847 * not the complete set of all properties belonging to the namespace. 1848 * 1849 * @param properties Contains the complete collection of properties which have changed for a 1850 * single namespace. This includes only those which were added, updated, 1851 * or deleted. 1852 */ onPropertiesChanged(@onNull Properties properties)1853 void onPropertiesChanged(@NonNull Properties properties); 1854 } 1855 1856 /** 1857 * Thrown by {@link #setProperties(Properties)} when a configuration is rejected. This 1858 * happens if RescueParty has identified a bad configuration and reset the namespace. 1859 * 1860 * @hide 1861 */ 1862 @SystemApi 1863 public static class BadConfigException extends Exception {} 1864 1865 /** 1866 * A mapping of properties to values, as well as a single namespace which they all belong to. 1867 * 1868 * @hide 1869 */ 1870 @SystemApi 1871 public static class Properties { 1872 private final String mNamespace; 1873 private final HashMap<String, String> mMap; 1874 private Set<String> mKeyset; 1875 1876 /** 1877 * Create a mapping of properties to values and the namespace they belong to. 1878 * 1879 * @param namespace The namespace these properties belong to. 1880 * @param keyValueMap A map between property names and property values. 1881 * @hide 1882 */ 1883 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) Properties(@onNull String namespace, @Nullable Map<String, String> keyValueMap)1884 public Properties(@NonNull String namespace, @Nullable Map<String, String> keyValueMap) { 1885 Objects.requireNonNull(namespace); 1886 mNamespace = namespace; 1887 mMap = new HashMap(); 1888 if (keyValueMap != null) { 1889 mMap.putAll(keyValueMap); 1890 } 1891 } 1892 1893 /** 1894 * @return the namespace all properties within this instance belong to. 1895 */ 1896 @NonNull getNamespace()1897 public String getNamespace() { 1898 return mNamespace; 1899 } 1900 1901 /** 1902 * @return the non-null set of property names. 1903 */ 1904 @NonNull getKeyset()1905 public Set<String> getKeyset() { 1906 if (mKeyset == null) { 1907 mKeyset = Collections.unmodifiableSet(mMap.keySet()); 1908 } 1909 return mKeyset; 1910 } 1911 1912 /** 1913 * Look up the String value of a property. 1914 * 1915 * @param name The name of the property to look up. 1916 * @param defaultValue The value to return if the property has not been defined. 1917 * @return the corresponding value, or defaultValue if none exists. 1918 */ 1919 @Nullable getString(@onNull String name, @Nullable String defaultValue)1920 public String getString(@NonNull String name, @Nullable String defaultValue) { 1921 Objects.requireNonNull(name); 1922 String value = mMap.get(name); 1923 return value != null ? value : defaultValue; 1924 } 1925 1926 @Nullable setString(@onNull String name, @Nullable String value)1927 private String setString(@NonNull String name, @Nullable String value) { 1928 Objects.requireNonNull(name); 1929 mKeyset = null; 1930 return mMap.put(name, value); 1931 } 1932 1933 @NonNull getMap()1934 private Map<String, String> getMap() { 1935 return mMap; 1936 } 1937 1938 /** 1939 * Look up the boolean value of a property. 1940 * 1941 * @param name The name of the property to look up. 1942 * @param defaultValue The value to return if the property has not been defined. 1943 * @return the corresponding value, or defaultValue if none exists. 1944 */ getBoolean(@onNull String name, boolean defaultValue)1945 public boolean getBoolean(@NonNull String name, boolean defaultValue) { 1946 Objects.requireNonNull(name); 1947 String value = mMap.get(name); 1948 return value != null ? Boolean.parseBoolean(value) : defaultValue; 1949 } 1950 1951 /** 1952 * Look up the int value of a property. 1953 * 1954 * @param name The name of the property to look up. 1955 * @param defaultValue The value to return if the property has not been defined or fails to 1956 * parse into an int. 1957 * @return the corresponding value, or defaultValue if no valid int is available. 1958 */ getInt(@onNull String name, int defaultValue)1959 public int getInt(@NonNull String name, int defaultValue) { 1960 Objects.requireNonNull(name); 1961 String value = mMap.get(name); 1962 if (value == null) { 1963 return defaultValue; 1964 } 1965 try { 1966 return Integer.parseInt(value); 1967 } catch (NumberFormatException e) { 1968 Slog.e(TAG, "Parsing int failed for " + name); 1969 return defaultValue; 1970 } 1971 } 1972 1973 /** 1974 * Look up the long value of a property. 1975 * 1976 * @param name The name of the property to look up. 1977 * @param defaultValue The value to return if the property has not been defined. or fails to 1978 * parse into a long. 1979 * @return the corresponding value, or defaultValue if no valid long is available. 1980 */ getLong(@onNull String name, long defaultValue)1981 public long getLong(@NonNull String name, long defaultValue) { 1982 Objects.requireNonNull(name); 1983 String value = mMap.get(name); 1984 if (value == null) { 1985 return defaultValue; 1986 } 1987 try { 1988 return Long.parseLong(value); 1989 } catch (NumberFormatException e) { 1990 Slog.e(TAG, "Parsing long failed for " + name); 1991 return defaultValue; 1992 } 1993 } 1994 1995 /** 1996 * Look up the int value of a property. 1997 * 1998 * @param name The name of the property to look up. 1999 * @param defaultValue The value to return if the property has not been defined. or fails to 2000 * parse into a float. 2001 * @return the corresponding value, or defaultValue if no valid float is available. 2002 */ getFloat(@onNull String name, float defaultValue)2003 public float getFloat(@NonNull String name, float defaultValue) { 2004 Objects.requireNonNull(name); 2005 String value = mMap.get(name); 2006 if (value == null) { 2007 return defaultValue; 2008 } 2009 try { 2010 return Float.parseFloat(value); 2011 } catch (NumberFormatException e) { 2012 Slog.e(TAG, "Parsing float failed for " + name); 2013 return defaultValue; 2014 } 2015 } 2016 2017 /** 2018 * Returns a map with the underlying property values defined by this object 2019 * 2020 * @hide 2021 */ getPropertyValues()2022 public @NonNull Map<String, String> getPropertyValues() { 2023 return Collections.unmodifiableMap(mMap); 2024 } 2025 2026 /** 2027 * Builder class for the construction of {@link Properties} objects. 2028 */ 2029 public static final class Builder { 2030 @NonNull 2031 private final String mNamespace; 2032 @NonNull 2033 private final Map<String, String> mKeyValues = new HashMap<>(); 2034 2035 /** 2036 * Create a new Builders for the specified namespace. 2037 * @param namespace non null namespace. 2038 */ Builder(@onNull String namespace)2039 public Builder(@NonNull String namespace) { 2040 mNamespace = namespace; 2041 } 2042 2043 /** 2044 * Add a new property with the specified key and value. 2045 * @param name non null name of the property. 2046 * @param value nullable string value of the property. 2047 * @return this Builder object 2048 */ 2049 @NonNull setString(@onNull String name, @Nullable String value)2050 public Builder setString(@NonNull String name, @Nullable String value) { 2051 mKeyValues.put(name, value); 2052 return this; 2053 } 2054 2055 /** 2056 * Add a new property with the specified key and value. 2057 * @param name non null name of the property. 2058 * @param value nullable string value of the property. 2059 * @return this Builder object 2060 */ 2061 @NonNull setBoolean(@onNull String name, boolean value)2062 public Builder setBoolean(@NonNull String name, boolean value) { 2063 mKeyValues.put(name, Boolean.toString(value)); 2064 return this; 2065 } 2066 2067 /** 2068 * Add a new property with the specified key and value. 2069 * @param name non null name of the property. 2070 * @param value int value of the property. 2071 * @return this Builder object 2072 */ 2073 @NonNull setInt(@onNull String name, int value)2074 public Builder setInt(@NonNull String name, int value) { 2075 mKeyValues.put(name, Integer.toString(value)); 2076 return this; 2077 } 2078 2079 /** 2080 * Add a new property with the specified key and value. 2081 * @param name non null name of the property. 2082 * @param value long value of the property. 2083 * @return this Builder object 2084 */ 2085 @NonNull setLong(@onNull String name, long value)2086 public Builder setLong(@NonNull String name, long value) { 2087 mKeyValues.put(name, Long.toString(value)); 2088 return this; 2089 } 2090 2091 /** 2092 * Add a new property with the specified key and value. 2093 * @param name non null name of the property. 2094 * @param value float value of the property. 2095 * @return this Builder object 2096 */ 2097 @NonNull setFloat(@onNull String name, float value)2098 public Builder setFloat(@NonNull String name, float value) { 2099 mKeyValues.put(name, Float.toString(value)); 2100 return this; 2101 } 2102 2103 /** 2104 * Create a new {@link Properties} object. 2105 * @return non null Properties. 2106 */ 2107 @NonNull build()2108 public Properties build() { 2109 return new Properties(mNamespace, mKeyValues); 2110 } 2111 } 2112 } 2113 2114 } 2115