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