1 /* 2 * Copyright (C) 2017 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.util; 18 19 import android.annotation.TestApi; 20 import android.content.Context; 21 import android.os.SystemProperties; 22 import android.provider.Settings; 23 import android.text.TextUtils; 24 25 import java.util.HashMap; 26 import java.util.HashSet; 27 import java.util.Map; 28 import java.util.Set; 29 30 /** 31 * Util class to get feature flag information. 32 * 33 * @hide 34 */ 35 @TestApi 36 public class FeatureFlagUtils { 37 38 public static final String FFLAG_PREFIX = "sys.fflag."; 39 public static final String FFLAG_OVERRIDE_PREFIX = FFLAG_PREFIX + "override."; 40 public static final String PERSIST_PREFIX = "persist." + FFLAG_OVERRIDE_PREFIX; 41 public static final String HEARING_AID_SETTINGS = "settings_bluetooth_hearing_aid"; 42 public static final String SETTINGS_WIFITRACKER2 = "settings_wifitracker2"; 43 /** @hide */ 44 public static final String SETTINGS_DO_NOT_RESTORE_PRESERVED = 45 "settings_do_not_restore_preserved"; 46 /** @hide */ 47 public static final String SETTINGS_USE_NEW_BACKUP_ELIGIBILITY_RULES 48 = "settings_use_new_backup_eligibility_rules"; 49 /** @hide */ 50 public static final String SETTINGS_ENABLE_SECURITY_HUB = "settings_enable_security_hub"; 51 /** @hide */ 52 public static final String SETTINGS_SUPPORT_LARGE_SCREEN = "settings_support_large_screen"; 53 54 /** 55 * Support locale opt-out and opt-in switch for per app's language. 56 * @hide 57 */ 58 public static final String SETTINGS_APP_LOCALE_OPT_IN_ENABLED = 59 "settings_app_locale_opt_in_enabled"; 60 61 /** 62 * Launch the Volume panel in SystemUI. 63 * @hide 64 */ 65 public static final String SETTINGS_VOLUME_PANEL_IN_SYSTEMUI = 66 "settings_volume_panel_in_systemui"; 67 68 /** @hide */ 69 public static final String SETTINGS_ENABLE_MONITOR_PHANTOM_PROCS = 70 "settings_enable_monitor_phantom_procs"; 71 72 /** 73 * Support dark theme activation at Bedtime. 74 * @hide 75 */ 76 public static final String SETTINGS_APP_ALLOW_DARK_THEME_ACTIVATION_AT_BEDTIME = 77 "settings_app_allow_dark_theme_activation_at_bedtime"; 78 79 /** 80 * Flag to decouple bluetooth LE Audio Broadcast from Unicast 81 * If the flag is true, the broadcast feature will be enabled when the phone 82 * is connected to the BLE device. 83 * If the flag is false, it is not necessary to connect the BLE device. 84 * @hide 85 */ 86 public static final String SETTINGS_NEED_CONNECTED_BLE_DEVICE_FOR_BROADCAST = 87 "settings_need_connected_ble_device_for_broadcast"; 88 89 /** 90 * Enable new modifier key settings UI 91 * @hide 92 */ 93 public static final String SETTINGS_NEW_KEYBOARD_MODIFIER_KEY = 94 "settings_new_keyboard_modifier_key"; 95 96 /** 97 * Enable new trackpad settings UI 98 * @hide 99 */ 100 public static final String SETTINGS_NEW_KEYBOARD_TRACKPAD = "settings_new_keyboard_trackpad"; 101 102 /** 103 * Enable trackpad gesture settings UI 104 * @hide 105 */ 106 public static final String SETTINGS_NEW_KEYBOARD_TRACKPAD_GESTURE = 107 "settings_new_keyboard_trackpad_gesture"; 108 109 /** 110 * Enable the new pages which is implemented with SPA. 111 * @hide 112 */ 113 public static final String SETTINGS_ENABLE_SPA = "settings_enable_spa"; 114 115 /** 116 * Enable new pages implemented with SPA besides the SPA pages controlled by the {@code 117 * settings_enable_spa} flag. 118 * @hide 119 */ 120 public static final String SETTINGS_ENABLE_SPA_PHASE2 = "settings_enable_spa_phase2"; 121 122 /** 123 * Enable the SPA metrics writing. 124 * @hide 125 */ 126 public static final String SETTINGS_ENABLE_SPA_METRICS = "settings_enable_spa_metrics"; 127 128 /** Flag to enable/disable adb log metrics 129 * @hide 130 */ 131 public static final String SETTINGS_ADB_METRICS_WRITER = "settings_adb_metrics_writer"; 132 133 /** 134 * Flag to show stylus-specific preferences in Connected Devices 135 * @hide 136 */ 137 public static final String SETTINGS_SHOW_STYLUS_PREFERENCES = 138 "settings_show_stylus_preferences"; 139 140 /** 141 * Flag to enable/disable biometrics enrollment v2 142 * @hide 143 */ 144 public static final String SETTINGS_BIOMETRICS2_ENROLLMENT = "settings_biometrics2_enrollment"; 145 146 /** 147 * Flag to enable/disable FingerprintSettings v2 148 * @hide 149 */ 150 public static final String SETTINGS_BIOMETRICS2_FINGERPRINT_SETTINGS = 151 "settings_biometrics2_fingerprint"; 152 153 /** 154 * Flag to enable/disable remote auth enrollment and settings 155 * @hide 156 */ 157 public static final String SETTINGS_REMOTEAUTH_ENROLLMENT_SETTINGS = 158 "settings_remoteauth_enrollment"; 159 160 /** 161 * Flag to enable/disable preferring the AccessibilityMenu service in the system. 162 * @hide 163 */ 164 public static final String SETTINGS_PREFER_ACCESSIBILITY_MENU_IN_SYSTEM = 165 "settings_prefer_accessibility_menu_in_system"; 166 167 /** Flag to enable/disable audio routing change 168 * @hide 169 */ 170 public static final String SETTINGS_AUDIO_ROUTING = "settings_audio_routing"; 171 172 /** Flag to enable/disable flash notifications 173 * @hide 174 */ 175 public static final String SETTINGS_FLASH_NOTIFICATIONS = "settings_flash_notifications"; 176 177 /** 178 * Flag to enable lock screen credentials transfer API in Android U. 179 * @hide 180 */ 181 public static final String SETTINGS_ENABLE_LOCKSCREEN_TRANSFER_API = 182 "settings_enable_lockscreen_transfer_api"; 183 184 /** 185 * Flag to enable remote device credential validation 186 * @hide 187 */ 188 public static final String SETTINGS_REMOTE_DEVICE_CREDENTIAL_VALIDATION = 189 "settings_remote_device_credential_validation"; 190 191 private static final Map<String, String> DEFAULT_FLAGS; 192 193 static { 194 DEFAULT_FLAGS = new HashMap<>(); 195 DEFAULT_FLAGS.put("settings_audio_switcher", "true"); 196 DEFAULT_FLAGS.put("settings_systemui_theme", "true"); DEFAULT_FLAGS.put(HEARING_AID_SETTINGS, "false")197 DEFAULT_FLAGS.put(HEARING_AID_SETTINGS, "false"); 198 DEFAULT_FLAGS.put("settings_wifi_details_datausage_header", "false"); 199 DEFAULT_FLAGS.put("settings_skip_direction_mutable", "true"); DEFAULT_FLAGS.put(SETTINGS_WIFITRACKER2, "true")200 DEFAULT_FLAGS.put(SETTINGS_WIFITRACKER2, "true"); 201 DEFAULT_FLAGS.put("settings_controller_loading_enhancement", "true"); 202 DEFAULT_FLAGS.put("settings_conditionals", "false"); 203 // This flags guards a feature introduced in R and will be removed in the next release 204 // (b/148367230). DEFAULT_FLAGS.put(SETTINGS_DO_NOT_RESTORE_PRESERVED, "true")205 DEFAULT_FLAGS.put(SETTINGS_DO_NOT_RESTORE_PRESERVED, "true"); 206 207 DEFAULT_FLAGS.put("settings_tether_all_in_one", "false"); 208 DEFAULT_FLAGS.put("settings_contextual_home", "false"); DEFAULT_FLAGS.put(SETTINGS_USE_NEW_BACKUP_ELIGIBILITY_RULES, "true")209 DEFAULT_FLAGS.put(SETTINGS_USE_NEW_BACKUP_ELIGIBILITY_RULES, "true"); DEFAULT_FLAGS.put(SETTINGS_ENABLE_SECURITY_HUB, "true")210 DEFAULT_FLAGS.put(SETTINGS_ENABLE_SECURITY_HUB, "true"); DEFAULT_FLAGS.put(SETTINGS_SUPPORT_LARGE_SCREEN, "true")211 DEFAULT_FLAGS.put(SETTINGS_SUPPORT_LARGE_SCREEN, "true"); 212 DEFAULT_FLAGS.put("settings_search_always_expand", "true"); DEFAULT_FLAGS.put(SETTINGS_APP_LOCALE_OPT_IN_ENABLED, "true")213 DEFAULT_FLAGS.put(SETTINGS_APP_LOCALE_OPT_IN_ENABLED, "true"); DEFAULT_FLAGS.put(SETTINGS_VOLUME_PANEL_IN_SYSTEMUI, "false")214 DEFAULT_FLAGS.put(SETTINGS_VOLUME_PANEL_IN_SYSTEMUI, "false"); DEFAULT_FLAGS.put(SETTINGS_ENABLE_MONITOR_PHANTOM_PROCS, "true")215 DEFAULT_FLAGS.put(SETTINGS_ENABLE_MONITOR_PHANTOM_PROCS, "true"); DEFAULT_FLAGS.put(SETTINGS_APP_ALLOW_DARK_THEME_ACTIVATION_AT_BEDTIME, "true")216 DEFAULT_FLAGS.put(SETTINGS_APP_ALLOW_DARK_THEME_ACTIVATION_AT_BEDTIME, "true"); DEFAULT_FLAGS.put(SETTINGS_NEED_CONNECTED_BLE_DEVICE_FOR_BROADCAST, "true")217 DEFAULT_FLAGS.put(SETTINGS_NEED_CONNECTED_BLE_DEVICE_FOR_BROADCAST, "true"); DEFAULT_FLAGS.put(SETTINGS_NEW_KEYBOARD_MODIFIER_KEY, "true")218 DEFAULT_FLAGS.put(SETTINGS_NEW_KEYBOARD_MODIFIER_KEY, "true"); DEFAULT_FLAGS.put(SETTINGS_NEW_KEYBOARD_TRACKPAD, "true")219 DEFAULT_FLAGS.put(SETTINGS_NEW_KEYBOARD_TRACKPAD, "true"); DEFAULT_FLAGS.put(SETTINGS_NEW_KEYBOARD_TRACKPAD_GESTURE, "false")220 DEFAULT_FLAGS.put(SETTINGS_NEW_KEYBOARD_TRACKPAD_GESTURE, "false"); DEFAULT_FLAGS.put(SETTINGS_ENABLE_SPA, "true")221 DEFAULT_FLAGS.put(SETTINGS_ENABLE_SPA, "true"); DEFAULT_FLAGS.put(SETTINGS_ENABLE_SPA_PHASE2, "false")222 DEFAULT_FLAGS.put(SETTINGS_ENABLE_SPA_PHASE2, "false"); DEFAULT_FLAGS.put(SETTINGS_ENABLE_SPA_METRICS, "true")223 DEFAULT_FLAGS.put(SETTINGS_ENABLE_SPA_METRICS, "true"); DEFAULT_FLAGS.put(SETTINGS_ADB_METRICS_WRITER, "false")224 DEFAULT_FLAGS.put(SETTINGS_ADB_METRICS_WRITER, "false"); DEFAULT_FLAGS.put(SETTINGS_SHOW_STYLUS_PREFERENCES, "true")225 DEFAULT_FLAGS.put(SETTINGS_SHOW_STYLUS_PREFERENCES, "true"); DEFAULT_FLAGS.put(SETTINGS_BIOMETRICS2_ENROLLMENT, "false")226 DEFAULT_FLAGS.put(SETTINGS_BIOMETRICS2_ENROLLMENT, "false"); DEFAULT_FLAGS.put(SETTINGS_PREFER_ACCESSIBILITY_MENU_IN_SYSTEM, "false")227 DEFAULT_FLAGS.put(SETTINGS_PREFER_ACCESSIBILITY_MENU_IN_SYSTEM, "false"); DEFAULT_FLAGS.put(SETTINGS_AUDIO_ROUTING, "false")228 DEFAULT_FLAGS.put(SETTINGS_AUDIO_ROUTING, "false"); DEFAULT_FLAGS.put(SETTINGS_FLASH_NOTIFICATIONS, "true")229 DEFAULT_FLAGS.put(SETTINGS_FLASH_NOTIFICATIONS, "true"); DEFAULT_FLAGS.put(SETTINGS_ENABLE_LOCKSCREEN_TRANSFER_API, "true")230 DEFAULT_FLAGS.put(SETTINGS_ENABLE_LOCKSCREEN_TRANSFER_API, "true"); DEFAULT_FLAGS.put(SETTINGS_REMOTE_DEVICE_CREDENTIAL_VALIDATION, "true")231 DEFAULT_FLAGS.put(SETTINGS_REMOTE_DEVICE_CREDENTIAL_VALIDATION, "true"); DEFAULT_FLAGS.put(SETTINGS_BIOMETRICS2_FINGERPRINT_SETTINGS, "false")232 DEFAULT_FLAGS.put(SETTINGS_BIOMETRICS2_FINGERPRINT_SETTINGS, "false"); 233 // TODO: b/298454866 Replace with Trunk Stable Feature Flag DEFAULT_FLAGS.put(SETTINGS_REMOTEAUTH_ENROLLMENT_SETTINGS, "false")234 DEFAULT_FLAGS.put(SETTINGS_REMOTEAUTH_ENROLLMENT_SETTINGS, "false"); 235 } 236 237 private static final Set<String> PERSISTENT_FLAGS; 238 239 static { 240 PERSISTENT_FLAGS = new HashSet<>(); 241 PERSISTENT_FLAGS.add(SETTINGS_APP_LOCALE_OPT_IN_ENABLED); 242 PERSISTENT_FLAGS.add(SETTINGS_SUPPORT_LARGE_SCREEN); 243 PERSISTENT_FLAGS.add(SETTINGS_ENABLE_MONITOR_PHANTOM_PROCS); 244 PERSISTENT_FLAGS.add(SETTINGS_APP_ALLOW_DARK_THEME_ACTIVATION_AT_BEDTIME); 245 PERSISTENT_FLAGS.add(SETTINGS_NEW_KEYBOARD_MODIFIER_KEY); 246 PERSISTENT_FLAGS.add(SETTINGS_NEW_KEYBOARD_TRACKPAD); 247 PERSISTENT_FLAGS.add(SETTINGS_NEW_KEYBOARD_TRACKPAD_GESTURE); 248 PERSISTENT_FLAGS.add(SETTINGS_ENABLE_SPA); 249 PERSISTENT_FLAGS.add(SETTINGS_ENABLE_SPA_PHASE2); 250 PERSISTENT_FLAGS.add(SETTINGS_PREFER_ACCESSIBILITY_MENU_IN_SYSTEM); 251 } 252 253 /** 254 * Whether or not a flag is enabled. 255 * 256 * @param feature the flag name 257 * @return true if the flag is enabled (either by default in system, or override by user) 258 */ isEnabled(Context context, String feature)259 public static boolean isEnabled(Context context, String feature) { 260 // Override precedence: 261 // Settings.Global -> sys.fflag.override.* -> static list 262 263 // Step 1: check if feature flag is set in Settings.Global. 264 String value; 265 if (context != null) { 266 value = Settings.Global.getString(context.getContentResolver(), feature); 267 if (!TextUtils.isEmpty(value)) { 268 return Boolean.parseBoolean(value); 269 } 270 } 271 272 // Step 2: check if feature flag has any override. 273 // Flag name: [persist.]sys.fflag.override.<feature> 274 value = SystemProperties.get(getSystemPropertyPrefix(feature) + feature); 275 if (!TextUtils.isEmpty(value)) { 276 return Boolean.parseBoolean(value); 277 } 278 // Step 3: check if feature flag has any default value. 279 value = getAllFeatureFlags().get(feature); 280 return Boolean.parseBoolean(value); 281 } 282 283 /** 284 * Override feature flag to new state. 285 */ setEnabled(Context context, String feature, boolean enabled)286 public static void setEnabled(Context context, String feature, boolean enabled) { 287 SystemProperties.set(getSystemPropertyPrefix(feature) + feature, 288 enabled ? "true" : "false"); 289 } 290 291 /** 292 * Returns all feature flags in their raw form. 293 */ getAllFeatureFlags()294 public static Map<String, String> getAllFeatureFlags() { 295 return DEFAULT_FLAGS; 296 } 297 getSystemPropertyPrefix(String feature)298 private static String getSystemPropertyPrefix(String feature) { 299 return PERSISTENT_FLAGS.contains(feature) ? PERSIST_PREFIX : FFLAG_OVERRIDE_PREFIX; 300 } 301 } 302