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.app.backup.BackupManager; 20 import android.content.Context; 21 import android.content.res.Resources; 22 import android.os.Bundle; 23 import android.os.PersistableBundle; 24 import android.os.UserManager; 25 import android.preference.ListPreference; 26 import android.preference.Preference; 27 import android.preference.PreferenceActivity; 28 import android.preference.PreferenceCategory; 29 import android.preference.PreferenceFragment; 30 import android.preference.PreferenceScreen; 31 import android.preference.TwoStatePreference; 32 import android.provider.Settings; 33 import android.telephony.CarrierConfigManager; 34 import android.telephony.SubscriptionManager; 35 import android.telephony.TelephonyManager; 36 import android.util.Log; 37 38 /** 39 * Settings activity for the cell broadcast receiver. 40 */ 41 public class CellBroadcastSettings extends PreferenceActivity { 42 43 private static final String TAG = "CellBroadcastSettings"; 44 45 private static final boolean DBG = false; 46 47 // Preference key for whether to enable emergency notifications (default enabled). 48 public static final String KEY_ENABLE_EMERGENCY_ALERTS = "enable_emergency_alerts"; 49 50 // Enable vibration on alert (unless master volume is silent). 51 public static final String KEY_ENABLE_ALERT_VIBRATE = "enable_alert_vibrate"; 52 53 // Speak contents of alert after playing the alert sound. 54 public static final String KEY_ENABLE_ALERT_SPEECH = "enable_alert_speech"; 55 56 // Preference category for emergency alert and CMAS settings. 57 public static final String KEY_CATEGORY_ALERT_SETTINGS = "category_alert_settings"; 58 59 // Preference category for ETWS related settings. 60 public static final String KEY_CATEGORY_ETWS_SETTINGS = "category_etws_settings"; 61 62 // Whether to display CMAS extreme threat notifications (default is enabled). 63 public static final String KEY_ENABLE_CMAS_EXTREME_THREAT_ALERTS = 64 "enable_cmas_extreme_threat_alerts"; 65 66 // Whether to display CMAS severe threat notifications (default is enabled). 67 public static final String KEY_ENABLE_CMAS_SEVERE_THREAT_ALERTS = 68 "enable_cmas_severe_threat_alerts"; 69 70 // Whether to display CMAS amber alert messages (default is enabled). 71 public static final String KEY_ENABLE_CMAS_AMBER_ALERTS = "enable_cmas_amber_alerts"; 72 73 // Preference category for development settings (enabled by settings developer options toggle). 74 public static final String KEY_CATEGORY_DEV_SETTINGS = "category_dev_settings"; 75 76 // Whether to display ETWS test messages (default is disabled). 77 public static final String KEY_ENABLE_ETWS_TEST_ALERTS = "enable_etws_test_alerts"; 78 79 // Whether to display CMAS monthly test messages (default is disabled). 80 public static final String KEY_ENABLE_CMAS_TEST_ALERTS = "enable_cmas_test_alerts"; 81 82 // Preference category for Brazil specific settings. 83 public static final String KEY_CATEGORY_BRAZIL_SETTINGS = "category_brazil_settings"; 84 85 // Preference key for whether to enable channel 50 notifications 86 // Enabled by default for phones sold in Brazil, otherwise this setting may be hidden. 87 public static final String KEY_ENABLE_CHANNEL_50_ALERTS = "enable_channel_50_alerts"; 88 89 // Preference key for initial opt-in/opt-out dialog. 90 public static final String KEY_SHOW_CMAS_OPT_OUT_DIALOG = "show_cmas_opt_out_dialog"; 91 92 // Alert reminder interval ("once" = single 2 minute reminder). 93 public static final String KEY_ALERT_REMINDER_INTERVAL = "alert_reminder_interval"; 94 95 // Brazil country code 96 private static final String COUNTRY_BRAZIL = "br"; 97 98 @Override 99 public void onCreate(Bundle savedInstanceState) { 100 super.onCreate(savedInstanceState); 101 102 UserManager userManager = (UserManager) getSystemService(Context.USER_SERVICE); 103 if (userManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_CELL_BROADCASTS)) { 104 setContentView(R.layout.cell_broadcast_disallowed_preference_screen); 105 return; 106 } 107 108 // Display the fragment as the main content. 109 getFragmentManager().beginTransaction().replace(android.R.id.content, 110 new CellBroadcastSettingsFragment()).commit(); 111 } 112 113 /** 114 * New fragment-style implementation of preferences. 115 */ 116 public static class CellBroadcastSettingsFragment extends PreferenceFragment { 117 118 private TwoStatePreference mExtremeCheckBox; 119 private TwoStatePreference mSevereCheckBox; 120 private TwoStatePreference mAmberCheckBox; 121 private TwoStatePreference mEmergencyCheckBox; 122 private ListPreference mReminderInterval; 123 private TwoStatePreference mSpeechCheckBox; 124 private TwoStatePreference mEtwsTestCheckBox; 125 private TwoStatePreference mChannel50CheckBox; 126 private TwoStatePreference mCmasTestCheckBox; 127 private PreferenceCategory mAlertCategory; 128 private PreferenceCategory mETWSSettingCategory; 129 private boolean mDisableSevereWhenExtremeDisabled = true; 130 131 @Override 132 public void onCreate(Bundle savedInstanceState) { 133 super.onCreate(savedInstanceState); 134 135 // Load the preferences from an XML resource 136 addPreferencesFromResource(R.xml.preferences); 137 138 PreferenceScreen preferenceScreen = getPreferenceScreen(); 139 140 mExtremeCheckBox = (TwoStatePreference) 141 findPreference(KEY_ENABLE_CMAS_EXTREME_THREAT_ALERTS); 142 mSevereCheckBox = (TwoStatePreference) 143 findPreference(KEY_ENABLE_CMAS_SEVERE_THREAT_ALERTS); 144 mAmberCheckBox = (TwoStatePreference) 145 findPreference(KEY_ENABLE_CMAS_AMBER_ALERTS); 146 mEmergencyCheckBox = (TwoStatePreference) 147 findPreference(KEY_ENABLE_EMERGENCY_ALERTS); 148 mReminderInterval = (ListPreference) 149 findPreference(KEY_ALERT_REMINDER_INTERVAL); 150 mSpeechCheckBox = (TwoStatePreference) 151 findPreference(KEY_ENABLE_ALERT_SPEECH); 152 mEtwsTestCheckBox = (TwoStatePreference) 153 findPreference(KEY_ENABLE_ETWS_TEST_ALERTS); 154 mChannel50CheckBox = (TwoStatePreference) 155 findPreference(KEY_ENABLE_CHANNEL_50_ALERTS); 156 mCmasTestCheckBox = (TwoStatePreference) 157 findPreference(KEY_ENABLE_CMAS_TEST_ALERTS); 158 mAlertCategory = (PreferenceCategory) 159 findPreference(KEY_CATEGORY_ALERT_SETTINGS); 160 mETWSSettingCategory = (PreferenceCategory) 161 findPreference(KEY_CATEGORY_ETWS_SETTINGS); 162 163 mDisableSevereWhenExtremeDisabled = isFeatureEnabled(getContext(), 164 CarrierConfigManager.KEY_DISABLE_SEVERE_WHEN_EXTREME_DISABLED_BOOL, true); 165 166 // Handler for settings that require us to reconfigure enabled channels in radio 167 Preference.OnPreferenceChangeListener startConfigServiceListener = 168 new Preference.OnPreferenceChangeListener() { 169 @Override 170 public boolean onPreferenceChange(Preference pref, Object newValue) { 171 CellBroadcastReceiver.startConfigService(pref.getContext()); 172 173 if (mDisableSevereWhenExtremeDisabled) { 174 if (pref.getKey().equals(KEY_ENABLE_CMAS_EXTREME_THREAT_ALERTS)) { 175 boolean isExtremeAlertChecked = (Boolean) newValue; 176 if (mSevereCheckBox != null) { 177 mSevereCheckBox.setEnabled(isExtremeAlertChecked); 178 mSevereCheckBox.setChecked(false); 179 } 180 } 181 } 182 183 // Notify backup manager a backup pass is needed. 184 new BackupManager(getContext()).dataChanged(); 185 return true; 186 } 187 }; 188 189 // Show extra settings when developer options is enabled in settings. 190 boolean enableDevSettings = Settings.Global.getInt(getContext().getContentResolver(), 191 Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0) != 0; 192 193 Resources res = getResources(); 194 boolean showEtwsSettings = res.getBoolean(R.bool.show_etws_settings); 195 196 initReminderIntervalList(); 197 198 boolean forceDisableEtwsCmasTest = CellBroadcastSettings.isFeatureEnabled(getContext(), 199 CarrierConfigManager.KEY_CARRIER_FORCE_DISABLE_ETWS_CMAS_TEST_BOOL, false); 200 201 boolean emergencyAlertOnOffOptionEnabled = isFeatureEnabled(getContext(), 202 CarrierConfigManager.KEY_ALWAYS_SHOW_EMERGENCY_ALERT_ONOFF_BOOL, false); 203 204 if (enableDevSettings || showEtwsSettings || emergencyAlertOnOffOptionEnabled) { 205 // enable/disable all alerts except CMAS presidential alerts. 206 if (mEmergencyCheckBox != null) { 207 mEmergencyCheckBox.setOnPreferenceChangeListener(startConfigServiceListener); 208 } 209 } else { 210 mAlertCategory.removePreference(mEmergencyCheckBox); 211 } 212 213 // Show alert settings and ETWS categories for ETWS builds and developer mode. 214 if (enableDevSettings || showEtwsSettings) { 215 216 if (forceDisableEtwsCmasTest) { 217 // Remove ETWS test preference. 218 preferenceScreen.removePreference(mETWSSettingCategory); 219 220 PreferenceCategory devSettingCategory = 221 (PreferenceCategory) findPreference(KEY_CATEGORY_DEV_SETTINGS); 222 223 // Remove CMAS test preference. 224 if (devSettingCategory != null) { 225 devSettingCategory.removePreference(mCmasTestCheckBox); 226 } 227 } 228 } else { 229 mAlertCategory.removePreference(mSpeechCheckBox); 230 // Remove ETWS test preference category. 231 preferenceScreen.removePreference(mETWSSettingCategory); 232 } 233 234 if (!res.getBoolean(R.bool.show_cmas_settings)) { 235 // Remove CMAS preference items in emergency alert category. 236 mAlertCategory.removePreference(mExtremeCheckBox); 237 mAlertCategory.removePreference(mSevereCheckBox); 238 mAlertCategory.removePreference(mAmberCheckBox); 239 } 240 241 TelephonyManager tm = (TelephonyManager) getContext().getSystemService( 242 Context.TELEPHONY_SERVICE); 243 244 // We display channel 50 enable/disable menu if one of the followings is true 245 // 1. The setting through resource overlay is set to true. 246 // 2. At least one SIM inserted is Brazilian SIM. 247 248 boolean enableChannel50Support = res.getBoolean(R.bool.show_brazil_settings); 249 250 if (!enableChannel50Support) { 251 SubscriptionManager sm = SubscriptionManager.from(getContext()); 252 for (int subId : sm.getActiveSubscriptionIdList()) { 253 if (COUNTRY_BRAZIL.equals(tm.getSimCountryIso(subId))) { 254 enableChannel50Support = true; 255 break; 256 } 257 } 258 } 259 260 if (!enableChannel50Support) { 261 preferenceScreen.removePreference(findPreference(KEY_CATEGORY_BRAZIL_SETTINGS)); 262 } 263 if (!enableDevSettings) { 264 preferenceScreen.removePreference(findPreference(KEY_CATEGORY_DEV_SETTINGS)); 265 } 266 267 if (mChannel50CheckBox != null) { 268 mChannel50CheckBox.setOnPreferenceChangeListener(startConfigServiceListener); 269 } 270 if (mEtwsTestCheckBox != null) { 271 mEtwsTestCheckBox.setOnPreferenceChangeListener(startConfigServiceListener); 272 } 273 if (mExtremeCheckBox != null) { 274 mExtremeCheckBox.setOnPreferenceChangeListener(startConfigServiceListener); 275 } 276 277 if (mSevereCheckBox != null) { 278 mSevereCheckBox.setOnPreferenceChangeListener(startConfigServiceListener); 279 if (mDisableSevereWhenExtremeDisabled) { 280 if (mExtremeCheckBox != null) { 281 mSevereCheckBox.setEnabled(mExtremeCheckBox.isChecked()); 282 } 283 } 284 } 285 if (mAmberCheckBox != null) { 286 mAmberCheckBox.setOnPreferenceChangeListener(startConfigServiceListener); 287 } 288 if (mCmasTestCheckBox != null) { 289 mCmasTestCheckBox.setOnPreferenceChangeListener(startConfigServiceListener); 290 } 291 } 292 293 private void initReminderIntervalList() { 294 295 String[] activeValues = 296 getResources().getStringArray(R.array.alert_reminder_interval_active_values); 297 String[] allEntries = 298 getResources().getStringArray(R.array.alert_reminder_interval_entries); 299 String[] newEntries = new String[activeValues.length]; 300 301 // Only add active interval to the list 302 for (int i = 0; i < activeValues.length; i++) { 303 int index = mReminderInterval.findIndexOfValue(activeValues[i]); 304 if (index != -1) { 305 newEntries[i] = allEntries[index]; 306 if (DBG) Log.d(TAG, "Added " + allEntries[index]); 307 } else { 308 Log.e(TAG, "Can't find " + activeValues[i]); 309 } 310 } 311 312 mReminderInterval.setEntries(newEntries); 313 mReminderInterval.setEntryValues(activeValues); 314 mReminderInterval.setSummary(mReminderInterval.getEntry()); 315 mReminderInterval.setOnPreferenceChangeListener( 316 new Preference.OnPreferenceChangeListener() { 317 @Override 318 public boolean onPreferenceChange(Preference pref, Object newValue) { 319 final ListPreference listPref = (ListPreference) pref; 320 final int idx = listPref.findIndexOfValue((String) newValue); 321 listPref.setSummary(listPref.getEntries()[idx]); 322 return true; 323 } 324 }); 325 } 326 } 327 328 public static boolean isFeatureEnabled(Context context, String feature, boolean defaultValue) { 329 int subId = SubscriptionManager.getDefaultSmsSubscriptionId(); 330 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { 331 subId = SubscriptionManager.getDefaultSubscriptionId(); 332 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { 333 return defaultValue; 334 } 335 } 336 337 CarrierConfigManager configManager = 338 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE); 339 340 if (configManager != null) { 341 PersistableBundle carrierConfig = configManager.getConfigForSubId(subId); 342 343 if (carrierConfig != null) { 344 return carrierConfig.getBoolean(feature, defaultValue); 345 } 346 } 347 348 return defaultValue; 349 } 350 } 351