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.ActionBar;
     20 import android.app.Activity;
     21 import android.app.Fragment;
     22 import android.app.backup.BackupManager;
     23 import android.content.Context;
     24 import android.content.Intent;
     25 import android.content.res.Resources;
     26 import android.os.Bundle;
     27 import android.os.PersistableBundle;
     28 import android.os.UserManager;
     29 import android.provider.Settings;
     30 import android.support.v14.preference.PreferenceFragment;
     31 import android.support.v7.preference.ListPreference;
     32 import android.support.v7.preference.Preference;
     33 import android.support.v7.preference.PreferenceCategory;
     34 import android.support.v7.preference.PreferenceScreen;
     35 import android.support.v7.preference.TwoStatePreference;
     36 import android.telephony.CarrierConfigManager;
     37 import android.telephony.SubscriptionManager;
     38 import android.util.Log;
     39 import android.view.MenuItem;
     40 
     41 /**
     42  * Settings activity for the cell broadcast receiver.
     43  */
     44 public class CellBroadcastSettings extends Activity {
     45 
     46     private static final String TAG = "CellBroadcastSettings";
     47 
     48     private static final boolean DBG = false;
     49 
     50     // Preference key for whether to enable emergency notifications (default enabled).
     51     public static final String KEY_ENABLE_EMERGENCY_ALERTS = "enable_emergency_alerts";
     52 
     53     // Enable vibration on alert (unless master volume is silent).
     54     public static final String KEY_ENABLE_ALERT_VIBRATE = "enable_alert_vibrate";
     55 
     56     // Speak contents of alert after playing the alert sound.
     57     public static final String KEY_ENABLE_ALERT_SPEECH = "enable_alert_speech";
     58 
     59     // Always play at full volume when playing the alert sound.
     60     public static final String KEY_USE_FULL_VOLUME = "use_full_volume";
     61 
     62     // Preference category for emergency alert and CMAS settings.
     63     public static final String KEY_CATEGORY_EMERGENCY_ALERTS = "category_emergency_alerts";
     64 
     65     // Preference category for alert preferences.
     66     public static final String KEY_CATEGORY_ALERT_PREFERENCES = "category_alert_preferences";
     67 
     68     // Whether to display CMAS extreme threat notifications (default is enabled).
     69     public static final String KEY_ENABLE_CMAS_EXTREME_THREAT_ALERTS =
     70             "enable_cmas_extreme_threat_alerts";
     71 
     72     // Whether to display CMAS severe threat notifications (default is enabled).
     73     public static final String KEY_ENABLE_CMAS_SEVERE_THREAT_ALERTS =
     74             "enable_cmas_severe_threat_alerts";
     75 
     76     // Whether to display CMAS amber alert messages (default is enabled).
     77     public static final String KEY_ENABLE_CMAS_AMBER_ALERTS = "enable_cmas_amber_alerts";
     78 
     79     // Preference category for development settings (enabled by settings developer options toggle).
     80     public static final String KEY_CATEGORY_DEV_SETTINGS = "category_dev_settings";
     81 
     82     // Whether to display ETWS test messages (default is disabled).
     83     public static final String KEY_ENABLE_ETWS_TEST_ALERTS = "enable_etws_test_alerts";
     84 
     85     // Whether to display CMAS monthly test messages (default is disabled).
     86     public static final String KEY_ENABLE_CMAS_TEST_ALERTS = "enable_cmas_test_alerts";
     87 
     88     // Preference key for whether to enable area update information notifications
     89     // Enabled by default for phones sold in Brazil and India, otherwise this setting may be hidden.
     90     public static final String KEY_ENABLE_AREA_UPDATE_INFO_ALERTS =
     91             "enable_area_update_info_alerts";
     92 
     93     // Preference key for initial opt-in/opt-out dialog.
     94     public static final String KEY_SHOW_CMAS_OPT_OUT_DIALOG = "show_cmas_opt_out_dialog";
     95 
     96     // Alert reminder interval ("once" = single 2 minute reminder).
     97     public static final String KEY_ALERT_REMINDER_INTERVAL = "alert_reminder_interval";
     98 
     99     // Preference key for emergency alerts history
    100     public static final String KEY_EMERGENCY_ALERT_HISTORY = "emergency_alert_history";
    101 
    102     @Override
    103     public void onCreate(Bundle savedInstanceState) {
    104         super.onCreate(savedInstanceState);
    105 
    106         ActionBar actionBar = getActionBar();
    107         if (actionBar != null) {
    108             // android.R.id.home will be triggered in onOptionsItemSelected()
    109             actionBar.setDisplayHomeAsUpEnabled(true);
    110         }
    111 
    112         UserManager userManager = (UserManager) getSystemService(Context.USER_SERVICE);
    113         if (userManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_CELL_BROADCASTS)) {
    114             setContentView(R.layout.cell_broadcast_disallowed_preference_screen);
    115             return;
    116         }
    117 
    118         // We only add new CellBroadcastSettingsFragment if no fragment is restored.
    119         Fragment fragment = getFragmentManager().findFragmentById(android.R.id.content);
    120         if (fragment == null) {
    121             getFragmentManager().beginTransaction().add(android.R.id.content,
    122                     new CellBroadcastSettingsFragment()).commit();
    123         }
    124     }
    125 
    126     @Override
    127     public boolean onOptionsItemSelected(MenuItem item) {
    128         switch (item.getItemId()) {
    129             // Respond to the action bar's Up/Home button
    130             case android.R.id.home:
    131                 finish();
    132                 return true;
    133         }
    134         return super.onOptionsItemSelected(item);
    135     }
    136 
    137     /**
    138      * New fragment-style implementation of preferences.
    139      */
    140     public static class CellBroadcastSettingsFragment extends PreferenceFragment {
    141 
    142         private TwoStatePreference mExtremeCheckBox;
    143         private TwoStatePreference mSevereCheckBox;
    144         private TwoStatePreference mAmberCheckBox;
    145         private TwoStatePreference mEmergencyCheckBox;
    146         private ListPreference mReminderInterval;
    147         private TwoStatePreference mSpeechCheckBox;
    148         private TwoStatePreference mFullVolumeCheckBox;
    149         private TwoStatePreference mEtwsTestCheckBox;
    150         private TwoStatePreference mAreaUpdateInfoCheckBox;
    151         private TwoStatePreference mCmasTestCheckBox;
    152         private Preference mAlertHistory;
    153         private PreferenceCategory mAlertCategory;
    154         private PreferenceCategory mAlertPreferencesCategory;
    155         private PreferenceCategory mDevSettingCategory;
    156         private boolean mDisableSevereWhenExtremeDisabled = true;
    157 
    158         @Override
    159         public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
    160             // Load the preferences from an XML resource
    161             addPreferencesFromResource(R.xml.preferences);
    162 
    163             PreferenceScreen preferenceScreen = getPreferenceScreen();
    164 
    165             mExtremeCheckBox = (TwoStatePreference)
    166                     findPreference(KEY_ENABLE_CMAS_EXTREME_THREAT_ALERTS);
    167             mSevereCheckBox = (TwoStatePreference)
    168                     findPreference(KEY_ENABLE_CMAS_SEVERE_THREAT_ALERTS);
    169             mAmberCheckBox = (TwoStatePreference)
    170                     findPreference(KEY_ENABLE_CMAS_AMBER_ALERTS);
    171             mEmergencyCheckBox = (TwoStatePreference)
    172                     findPreference(KEY_ENABLE_EMERGENCY_ALERTS);
    173             mReminderInterval = (ListPreference)
    174                     findPreference(KEY_ALERT_REMINDER_INTERVAL);
    175             mSpeechCheckBox = (TwoStatePreference)
    176                     findPreference(KEY_ENABLE_ALERT_SPEECH);
    177             mFullVolumeCheckBox = (TwoStatePreference)
    178                     findPreference(KEY_USE_FULL_VOLUME);
    179             mEtwsTestCheckBox = (TwoStatePreference)
    180                     findPreference(KEY_ENABLE_ETWS_TEST_ALERTS);
    181             mAreaUpdateInfoCheckBox = (TwoStatePreference)
    182                     findPreference(KEY_ENABLE_AREA_UPDATE_INFO_ALERTS);
    183             mCmasTestCheckBox = (TwoStatePreference)
    184                     findPreference(KEY_ENABLE_CMAS_TEST_ALERTS);
    185             mAlertHistory = findPreference(KEY_EMERGENCY_ALERT_HISTORY);
    186             mAlertCategory = (PreferenceCategory)
    187                     findPreference(KEY_CATEGORY_EMERGENCY_ALERTS);
    188             mAlertPreferencesCategory = (PreferenceCategory)
    189                     findPreference(KEY_CATEGORY_ALERT_PREFERENCES);
    190             mDevSettingCategory = (PreferenceCategory)
    191                     findPreference(KEY_CATEGORY_DEV_SETTINGS);
    192 
    193             mDisableSevereWhenExtremeDisabled = isFeatureEnabled(getContext(),
    194                     CarrierConfigManager.KEY_DISABLE_SEVERE_WHEN_EXTREME_DISABLED_BOOL, true);
    195 
    196             // Handler for settings that require us to reconfigure enabled channels in radio
    197             Preference.OnPreferenceChangeListener startConfigServiceListener =
    198                     new Preference.OnPreferenceChangeListener() {
    199                         @Override
    200                         public boolean onPreferenceChange(Preference pref, Object newValue) {
    201                             CellBroadcastReceiver.startConfigService(pref.getContext());
    202 
    203                             if (mDisableSevereWhenExtremeDisabled) {
    204                                 if (pref.getKey().equals(KEY_ENABLE_CMAS_EXTREME_THREAT_ALERTS)) {
    205                                     boolean isExtremeAlertChecked = (Boolean) newValue;
    206                                     if (mSevereCheckBox != null) {
    207                                         mSevereCheckBox.setEnabled(isExtremeAlertChecked);
    208                                         mSevereCheckBox.setChecked(false);
    209                                     }
    210                                 }
    211                             }
    212 
    213                             if (pref.getKey().equals(KEY_ENABLE_EMERGENCY_ALERTS)) {
    214                                 boolean isEnableAlerts = (Boolean) newValue;
    215                                 setAlertsEnabled(isEnableAlerts);
    216                             }
    217 
    218                             // Notify backup manager a backup pass is needed.
    219                             new BackupManager(getContext()).dataChanged();
    220                             return true;
    221                         }
    222                     };
    223 
    224             // Show extra settings when developer options is enabled in settings.
    225             boolean enableDevSettings = Settings.Global.getInt(getContext().getContentResolver(),
    226                     Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0) != 0;
    227 
    228             Resources res = getResources();
    229 
    230             initReminderIntervalList();
    231 
    232             boolean forceDisableEtwsCmasTest = CellBroadcastSettings.isFeatureEnabled(getContext(),
    233                     CarrierConfigManager.KEY_CARRIER_FORCE_DISABLE_ETWS_CMAS_TEST_BOOL, false);
    234 
    235             boolean emergencyAlertOnOffOptionEnabled = isFeatureEnabled(getContext(),
    236                     CarrierConfigManager.KEY_ALWAYS_SHOW_EMERGENCY_ALERT_ONOFF_BOOL, false);
    237 
    238             if (enableDevSettings || emergencyAlertOnOffOptionEnabled) {
    239                 // enable/disable all alerts except CMAS presidential alerts.
    240                 if (mEmergencyCheckBox != null) {
    241                     mEmergencyCheckBox.setOnPreferenceChangeListener(startConfigServiceListener);
    242                 }
    243                 // If allow alerts are disabled, we turn all sub-alerts off. If it's enabled, we
    244                 // leave them as they are.
    245                 if (!mEmergencyCheckBox.isChecked()) {
    246                     setAlertsEnabled(false);
    247                 }
    248             } else {
    249                 preferenceScreen.removePreference(mEmergencyCheckBox);
    250             }
    251 
    252             // Show alert settings and ETWS categories for ETWS builds and developer mode.
    253             if (enableDevSettings) {
    254                 if (forceDisableEtwsCmasTest) {
    255                     if (mDevSettingCategory != null) {
    256                         // Remove ETWS test preference.
    257                         mDevSettingCategory.removePreference(mEtwsTestCheckBox);
    258                         // Remove CMAS test preference.
    259                         mDevSettingCategory.removePreference(mCmasTestCheckBox);
    260                     }
    261                 }
    262             } else {
    263                 preferenceScreen.removePreference(mDevSettingCategory);
    264             }
    265 
    266             if (!res.getBoolean(R.bool.show_cmas_settings)) {
    267                 // Remove CMAS preference items in emergency alert category.
    268                 mAlertCategory.removePreference(mExtremeCheckBox);
    269                 mAlertCategory.removePreference(mSevereCheckBox);
    270                 mAlertCategory.removePreference(mAmberCheckBox);
    271             }
    272 
    273             if (!Resources.getSystem().getBoolean(
    274                     com.android.internal.R.bool.config_showAreaUpdateInfoSettings)) {
    275                 mAlertCategory.removePreference(mAreaUpdateInfoCheckBox);
    276             }
    277 
    278             if (mAreaUpdateInfoCheckBox != null) {
    279                 mAreaUpdateInfoCheckBox.setOnPreferenceChangeListener(startConfigServiceListener);
    280             }
    281             if (mEtwsTestCheckBox != null) {
    282                 mEtwsTestCheckBox.setOnPreferenceChangeListener(startConfigServiceListener);
    283             }
    284             if (mExtremeCheckBox != null) {
    285                 mExtremeCheckBox.setOnPreferenceChangeListener(startConfigServiceListener);
    286             }
    287 
    288             if (mSevereCheckBox != null) {
    289                 mSevereCheckBox.setOnPreferenceChangeListener(startConfigServiceListener);
    290                 if (mDisableSevereWhenExtremeDisabled) {
    291                     if (mExtremeCheckBox != null) {
    292                         mSevereCheckBox.setEnabled(mExtremeCheckBox.isChecked());
    293                     }
    294                 }
    295             }
    296             if (mAmberCheckBox != null) {
    297                 mAmberCheckBox.setOnPreferenceChangeListener(startConfigServiceListener);
    298             }
    299             if (mCmasTestCheckBox != null) {
    300                 mCmasTestCheckBox.setOnPreferenceChangeListener(startConfigServiceListener);
    301             }
    302 
    303             if (mAlertHistory != null) {
    304                 mAlertHistory.setOnPreferenceClickListener(
    305                         new Preference.OnPreferenceClickListener() {
    306                             @Override
    307                             public boolean onPreferenceClick(final Preference preference) {
    308                                 final Intent intent = new Intent(getContext(),
    309                                         CellBroadcastListActivity.class);
    310                                 startActivity(intent);
    311                                 return true;
    312                             }
    313                         });
    314             }
    315         }
    316 
    317         private void initReminderIntervalList() {
    318 
    319             String[] activeValues =
    320                     getResources().getStringArray(R.array.alert_reminder_interval_active_values);
    321             String[] allEntries =
    322                     getResources().getStringArray(R.array.alert_reminder_interval_entries);
    323             String[] newEntries = new String[activeValues.length];
    324 
    325             // Only add active interval to the list
    326             for (int i = 0; i < activeValues.length; i++) {
    327                 int index = mReminderInterval.findIndexOfValue(activeValues[i]);
    328                 if (index != -1) {
    329                     newEntries[i] = allEntries[index];
    330                     if (DBG) Log.d(TAG, "Added " + allEntries[index]);
    331                 } else {
    332                     Log.e(TAG, "Can't find " + activeValues[i]);
    333                 }
    334             }
    335 
    336             mReminderInterval.setEntries(newEntries);
    337             mReminderInterval.setEntryValues(activeValues);
    338             mReminderInterval.setSummary(mReminderInterval.getEntry());
    339             mReminderInterval.setOnPreferenceChangeListener(
    340                     new Preference.OnPreferenceChangeListener() {
    341                         @Override
    342                         public boolean onPreferenceChange(Preference pref, Object newValue) {
    343                             final ListPreference listPref = (ListPreference) pref;
    344                             final int idx = listPref.findIndexOfValue((String) newValue);
    345                             listPref.setSummary(listPref.getEntries()[idx]);
    346                             return true;
    347                         }
    348                     });
    349         }
    350 
    351 
    352         private void setAlertsEnabled(boolean alertsEnabled) {
    353             if (mSevereCheckBox != null) {
    354                 mSevereCheckBox.setEnabled(alertsEnabled);
    355                 mSevereCheckBox.setChecked(alertsEnabled);
    356             }
    357             if (mExtremeCheckBox != null) {
    358                 mExtremeCheckBox.setEnabled(alertsEnabled);
    359                 mExtremeCheckBox.setChecked(alertsEnabled);
    360             }
    361             if (mAmberCheckBox != null) {
    362                 mAmberCheckBox.setEnabled(alertsEnabled);
    363                 mAmberCheckBox.setChecked(alertsEnabled);
    364             }
    365             if (mAreaUpdateInfoCheckBox != null) {
    366                 mAreaUpdateInfoCheckBox.setEnabled(alertsEnabled);
    367                 mAreaUpdateInfoCheckBox.setChecked(alertsEnabled);
    368             }
    369             if (mAlertPreferencesCategory != null) {
    370                 mAlertPreferencesCategory.setEnabled(alertsEnabled);
    371             }
    372             if (mDevSettingCategory != null) {
    373                 mDevSettingCategory.setEnabled(alertsEnabled);
    374             }
    375         }
    376     }
    377 
    378     public static boolean isFeatureEnabled(Context context, String feature, boolean defaultValue) {
    379         int subId = SubscriptionManager.getDefaultSmsSubscriptionId();
    380         if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
    381             subId = SubscriptionManager.getDefaultSubscriptionId();
    382             if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
    383                 return defaultValue;
    384             }
    385         }
    386 
    387         CarrierConfigManager configManager =
    388                 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
    389 
    390         if (configManager != null) {
    391             PersistableBundle carrierConfig = configManager.getConfigForSubId(subId);
    392 
    393             if (carrierConfig != null) {
    394                 return carrierConfig.getBoolean(feature, defaultValue);
    395             }
    396         }
    397 
    398         return defaultValue;
    399     }
    400 }
    401