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 master 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 master 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 onStart()167 public void onStart() { 168 super.onStart(); 169 getWindow().addSystemFlags( 170 android.view.WindowManager.LayoutParams 171 .SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); 172 } 173 174 @Override onOptionsItemSelected(MenuItem item)175 public boolean onOptionsItemSelected(MenuItem item) { 176 switch (item.getItemId()) { 177 // Respond to the action bar's Up/Home button 178 case android.R.id.home: 179 finish(); 180 return true; 181 } 182 return super.onOptionsItemSelected(item); 183 } 184 185 /** 186 * New fragment-style implementation of preferences. 187 */ 188 public static class CellBroadcastSettingsFragment extends PreferenceFragment { 189 190 private TwoStatePreference mExtremeCheckBox; 191 private TwoStatePreference mSevereCheckBox; 192 private TwoStatePreference mAmberCheckBox; 193 private TwoStatePreference mMasterToggle; 194 private TwoStatePreference mPublicSafetyMessagesChannelCheckBox; 195 private TwoStatePreference mEmergencyAlertsCheckBox; 196 private ListPreference mReminderInterval; 197 private TwoStatePreference mOverrideDndCheckBox; 198 private TwoStatePreference mAreaUpdateInfoCheckBox; 199 private TwoStatePreference mTestCheckBox; 200 private TwoStatePreference mStateLocalTestCheckBox; 201 private TwoStatePreference mEnableVibrateCheckBox; 202 private Preference mAlertHistory; 203 private Preference mAlertsHeader; 204 private PreferenceCategory mAlertCategory; 205 private PreferenceCategory mAlertPreferencesCategory; 206 private boolean mDisableSevereWhenExtremeDisabled = true; 207 208 // WATCH 209 private TwoStatePreference mAlertReminder; 210 211 // Show checkbox for Presidential alerts in settings 212 private TwoStatePreference mPresidentialCheckBox; 213 214 // on/off switch in settings for receiving alert in second language code 215 private TwoStatePreference mReceiveCmasInSecondLanguageCheckBox; 216 217 private final BroadcastReceiver mTestingModeChangedReeiver = new BroadcastReceiver() { 218 @Override 219 public void onReceive(Context context, Intent intent) { 220 switch (intent.getAction()) { 221 case CellBroadcastReceiver.ACTION_TESTING_MODE_CHANGED: 222 updatePreferenceVisibility(); 223 break; 224 } 225 } 226 }; 227 228 @Override onCreatePreferences(Bundle savedInstanceState, String rootKey)229 public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { 230 231 LocalBroadcastManager.getInstance(getContext()) 232 .registerReceiver(mTestingModeChangedReeiver, new IntentFilter( 233 CellBroadcastReceiver.ACTION_TESTING_MODE_CHANGED)); 234 235 // Load the preferences from an XML resource 236 PackageManager pm = getActivity().getPackageManager(); 237 if (pm.hasSystemFeature(PackageManager.FEATURE_WATCH)) { 238 addPreferencesFromResource(R.xml.watch_preferences); 239 } else { 240 addPreferencesFromResource(R.xml.preferences); 241 } 242 243 PreferenceScreen preferenceScreen = getPreferenceScreen(); 244 245 mExtremeCheckBox = (TwoStatePreference) 246 findPreference(KEY_ENABLE_CMAS_EXTREME_THREAT_ALERTS); 247 mSevereCheckBox = (TwoStatePreference) 248 findPreference(KEY_ENABLE_CMAS_SEVERE_THREAT_ALERTS); 249 mAmberCheckBox = (TwoStatePreference) 250 findPreference(KEY_ENABLE_CMAS_AMBER_ALERTS); 251 mMasterToggle = (TwoStatePreference) 252 findPreference(KEY_ENABLE_ALERTS_MASTER_TOGGLE); 253 mPublicSafetyMessagesChannelCheckBox = (TwoStatePreference) 254 findPreference(KEY_ENABLE_PUBLIC_SAFETY_MESSAGES); 255 mEmergencyAlertsCheckBox = (TwoStatePreference) 256 findPreference(KEY_ENABLE_EMERGENCY_ALERTS); 257 mReminderInterval = (ListPreference) 258 findPreference(KEY_ALERT_REMINDER_INTERVAL); 259 mOverrideDndCheckBox = (TwoStatePreference) 260 findPreference(KEY_OVERRIDE_DND); 261 mAreaUpdateInfoCheckBox = (TwoStatePreference) 262 findPreference(KEY_ENABLE_AREA_UPDATE_INFO_ALERTS); 263 mTestCheckBox = (TwoStatePreference) 264 findPreference(KEY_ENABLE_TEST_ALERTS); 265 mStateLocalTestCheckBox = (TwoStatePreference) 266 findPreference(KEY_ENABLE_STATE_LOCAL_TEST_ALERTS); 267 mAlertHistory = findPreference(KEY_EMERGENCY_ALERT_HISTORY); 268 mAlertsHeader = findPreference(KEY_ALERTS_HEADER); 269 mReceiveCmasInSecondLanguageCheckBox = (TwoStatePreference) findPreference 270 (KEY_RECEIVE_CMAS_IN_SECOND_LANGUAGE); 271 mEnableVibrateCheckBox = findPreference(KEY_ENABLE_ALERT_VIBRATE); 272 273 // Show checkbox for Presidential alerts in settings 274 mPresidentialCheckBox = (TwoStatePreference) 275 findPreference(KEY_ENABLE_CMAS_PRESIDENTIAL_ALERTS); 276 277 if (pm.hasSystemFeature(PackageManager.FEATURE_WATCH)) { 278 mAlertReminder = (TwoStatePreference) 279 findPreference(KEY_WATCH_ALERT_REMINDER); 280 if (Integer.valueOf(mReminderInterval.getValue()) == 0) { 281 mAlertReminder.setChecked(false); 282 } else { 283 mAlertReminder.setChecked(true); 284 } 285 mAlertReminder.setOnPreferenceChangeListener((p, newVal) -> { 286 try { 287 mReminderInterval.setValueIndex((Boolean) newVal ? 1 : 3); 288 } catch (IndexOutOfBoundsException e) { 289 mReminderInterval.setValue(String.valueOf(0)); 290 Log.w(TAG, "Setting default value"); 291 } 292 return true; 293 }); 294 PreferenceScreen watchScreen = (PreferenceScreen) 295 findPreference(KEY_CATEGORY_ALERT_PREFERENCES); 296 watchScreen.removePreference(mReminderInterval); 297 } else { 298 mAlertPreferencesCategory = (PreferenceCategory) 299 findPreference(KEY_CATEGORY_ALERT_PREFERENCES); 300 mAlertCategory = (PreferenceCategory) 301 findPreference(KEY_CATEGORY_EMERGENCY_ALERTS); 302 } 303 304 Resources res = CellBroadcastSettings.getResources(getContext(), 305 SubscriptionManager.DEFAULT_SUBSCRIPTION_ID); 306 307 SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext()); 308 mDisableSevereWhenExtremeDisabled = res.getBoolean( 309 R.bool.disable_severe_when_extreme_disabled); 310 311 // Handler for settings that require us to reconfigure enabled channels in radio 312 Preference.OnPreferenceChangeListener startConfigServiceListener = 313 new Preference.OnPreferenceChangeListener() { 314 @Override 315 public boolean onPreferenceChange(Preference pref, Object newValue) { 316 CellBroadcastReceiver.startConfigService(pref.getContext()); 317 318 if (mDisableSevereWhenExtremeDisabled) { 319 if (pref.getKey().equals(KEY_ENABLE_CMAS_EXTREME_THREAT_ALERTS)) { 320 boolean isExtremeAlertChecked = (Boolean) newValue; 321 if (mSevereCheckBox != null) { 322 mSevereCheckBox.setEnabled(isExtremeAlertChecked); 323 mSevereCheckBox.setChecked(false); 324 } 325 } 326 } 327 328 if (pref.getKey().equals(KEY_ENABLE_ALERTS_MASTER_TOGGLE)) { 329 boolean isEnableAlerts = (Boolean) newValue; 330 setAlertsEnabled(isEnableAlerts); 331 } 332 333 // Notify backup manager a backup pass is needed. 334 new BackupManager(getContext()).dataChanged(); 335 return true; 336 } 337 }; 338 339 initReminderIntervalList(); 340 341 if (mMasterToggle != null) { 342 mMasterToggle.setOnPreferenceChangeListener(startConfigServiceListener); 343 // If allow alerts are disabled, we turn all sub-alerts off. If it's enabled, we 344 // leave them as they are. 345 if (!mMasterToggle.isChecked()) { 346 setAlertsEnabled(false); 347 } 348 } 349 350 if (mAreaUpdateInfoCheckBox != null) { 351 mAreaUpdateInfoCheckBox.setOnPreferenceChangeListener(startConfigServiceListener); 352 } 353 if (mExtremeCheckBox != null) { 354 mExtremeCheckBox.setOnPreferenceChangeListener(startConfigServiceListener); 355 } 356 if (mPublicSafetyMessagesChannelCheckBox != null) { 357 mPublicSafetyMessagesChannelCheckBox.setOnPreferenceChangeListener( 358 startConfigServiceListener); 359 } 360 if (mEmergencyAlertsCheckBox != null) { 361 mEmergencyAlertsCheckBox.setOnPreferenceChangeListener(startConfigServiceListener); 362 } 363 if (mSevereCheckBox != null) { 364 mSevereCheckBox.setOnPreferenceChangeListener(startConfigServiceListener); 365 if (mDisableSevereWhenExtremeDisabled) { 366 if (mExtremeCheckBox != null) { 367 mSevereCheckBox.setEnabled(mExtremeCheckBox.isChecked()); 368 } 369 } 370 } 371 if (mAmberCheckBox != null) { 372 mAmberCheckBox.setOnPreferenceChangeListener(startConfigServiceListener); 373 } 374 if (mTestCheckBox != null) { 375 mTestCheckBox.setOnPreferenceChangeListener(startConfigServiceListener); 376 } 377 if (mStateLocalTestCheckBox != null) { 378 mStateLocalTestCheckBox.setOnPreferenceChangeListener( 379 startConfigServiceListener); 380 } 381 382 if (mOverrideDndCheckBox != null) { 383 if (!sp.getBoolean(KEY_OVERRIDE_DND_SETTINGS_CHANGED, false)) { 384 // If the user hasn't changed this settings yet, use the default settings 385 // from resource overlay. 386 mOverrideDndCheckBox.setChecked(res.getBoolean(R.bool.override_dnd_default)); 387 } 388 mOverrideDndCheckBox.setOnPreferenceChangeListener( 389 (pref, newValue) -> { 390 sp.edit().putBoolean(KEY_OVERRIDE_DND_SETTINGS_CHANGED, 391 true).apply(); 392 updateVibrationPreference((boolean) newValue); 393 return true; 394 }); 395 } 396 397 if (mAlertHistory != null) { 398 mAlertHistory.setOnPreferenceClickListener( 399 preference -> { 400 final Intent intent = new Intent(getContext(), 401 CellBroadcastListActivity.class); 402 startActivity(intent); 403 return true; 404 }); 405 } 406 407 updateVibrationPreference(sp.getBoolean(CellBroadcastSettings.KEY_OVERRIDE_DND, 408 false)); 409 updatePreferenceVisibility(); 410 } 411 412 /** 413 * Update the vibration preference based on override DND. If DND is overridden, then do 414 * not allow users to turn off vibration. 415 * 416 * @param overrideDnd {@code true} if the alert will be played at full volume, regardless 417 * DND settings. 418 */ updateVibrationPreference(boolean overrideDnd)419 private void updateVibrationPreference(boolean overrideDnd) { 420 if (mEnableVibrateCheckBox != null) { 421 if (overrideDnd) { 422 // If DND is enabled, always enable vibration. 423 mEnableVibrateCheckBox.setChecked(true); 424 } 425 // Grey out the preference if DND is overridden. 426 mEnableVibrateCheckBox.setEnabled(!overrideDnd); 427 } 428 } 429 430 /** 431 * Dynamically update each preference's visibility based on configuration. 432 */ updatePreferenceVisibility()433 private void updatePreferenceVisibility() { 434 Resources res = CellBroadcastSettings.getResources(getContext(), 435 SubscriptionManager.DEFAULT_SUBSCRIPTION_ID); 436 437 CellBroadcastChannelManager channelManager = new CellBroadcastChannelManager( 438 getContext(), SubscriptionManager.DEFAULT_SUBSCRIPTION_ID); 439 440 if (mPresidentialCheckBox != null) { 441 mPresidentialCheckBox.setVisible( 442 res.getBoolean(R.bool.show_presidential_alerts_settings)); 443 } 444 445 if (mExtremeCheckBox != null) { 446 mExtremeCheckBox.setVisible(res.getBoolean(R.bool.show_extreme_alert_settings) 447 && !channelManager.getCellBroadcastChannelRanges( 448 R.array.cmas_alert_extreme_channels_range_strings).isEmpty()); 449 } 450 451 if (mSevereCheckBox != null) { 452 mSevereCheckBox.setVisible(res.getBoolean(R.bool.show_severe_alert_settings) 453 && !channelManager.getCellBroadcastChannelRanges( 454 R.array.cmas_alerts_severe_range_strings).isEmpty()); 455 } 456 457 if (mAmberCheckBox != null) { 458 mAmberCheckBox.setVisible(res.getBoolean(R.bool.show_amber_alert_settings) 459 && !channelManager.getCellBroadcastChannelRanges( 460 R.array.cmas_amber_alerts_channels_range_strings).isEmpty()); 461 } 462 463 if (mPublicSafetyMessagesChannelCheckBox != null) { 464 mPublicSafetyMessagesChannelCheckBox.setVisible( 465 res.getBoolean(R.bool.show_public_safety_settings) 466 && !channelManager.getCellBroadcastChannelRanges( 467 R.array.public_safety_messages_channels_range_strings) 468 .isEmpty()); 469 } 470 471 if (mTestCheckBox != null) { 472 mTestCheckBox.setVisible(isTestAlertsToggleVisible(getContext())); 473 } 474 475 if (mEmergencyAlertsCheckBox != null) { 476 mEmergencyAlertsCheckBox.setVisible(!channelManager.getCellBroadcastChannelRanges( 477 R.array.emergency_alerts_channels_range_strings).isEmpty()); 478 } 479 480 if (mStateLocalTestCheckBox != null) { 481 mStateLocalTestCheckBox.setVisible( 482 res.getBoolean(R.bool.show_state_local_test_settings) 483 && !channelManager.getCellBroadcastChannelRanges( 484 R.array.state_local_test_alert_range_strings).isEmpty()); 485 } 486 487 if (mReceiveCmasInSecondLanguageCheckBox != null) { 488 mReceiveCmasInSecondLanguageCheckBox.setVisible(!res.getString( 489 R.string.emergency_alert_second_language_code).isEmpty()); 490 } 491 492 if (mAreaUpdateInfoCheckBox != null) { 493 mAreaUpdateInfoCheckBox.setVisible( 494 res.getBoolean(R.bool.config_showAreaUpdateInfoSettings)); 495 } 496 497 if (mOverrideDndCheckBox != null) { 498 mOverrideDndCheckBox.setVisible(res.getBoolean(R.bool.show_override_dnd_settings)); 499 } 500 501 if (mEnableVibrateCheckBox != null) { 502 // Only show vibrate toggle when override DND toggle is available to users, or when 503 // override DND default is turned off. 504 // In some countries, override DND is always on, which means vibration is always on. 505 // In that case, no need to show vibration toggle for users. 506 mEnableVibrateCheckBox.setVisible( 507 res.getBoolean(R.bool.show_override_dnd_settings) 508 || !res.getBoolean(R.bool.override_dnd_default)); 509 } 510 if (mAlertsHeader != null) { 511 mAlertsHeader.setVisible( 512 !getContext().getString(R.string.alerts_header_summary).isEmpty()); 513 } 514 } 515 initReminderIntervalList()516 private void initReminderIntervalList() { 517 Resources res = CellBroadcastSettings.getResources( 518 getContext(), SubscriptionManager.DEFAULT_SUBSCRIPTION_ID); 519 520 String[] activeValues = 521 res.getStringArray(R.array.alert_reminder_interval_active_values); 522 String[] allEntries = res.getStringArray(R.array.alert_reminder_interval_entries); 523 String[] newEntries = new String[activeValues.length]; 524 525 // Only add active interval to the list 526 for (int i = 0; i < activeValues.length; i++) { 527 int index = mReminderInterval.findIndexOfValue(activeValues[i]); 528 if (index != -1) { 529 newEntries[i] = allEntries[index]; 530 if (DBG) Log.d(TAG, "Added " + allEntries[index]); 531 } else { 532 Log.e(TAG, "Can't find " + activeValues[i]); 533 } 534 } 535 536 mReminderInterval.setEntries(newEntries); 537 mReminderInterval.setEntryValues(activeValues); 538 mReminderInterval.setSummary(mReminderInterval.getEntry()); 539 mReminderInterval.setOnPreferenceChangeListener( 540 new Preference.OnPreferenceChangeListener() { 541 @Override 542 public boolean onPreferenceChange(Preference pref, Object newValue) { 543 final ListPreference listPref = (ListPreference) pref; 544 final int idx = listPref.findIndexOfValue((String) newValue); 545 listPref.setSummary(listPref.getEntries()[idx]); 546 return true; 547 } 548 }); 549 } 550 551 setAlertsEnabled(boolean alertsEnabled)552 private void setAlertsEnabled(boolean alertsEnabled) { 553 if (mSevereCheckBox != null) { 554 mSevereCheckBox.setEnabled(alertsEnabled); 555 mSevereCheckBox.setChecked(alertsEnabled); 556 } 557 if (mExtremeCheckBox != null) { 558 mExtremeCheckBox.setEnabled(alertsEnabled); 559 mExtremeCheckBox.setChecked(alertsEnabled); 560 } 561 if (mAmberCheckBox != null) { 562 mAmberCheckBox.setEnabled(alertsEnabled); 563 mAmberCheckBox.setChecked(alertsEnabled); 564 } 565 if (mAreaUpdateInfoCheckBox != null) { 566 mAreaUpdateInfoCheckBox.setEnabled(alertsEnabled); 567 mAreaUpdateInfoCheckBox.setChecked(alertsEnabled); 568 } 569 if (mAlertPreferencesCategory != null) { 570 mAlertPreferencesCategory.setEnabled(alertsEnabled); 571 } 572 if (mEmergencyAlertsCheckBox != null) { 573 mEmergencyAlertsCheckBox.setEnabled(alertsEnabled); 574 mEmergencyAlertsCheckBox.setChecked(alertsEnabled); 575 } 576 if (mPublicSafetyMessagesChannelCheckBox != null) { 577 mPublicSafetyMessagesChannelCheckBox.setEnabled(alertsEnabled); 578 mPublicSafetyMessagesChannelCheckBox.setChecked(alertsEnabled); 579 } 580 if (mStateLocalTestCheckBox != null) { 581 mStateLocalTestCheckBox.setEnabled(alertsEnabled); 582 mStateLocalTestCheckBox.setChecked(alertsEnabled); 583 } 584 if (mTestCheckBox != null) { 585 mTestCheckBox.setEnabled(alertsEnabled); 586 mTestCheckBox.setChecked(alertsEnabled); 587 } 588 } 589 590 @Override onResume()591 public void onResume() { 592 super.onResume(); 593 updatePreferenceVisibility(); 594 } 595 596 @Override onDestroy()597 public void onDestroy() { 598 super.onDestroy(); 599 LocalBroadcastManager.getInstance(getContext()) 600 .unregisterReceiver(mTestingModeChangedReeiver); 601 } 602 } 603 isTestAlertsToggleVisible(Context context)604 public static boolean isTestAlertsToggleVisible(Context context) { 605 CellBroadcastChannelManager channelManager = new CellBroadcastChannelManager(context, 606 SubscriptionManager.DEFAULT_SUBSCRIPTION_ID); 607 Resources res = CellBroadcastSettings.getResources(context, 608 SubscriptionManager.DEFAULT_SUBSCRIPTION_ID); 609 boolean isTestAlertsAvailable = !channelManager.getCellBroadcastChannelRanges( 610 R.array.required_monthly_test_range_strings).isEmpty() 611 || !channelManager.getCellBroadcastChannelRanges( 612 R.array.exercise_alert_range_strings).isEmpty() 613 || !channelManager.getCellBroadcastChannelRanges( 614 R.array.operator_defined_alert_range_strings).isEmpty() 615 || !channelManager.getCellBroadcastChannelRanges( 616 R.array.etws_test_alerts_range_strings).isEmpty(); 617 618 return (res.getBoolean(R.bool.show_test_settings) 619 || CellBroadcastReceiver.isTestingMode(context)) 620 && isTestAlertsAvailable; 621 } 622 isFeatureEnabled(Context context, String feature, boolean defaultValue)623 public static boolean isFeatureEnabled(Context context, String feature, boolean defaultValue) { 624 CarrierConfigManager configManager = 625 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE); 626 627 if (configManager != null) { 628 PersistableBundle carrierConfig = configManager.getConfig(); 629 if (carrierConfig != null) { 630 return carrierConfig.getBoolean(feature, defaultValue); 631 } 632 } 633 634 return defaultValue; 635 } 636 637 /** 638 * Override used by tests so that we don't call 639 * SubscriptionManager.getResourcesForSubId, which is a static unmockable 640 * method. 641 */ 642 @VisibleForTesting setUseResourcesForSubId(boolean useResourcesForSubId)643 public static void setUseResourcesForSubId(boolean useResourcesForSubId) { 644 sUseResourcesForSubId = useResourcesForSubId; 645 } 646 647 /** 648 * Get the device resource based on SIM 649 * 650 * @param context Context 651 * @param subId Subscription index 652 * 653 * @return The resource 654 */ getResources(@onNull Context context, int subId)655 public static @NonNull Resources getResources(@NonNull Context context, int subId) { 656 if (subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID 657 || !SubscriptionManager.isValidSubscriptionId(subId) || !sUseResourcesForSubId) { 658 return context.getResources(); 659 } 660 661 if (sResourcesCache.containsKey(subId)) { 662 return sResourcesCache.get(subId); 663 } 664 665 Resources res = SubscriptionManager.getResourcesForSubId(context, subId); 666 sResourcesCache.put(subId, res); 667 668 return res; 669 } 670 } 671