1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 * use this file except in compliance with the License. You may obtain a copy of 6 * 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, WITHOUT 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 * License for the specific language governing permissions and limitations under 14 * the License. 15 */ 16 17 package com.android.cellbroadcastreceiver; 18 19 import android.annotation.NonNull; 20 import android.app.ActionBar; 21 import android.app.Activity; 22 import android.app.Fragment; 23 import android.app.backup.BackupManager; 24 import android.content.BroadcastReceiver; 25 import android.content.Context; 26 import android.content.Intent; 27 import android.content.IntentFilter; 28 import android.content.SharedPreferences; 29 import android.content.pm.PackageManager; 30 import android.content.res.Resources; 31 import android.os.Bundle; 32 import android.os.PersistableBundle; 33 import android.os.UserManager; 34 import android.telephony.CarrierConfigManager; 35 import android.telephony.SubscriptionManager; 36 import android.util.Log; 37 import android.view.MenuItem; 38 39 import androidx.localbroadcastmanager.content.LocalBroadcastManager; 40 import androidx.preference.ListPreference; 41 import androidx.preference.Preference; 42 import androidx.preference.PreferenceCategory; 43 import androidx.preference.PreferenceFragment; 44 import androidx.preference.PreferenceManager; 45 import androidx.preference.PreferenceScreen; 46 import androidx.preference.TwoStatePreference; 47 48 import com.android.internal.annotations.VisibleForTesting; 49 50 import java.util.HashMap; 51 import java.util.Map; 52 53 /** 54 * Settings activity for the cell broadcast receiver. 55 */ 56 public class CellBroadcastSettings extends Activity { 57 58 private static final String TAG = "CellBroadcastSettings"; 59 60 private static final boolean DBG = false; 61 62 // Preference key for alert header (A text view, not clickable). 63 public static final String KEY_ALERTS_HEADER = "alerts_header"; 64 65 // Preference key for a main toggle to enable/disable all alerts message (default enabled). 66 public static final String KEY_ENABLE_ALERTS_MASTER_TOGGLE = "enable_alerts_master_toggle"; 67 68 // Preference key for whether to enable public safety messages (default enabled). 69 public static final String KEY_ENABLE_PUBLIC_SAFETY_MESSAGES = "enable_public_safety_messages"; 70 71 // Preference key for whether to enable emergency alerts (default enabled). 72 public static final String KEY_ENABLE_EMERGENCY_ALERTS = "enable_emergency_alerts"; 73 74 // Enable vibration on alert (unless main volume is silent). 75 public static final String KEY_ENABLE_ALERT_VIBRATE = "enable_alert_vibrate"; 76 77 // Play alert sound in full volume regardless Do Not Disturb is on. 78 public static final String KEY_OVERRIDE_DND = "override_dnd"; 79 80 public static final String KEY_OVERRIDE_DND_SETTINGS_CHANGED = 81 "override_dnd_settings_changed"; 82 83 // Preference category for emergency alert and CMAS settings. 84 public static final String KEY_CATEGORY_EMERGENCY_ALERTS = "category_emergency_alerts"; 85 86 // Preference category for alert preferences. 87 public static final String KEY_CATEGORY_ALERT_PREFERENCES = "category_alert_preferences"; 88 89 // Show checkbox for Presidential alerts in settings 90 // Whether to display CMAS presidential alert notifications (always enabled). 91 public static final String KEY_ENABLE_CMAS_PRESIDENTIAL_ALERTS = 92 "enable_cmas_presidential_alerts"; 93 94 // Whether to display CMAS extreme threat notifications (default is enabled). 95 public static final String KEY_ENABLE_CMAS_EXTREME_THREAT_ALERTS = 96 "enable_cmas_extreme_threat_alerts"; 97 98 // Whether to display CMAS severe threat notifications (default is enabled). 99 public static final String KEY_ENABLE_CMAS_SEVERE_THREAT_ALERTS = 100 "enable_cmas_severe_threat_alerts"; 101 102 // Whether to display CMAS amber alert messages (default is enabled). 103 public static final String KEY_ENABLE_CMAS_AMBER_ALERTS = "enable_cmas_amber_alerts"; 104 105 // Whether to display monthly test messages (default is disabled). 106 public static final String KEY_ENABLE_TEST_ALERTS = "enable_test_alerts"; 107 108 // Whether to display state/local test messages (default disabled). 109 public static final String KEY_ENABLE_STATE_LOCAL_TEST_ALERTS = 110 "enable_state_local_test_alerts"; 111 112 // Preference key for whether to enable area update information notifications 113 // Enabled by default for phones sold in Brazil and India, otherwise this setting may be hidden. 114 public static final String KEY_ENABLE_AREA_UPDATE_INFO_ALERTS = 115 "enable_area_update_info_alerts"; 116 117 // Preference key for initial opt-in/opt-out dialog. 118 public static final String KEY_SHOW_CMAS_OPT_OUT_DIALOG = "show_cmas_opt_out_dialog"; 119 120 // Alert reminder interval ("once" = single 2 minute reminder). 121 public static final String KEY_ALERT_REMINDER_INTERVAL = "alert_reminder_interval"; 122 123 // Preference key for emergency alerts history 124 public static final String KEY_EMERGENCY_ALERT_HISTORY = "emergency_alert_history"; 125 126 // For watch layout 127 private static final String KEY_WATCH_ALERT_REMINDER = "watch_alert_reminder"; 128 129 // Resource cache 130 private static final Map<Integer, Resources> sResourcesCache = new HashMap<>(); 131 132 // Test override for disabling the subId specific resources 133 private static boolean sUseResourcesForSubId = true; 134 135 // Whether to receive alert in second language code 136 public static final String KEY_RECEIVE_CMAS_IN_SECOND_LANGUAGE = 137 "receive_cmas_in_second_language"; 138 139 @Override onCreate(Bundle savedInstanceState)140 public void onCreate(Bundle savedInstanceState) { 141 super.onCreate(savedInstanceState); 142 143 ActionBar actionBar = getActionBar(); 144 if (actionBar != null) { 145 // android.R.id.home will be triggered in onOptionsItemSelected() 146 actionBar.setDisplayHomeAsUpEnabled(true); 147 } 148 149 UserManager userManager = (UserManager) getSystemService(Context.USER_SERVICE); 150 if (userManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_CELL_BROADCASTS)) { 151 setContentView(R.layout.cell_broadcast_disallowed_preference_screen); 152 return; 153 } 154 155 // We only add new CellBroadcastSettingsFragment if no fragment is restored. 156 Fragment fragment = getFragmentManager().findFragmentById(android.R.id.content); 157 if (fragment == null) { 158 fragment = new CellBroadcastSettingsFragment(); 159 getFragmentManager() 160 .beginTransaction() 161 .add(android.R.id.content, fragment) 162 .commit(); 163 } 164 } 165 166 @Override onOptionsItemSelected(MenuItem item)167 public boolean onOptionsItemSelected(MenuItem item) { 168 switch (item.getItemId()) { 169 // Respond to the action bar's Up/Home button 170 case android.R.id.home: 171 finish(); 172 return true; 173 } 174 return super.onOptionsItemSelected(item); 175 } 176 177 /** 178 * New fragment-style implementation of preferences. 179 */ 180 public static class CellBroadcastSettingsFragment extends PreferenceFragment { 181 182 private TwoStatePreference mExtremeCheckBox; 183 private TwoStatePreference mSevereCheckBox; 184 private TwoStatePreference mAmberCheckBox; 185 private TwoStatePreference mMasterToggle; 186 private TwoStatePreference mPublicSafetyMessagesChannelCheckBox; 187 private TwoStatePreference mEmergencyAlertsCheckBox; 188 private ListPreference mReminderInterval; 189 private TwoStatePreference mOverrideDndCheckBox; 190 private TwoStatePreference mAreaUpdateInfoCheckBox; 191 private TwoStatePreference mTestCheckBox; 192 private TwoStatePreference mStateLocalTestCheckBox; 193 private TwoStatePreference mEnableVibrateCheckBox; 194 private Preference mAlertHistory; 195 private Preference mAlertsHeader; 196 private PreferenceCategory mAlertCategory; 197 private PreferenceCategory mAlertPreferencesCategory; 198 private boolean mDisableSevereWhenExtremeDisabled = true; 199 200 // WATCH 201 private TwoStatePreference mAlertReminder; 202 203 // Show checkbox for Presidential alerts in settings 204 private TwoStatePreference mPresidentialCheckBox; 205 206 // on/off switch in settings for receiving alert in second language code 207 private TwoStatePreference mReceiveCmasInSecondLanguageCheckBox; 208 209 private final BroadcastReceiver mTestingModeChangedReeiver = new BroadcastReceiver() { 210 @Override 211 public void onReceive(Context context, Intent intent) { 212 switch (intent.getAction()) { 213 case CellBroadcastReceiver.ACTION_TESTING_MODE_CHANGED: 214 updatePreferenceVisibility(); 215 break; 216 } 217 } 218 }; 219 220 @Override onCreatePreferences(Bundle savedInstanceState, String rootKey)221 public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { 222 223 LocalBroadcastManager.getInstance(getContext()) 224 .registerReceiver(mTestingModeChangedReeiver, new IntentFilter( 225 CellBroadcastReceiver.ACTION_TESTING_MODE_CHANGED)); 226 227 // Load the preferences from an XML resource 228 PackageManager pm = getActivity().getPackageManager(); 229 if (pm.hasSystemFeature(PackageManager.FEATURE_WATCH)) { 230 addPreferencesFromResource(R.xml.watch_preferences); 231 } else { 232 addPreferencesFromResource(R.xml.preferences); 233 } 234 235 PreferenceScreen preferenceScreen = getPreferenceScreen(); 236 237 mExtremeCheckBox = (TwoStatePreference) 238 findPreference(KEY_ENABLE_CMAS_EXTREME_THREAT_ALERTS); 239 mSevereCheckBox = (TwoStatePreference) 240 findPreference(KEY_ENABLE_CMAS_SEVERE_THREAT_ALERTS); 241 mAmberCheckBox = (TwoStatePreference) 242 findPreference(KEY_ENABLE_CMAS_AMBER_ALERTS); 243 mMasterToggle = (TwoStatePreference) 244 findPreference(KEY_ENABLE_ALERTS_MASTER_TOGGLE); 245 mPublicSafetyMessagesChannelCheckBox = (TwoStatePreference) 246 findPreference(KEY_ENABLE_PUBLIC_SAFETY_MESSAGES); 247 mEmergencyAlertsCheckBox = (TwoStatePreference) 248 findPreference(KEY_ENABLE_EMERGENCY_ALERTS); 249 mReminderInterval = (ListPreference) 250 findPreference(KEY_ALERT_REMINDER_INTERVAL); 251 mOverrideDndCheckBox = (TwoStatePreference) 252 findPreference(KEY_OVERRIDE_DND); 253 mAreaUpdateInfoCheckBox = (TwoStatePreference) 254 findPreference(KEY_ENABLE_AREA_UPDATE_INFO_ALERTS); 255 mTestCheckBox = (TwoStatePreference) 256 findPreference(KEY_ENABLE_TEST_ALERTS); 257 mStateLocalTestCheckBox = (TwoStatePreference) 258 findPreference(KEY_ENABLE_STATE_LOCAL_TEST_ALERTS); 259 mAlertHistory = findPreference(KEY_EMERGENCY_ALERT_HISTORY); 260 mAlertsHeader = findPreference(KEY_ALERTS_HEADER); 261 mReceiveCmasInSecondLanguageCheckBox = (TwoStatePreference) findPreference 262 (KEY_RECEIVE_CMAS_IN_SECOND_LANGUAGE); 263 mEnableVibrateCheckBox = findPreference(KEY_ENABLE_ALERT_VIBRATE); 264 265 // Show checkbox for Presidential alerts in settings 266 mPresidentialCheckBox = (TwoStatePreference) 267 findPreference(KEY_ENABLE_CMAS_PRESIDENTIAL_ALERTS); 268 269 if (pm.hasSystemFeature(PackageManager.FEATURE_WATCH)) { 270 mAlertReminder = (TwoStatePreference) 271 findPreference(KEY_WATCH_ALERT_REMINDER); 272 if (Integer.valueOf(mReminderInterval.getValue()) == 0) { 273 mAlertReminder.setChecked(false); 274 } else { 275 mAlertReminder.setChecked(true); 276 } 277 mAlertReminder.setOnPreferenceChangeListener((p, newVal) -> { 278 try { 279 mReminderInterval.setValueIndex((Boolean) newVal ? 1 : 3); 280 } catch (IndexOutOfBoundsException e) { 281 mReminderInterval.setValue(String.valueOf(0)); 282 Log.w(TAG, "Setting default value"); 283 } 284 return true; 285 }); 286 PreferenceScreen watchScreen = (PreferenceScreen) 287 findPreference(KEY_CATEGORY_ALERT_PREFERENCES); 288 watchScreen.removePreference(mReminderInterval); 289 } else { 290 mAlertPreferencesCategory = (PreferenceCategory) 291 findPreference(KEY_CATEGORY_ALERT_PREFERENCES); 292 mAlertCategory = (PreferenceCategory) 293 findPreference(KEY_CATEGORY_EMERGENCY_ALERTS); 294 } 295 296 Resources res = CellBroadcastSettings.getResources(getContext(), 297 SubscriptionManager.DEFAULT_SUBSCRIPTION_ID); 298 299 SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext()); 300 mDisableSevereWhenExtremeDisabled = res.getBoolean( 301 R.bool.disable_severe_when_extreme_disabled); 302 303 // Handler for settings that require us to reconfigure enabled channels in radio 304 Preference.OnPreferenceChangeListener startConfigServiceListener = 305 new Preference.OnPreferenceChangeListener() { 306 @Override 307 public boolean onPreferenceChange(Preference pref, Object newValue) { 308 CellBroadcastReceiver.startConfigService(pref.getContext()); 309 310 if (mDisableSevereWhenExtremeDisabled) { 311 if (pref.getKey().equals(KEY_ENABLE_CMAS_EXTREME_THREAT_ALERTS)) { 312 boolean isExtremeAlertChecked = (Boolean) newValue; 313 if (mSevereCheckBox != null) { 314 mSevereCheckBox.setEnabled(isExtremeAlertChecked); 315 mSevereCheckBox.setChecked(false); 316 } 317 } 318 } 319 320 if (pref.getKey().equals(KEY_ENABLE_ALERTS_MASTER_TOGGLE)) { 321 boolean isEnableAlerts = (Boolean) newValue; 322 setAlertsEnabled(isEnableAlerts); 323 } 324 325 // Notify backup manager a backup pass is needed. 326 new BackupManager(getContext()).dataChanged(); 327 return true; 328 } 329 }; 330 331 initReminderIntervalList(); 332 333 if (mMasterToggle != null) { 334 mMasterToggle.setOnPreferenceChangeListener(startConfigServiceListener); 335 // If allow alerts are disabled, we turn all sub-alerts off. If it's enabled, we 336 // leave them as they are. 337 if (!mMasterToggle.isChecked()) { 338 setAlertsEnabled(false); 339 } 340 } 341 342 if (mAreaUpdateInfoCheckBox != null) { 343 mAreaUpdateInfoCheckBox.setOnPreferenceChangeListener(startConfigServiceListener); 344 } 345 if (mExtremeCheckBox != null) { 346 mExtremeCheckBox.setOnPreferenceChangeListener(startConfigServiceListener); 347 } 348 if (mPublicSafetyMessagesChannelCheckBox != null) { 349 mPublicSafetyMessagesChannelCheckBox.setOnPreferenceChangeListener( 350 startConfigServiceListener); 351 } 352 if (mEmergencyAlertsCheckBox != null) { 353 mEmergencyAlertsCheckBox.setOnPreferenceChangeListener(startConfigServiceListener); 354 } 355 if (mSevereCheckBox != null) { 356 mSevereCheckBox.setOnPreferenceChangeListener(startConfigServiceListener); 357 if (mDisableSevereWhenExtremeDisabled) { 358 if (mExtremeCheckBox != null) { 359 mSevereCheckBox.setEnabled(mExtremeCheckBox.isChecked()); 360 } 361 } 362 } 363 if (mAmberCheckBox != null) { 364 mAmberCheckBox.setOnPreferenceChangeListener(startConfigServiceListener); 365 } 366 if (mTestCheckBox != null) { 367 mTestCheckBox.setOnPreferenceChangeListener(startConfigServiceListener); 368 } 369 if (mStateLocalTestCheckBox != null) { 370 mStateLocalTestCheckBox.setOnPreferenceChangeListener( 371 startConfigServiceListener); 372 } 373 374 if (mOverrideDndCheckBox != null) { 375 if (!sp.getBoolean(KEY_OVERRIDE_DND_SETTINGS_CHANGED, false)) { 376 // If the user hasn't changed this settings yet, use the default settings 377 // from resource overlay. 378 mOverrideDndCheckBox.setChecked(res.getBoolean(R.bool.override_dnd_default)); 379 } 380 mOverrideDndCheckBox.setOnPreferenceChangeListener( 381 (pref, newValue) -> { 382 sp.edit().putBoolean(KEY_OVERRIDE_DND_SETTINGS_CHANGED, 383 true).apply(); 384 updateVibrationPreference((boolean) newValue); 385 return true; 386 }); 387 } 388 389 if (mAlertHistory != null) { 390 mAlertHistory.setOnPreferenceClickListener( 391 preference -> { 392 final Intent intent = new Intent(getContext(), 393 CellBroadcastListActivity.class); 394 startActivity(intent); 395 return true; 396 }); 397 } 398 399 updateVibrationPreference(sp.getBoolean(CellBroadcastSettings.KEY_OVERRIDE_DND, 400 false)); 401 updatePreferenceVisibility(); 402 } 403 404 /** 405 * Update the vibration preference based on override DND. If DND is overridden, then do 406 * not allow users to turn off vibration. 407 * 408 * @param overrideDnd {@code true} if the alert will be played at full volume, regardless 409 * DND settings. 410 */ updateVibrationPreference(boolean overrideDnd)411 private void updateVibrationPreference(boolean overrideDnd) { 412 if (mEnableVibrateCheckBox != null) { 413 if (overrideDnd) { 414 // If DND is enabled, always enable vibration. 415 mEnableVibrateCheckBox.setChecked(true); 416 } 417 // Grey out the preference if DND is overridden. 418 mEnableVibrateCheckBox.setEnabled(!overrideDnd); 419 } 420 } 421 422 /** 423 * Dynamically update each preference's visibility based on configuration. 424 */ updatePreferenceVisibility()425 private void updatePreferenceVisibility() { 426 Resources res = CellBroadcastSettings.getResources(getContext(), 427 SubscriptionManager.DEFAULT_SUBSCRIPTION_ID); 428 429 CellBroadcastChannelManager channelManager = new CellBroadcastChannelManager( 430 getContext(), SubscriptionManager.DEFAULT_SUBSCRIPTION_ID); 431 432 if (mPresidentialCheckBox != null) { 433 mPresidentialCheckBox.setVisible( 434 res.getBoolean(R.bool.show_presidential_alerts_settings)); 435 } 436 437 if (mExtremeCheckBox != null) { 438 mExtremeCheckBox.setVisible(res.getBoolean(R.bool.show_extreme_alert_settings) 439 && !channelManager.getCellBroadcastChannelRanges( 440 R.array.cmas_alert_extreme_channels_range_strings).isEmpty()); 441 } 442 443 if (mSevereCheckBox != null) { 444 mSevereCheckBox.setVisible(res.getBoolean(R.bool.show_severe_alert_settings) 445 && !channelManager.getCellBroadcastChannelRanges( 446 R.array.cmas_alerts_severe_range_strings).isEmpty()); 447 } 448 449 if (mAmberCheckBox != null) { 450 mAmberCheckBox.setVisible(res.getBoolean(R.bool.show_amber_alert_settings) 451 && !channelManager.getCellBroadcastChannelRanges( 452 R.array.cmas_amber_alerts_channels_range_strings).isEmpty()); 453 } 454 455 if (mPublicSafetyMessagesChannelCheckBox != null) { 456 mPublicSafetyMessagesChannelCheckBox.setVisible( 457 res.getBoolean(R.bool.show_public_safety_settings) 458 && !channelManager.getCellBroadcastChannelRanges( 459 R.array.public_safety_messages_channels_range_strings) 460 .isEmpty()); 461 } 462 463 if (mTestCheckBox != null) { 464 mTestCheckBox.setVisible(isTestAlertsToggleVisible(getContext())); 465 } 466 467 if (mEmergencyAlertsCheckBox != null) { 468 mEmergencyAlertsCheckBox.setVisible(!channelManager.getCellBroadcastChannelRanges( 469 R.array.emergency_alerts_channels_range_strings).isEmpty()); 470 } 471 472 if (mStateLocalTestCheckBox != null) { 473 mStateLocalTestCheckBox.setVisible( 474 res.getBoolean(R.bool.show_state_local_test_settings) 475 && !channelManager.getCellBroadcastChannelRanges( 476 R.array.state_local_test_alert_range_strings).isEmpty()); 477 } 478 479 if (mReceiveCmasInSecondLanguageCheckBox != null) { 480 mReceiveCmasInSecondLanguageCheckBox.setVisible(!res.getString( 481 R.string.emergency_alert_second_language_code).isEmpty()); 482 } 483 484 if (mAreaUpdateInfoCheckBox != null) { 485 mAreaUpdateInfoCheckBox.setVisible( 486 res.getBoolean(R.bool.config_showAreaUpdateInfoSettings)); 487 } 488 489 if (mOverrideDndCheckBox != null) { 490 mOverrideDndCheckBox.setVisible(res.getBoolean(R.bool.show_override_dnd_settings)); 491 } 492 493 if (mEnableVibrateCheckBox != null) { 494 // Only show vibrate toggle when override DND toggle is available to users, or when 495 // override DND default is turned off. 496 // In some countries, override DND is always on, which means vibration is always on. 497 // In that case, no need to show vibration toggle for users. 498 mEnableVibrateCheckBox.setVisible( 499 res.getBoolean(R.bool.show_override_dnd_settings) 500 || !res.getBoolean(R.bool.override_dnd_default)); 501 } 502 if (mAlertsHeader != null) { 503 mAlertsHeader.setVisible( 504 !getContext().getString(R.string.alerts_header_summary).isEmpty()); 505 } 506 } 507 initReminderIntervalList()508 private void initReminderIntervalList() { 509 Resources res = CellBroadcastSettings.getResources( 510 getContext(), SubscriptionManager.DEFAULT_SUBSCRIPTION_ID); 511 512 String[] activeValues = 513 res.getStringArray(R.array.alert_reminder_interval_active_values); 514 String[] allEntries = res.getStringArray(R.array.alert_reminder_interval_entries); 515 String[] newEntries = new String[activeValues.length]; 516 517 // Only add active interval to the list 518 for (int i = 0; i < activeValues.length; i++) { 519 int index = mReminderInterval.findIndexOfValue(activeValues[i]); 520 if (index != -1) { 521 newEntries[i] = allEntries[index]; 522 if (DBG) Log.d(TAG, "Added " + allEntries[index]); 523 } else { 524 Log.e(TAG, "Can't find " + activeValues[i]); 525 } 526 } 527 528 mReminderInterval.setEntries(newEntries); 529 mReminderInterval.setEntryValues(activeValues); 530 mReminderInterval.setSummary(mReminderInterval.getEntry()); 531 mReminderInterval.setOnPreferenceChangeListener( 532 new Preference.OnPreferenceChangeListener() { 533 @Override 534 public boolean onPreferenceChange(Preference pref, Object newValue) { 535 final ListPreference listPref = (ListPreference) pref; 536 final int idx = listPref.findIndexOfValue((String) newValue); 537 listPref.setSummary(listPref.getEntries()[idx]); 538 return true; 539 } 540 }); 541 } 542 543 setAlertsEnabled(boolean alertsEnabled)544 private void setAlertsEnabled(boolean alertsEnabled) { 545 if (mSevereCheckBox != null) { 546 mSevereCheckBox.setEnabled(alertsEnabled); 547 mSevereCheckBox.setChecked(alertsEnabled); 548 } 549 if (mExtremeCheckBox != null) { 550 mExtremeCheckBox.setEnabled(alertsEnabled); 551 mExtremeCheckBox.setChecked(alertsEnabled); 552 } 553 if (mAmberCheckBox != null) { 554 mAmberCheckBox.setEnabled(alertsEnabled); 555 mAmberCheckBox.setChecked(alertsEnabled); 556 } 557 if (mAreaUpdateInfoCheckBox != null) { 558 mAreaUpdateInfoCheckBox.setEnabled(alertsEnabled); 559 mAreaUpdateInfoCheckBox.setChecked(alertsEnabled); 560 } 561 if (mAlertPreferencesCategory != null) { 562 mAlertPreferencesCategory.setEnabled(alertsEnabled); 563 } 564 if (mEmergencyAlertsCheckBox != null) { 565 mEmergencyAlertsCheckBox.setEnabled(alertsEnabled); 566 mEmergencyAlertsCheckBox.setChecked(alertsEnabled); 567 } 568 if (mPublicSafetyMessagesChannelCheckBox != null) { 569 mPublicSafetyMessagesChannelCheckBox.setEnabled(alertsEnabled); 570 mPublicSafetyMessagesChannelCheckBox.setChecked(alertsEnabled); 571 } 572 if (mStateLocalTestCheckBox != null) { 573 mStateLocalTestCheckBox.setEnabled(alertsEnabled); 574 mStateLocalTestCheckBox.setChecked(alertsEnabled); 575 } 576 if (mTestCheckBox != null) { 577 mTestCheckBox.setEnabled(alertsEnabled); 578 mTestCheckBox.setChecked(alertsEnabled); 579 } 580 } 581 582 @Override onResume()583 public void onResume() { 584 super.onResume(); 585 updatePreferenceVisibility(); 586 } 587 588 @Override onDestroy()589 public void onDestroy() { 590 super.onDestroy(); 591 LocalBroadcastManager.getInstance(getContext()) 592 .unregisterReceiver(mTestingModeChangedReeiver); 593 } 594 } 595 isTestAlertsToggleVisible(Context context)596 public static boolean isTestAlertsToggleVisible(Context context) { 597 CellBroadcastChannelManager channelManager = new CellBroadcastChannelManager(context, 598 SubscriptionManager.DEFAULT_SUBSCRIPTION_ID); 599 Resources res = CellBroadcastSettings.getResources(context, 600 SubscriptionManager.DEFAULT_SUBSCRIPTION_ID); 601 boolean isTestAlertsAvailable = !channelManager.getCellBroadcastChannelRanges( 602 R.array.required_monthly_test_range_strings).isEmpty() 603 || !channelManager.getCellBroadcastChannelRanges( 604 R.array.exercise_alert_range_strings).isEmpty() 605 || !channelManager.getCellBroadcastChannelRanges( 606 R.array.operator_defined_alert_range_strings).isEmpty() 607 || !channelManager.getCellBroadcastChannelRanges( 608 R.array.etws_test_alerts_range_strings).isEmpty(); 609 610 return (res.getBoolean(R.bool.show_test_settings) 611 || CellBroadcastReceiver.isTestingMode(context)) 612 && isTestAlertsAvailable; 613 } 614 isFeatureEnabled(Context context, String feature, boolean defaultValue)615 public static boolean isFeatureEnabled(Context context, String feature, boolean defaultValue) { 616 CarrierConfigManager configManager = 617 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE); 618 619 if (configManager != null) { 620 PersistableBundle carrierConfig = configManager.getConfig(); 621 if (carrierConfig != null) { 622 return carrierConfig.getBoolean(feature, defaultValue); 623 } 624 } 625 626 return defaultValue; 627 } 628 629 /** 630 * Override used by tests so that we don't call 631 * SubscriptionManager.getResourcesForSubId, which is a static unmockable 632 * method. 633 */ 634 @VisibleForTesting setUseResourcesForSubId(boolean useResourcesForSubId)635 public static void setUseResourcesForSubId(boolean useResourcesForSubId) { 636 sUseResourcesForSubId = useResourcesForSubId; 637 } 638 639 /** 640 * Get the device resource based on SIM 641 * 642 * @param context Context 643 * @param subId Subscription index 644 * 645 * @return The resource 646 */ getResources(@onNull Context context, int subId)647 public static @NonNull Resources getResources(@NonNull Context context, int subId) { 648 if (subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID 649 || !SubscriptionManager.isValidSubscriptionId(subId) || !sUseResourcesForSubId) { 650 return context.getResources(); 651 } 652 653 if (sResourcesCache.containsKey(subId)) { 654 return sResourcesCache.get(subId); 655 } 656 657 Resources res = SubscriptionManager.getResourcesForSubId(context, subId); 658 sResourcesCache.put(subId, res); 659 660 return res; 661 } 662 } 663