Home | History | Annotate | Download | only in cellbroadcastreceiver
      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