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     // Preference key for whether to enable emergency notifications (default enabled).
45     public static final String KEY_ENABLE_EMERGENCY_ALERTS = "enable_emergency_alerts";
46 
47     // Duration of alert sound (in seconds).
48     public static final String KEY_ALERT_SOUND_DURATION = "alert_sound_duration";
49 
50     // Default alert duration (in seconds).
51     public static final String ALERT_SOUND_DEFAULT_DURATION = "4";
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     // Preference category for emergency alert and CMAS settings.
60     public static final String KEY_CATEGORY_ALERT_SETTINGS = "category_alert_settings";
61 
62     // Preference category for ETWS related settings.
63     public static final String KEY_CATEGORY_ETWS_SETTINGS = "category_etws_settings";
64 
65     // Whether to display CMAS extreme threat notifications (default is enabled).
66     public static final String KEY_ENABLE_CMAS_EXTREME_THREAT_ALERTS =
67             "enable_cmas_extreme_threat_alerts";
68 
69     // Whether to display CMAS severe threat notifications (default is enabled).
70     public static final String KEY_ENABLE_CMAS_SEVERE_THREAT_ALERTS =
71             "enable_cmas_severe_threat_alerts";
72 
73     // Whether to display CMAS amber alert messages (default is enabled).
74     public static final String KEY_ENABLE_CMAS_AMBER_ALERTS = "enable_cmas_amber_alerts";
75 
76     // Preference category for development settings (enabled by settings developer options toggle).
77     public static final String KEY_CATEGORY_DEV_SETTINGS = "category_dev_settings";
78 
79     // Whether to display ETWS test messages (default is disabled).
80     public static final String KEY_ENABLE_ETWS_TEST_ALERTS = "enable_etws_test_alerts";
81 
82     // Whether to display CMAS monthly test messages (default is disabled).
83     public static final String KEY_ENABLE_CMAS_TEST_ALERTS = "enable_cmas_test_alerts";
84 
85     // Preference category for Brazil specific settings.
86     public static final String KEY_CATEGORY_BRAZIL_SETTINGS = "category_brazil_settings";
87 
88     // Preference key for whether to enable channel 50 notifications
89     // Enabled by default for phones sold in Brazil, otherwise this setting may be hidden.
90     public static final String KEY_ENABLE_CHANNEL_50_ALERTS = "enable_channel_50_alerts";
91 
92     // Preference key for initial opt-in/opt-out dialog.
93     public static final String KEY_SHOW_CMAS_OPT_OUT_DIALOG = "show_cmas_opt_out_dialog";
94 
95     // Alert reminder interval ("once" = single 2 minute reminder).
96     public static final String KEY_ALERT_REMINDER_INTERVAL = "alert_reminder_interval";
97 
98     // Default reminder interval.
99     public static final String ALERT_REMINDER_INTERVAL = "0";
100 
101     // First time use
102     public static final String KEY_FIRST_TIME = "first_time";
103 
104     // Brazil country code
105     private static final String COUNTRY_BRAZIL = "br";
106 
107     @Override
onCreate(Bundle savedInstanceState)108     public void onCreate(Bundle savedInstanceState) {
109         super.onCreate(savedInstanceState);
110 
111         UserManager userManager = (UserManager) getSystemService(Context.USER_SERVICE);
112         if (userManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_CELL_BROADCASTS)) {
113             setContentView(R.layout.cell_broadcast_disallowed_preference_screen);
114             return;
115         }
116 
117         // Display the fragment as the main content.
118         getFragmentManager().beginTransaction().replace(android.R.id.content,
119                 new CellBroadcastSettingsFragment()).commit();
120     }
121 
122     /**
123      * New fragment-style implementation of preferences.
124      */
125     public static class CellBroadcastSettingsFragment extends PreferenceFragment {
126 
127         private CheckBoxPreference mExtremeCheckBox;
128         private CheckBoxPreference mSevereCheckBox;
129         private CheckBoxPreference mAmberCheckBox;
130         private CheckBoxPreference mEmergencyCheckBox;
131         private ListPreference mAlertDuration;
132         private ListPreference mReminderInterval;
133         private CheckBoxPreference mSpeechCheckBox;
134         private CheckBoxPreference mEtwsTestCheckBox;
135         private CheckBoxPreference mChannel50CheckBox;
136         private CheckBoxPreference mCmasTestCheckBox;
137         private PreferenceCategory mAlertCategory;
138         private PreferenceCategory mETWSSettingCategory;
139 
140         @Override
onCreate(Bundle savedInstanceState)141         public void onCreate(Bundle savedInstanceState) {
142             super.onCreate(savedInstanceState);
143 
144             // Load the preferences from an XML resource
145             addPreferencesFromResource(R.xml.preferences);
146 
147             PreferenceScreen preferenceScreen = getPreferenceScreen();
148 
149             mExtremeCheckBox = (CheckBoxPreference)
150                     findPreference(KEY_ENABLE_CMAS_EXTREME_THREAT_ALERTS);
151             mSevereCheckBox = (CheckBoxPreference)
152                     findPreference(KEY_ENABLE_CMAS_SEVERE_THREAT_ALERTS);
153             mAmberCheckBox = (CheckBoxPreference)
154                     findPreference(KEY_ENABLE_CMAS_AMBER_ALERTS);
155             mEmergencyCheckBox = (CheckBoxPreference)
156                     findPreference(KEY_ENABLE_EMERGENCY_ALERTS);
157             mAlertDuration = (ListPreference)
158                     findPreference(KEY_ALERT_SOUND_DURATION);
159             mReminderInterval = (ListPreference)
160                     findPreference(KEY_ALERT_REMINDER_INTERVAL);
161             mSpeechCheckBox = (CheckBoxPreference)
162                     findPreference(KEY_ENABLE_ALERT_SPEECH);
163             mEtwsTestCheckBox = (CheckBoxPreference)
164                     findPreference(KEY_ENABLE_ETWS_TEST_ALERTS);
165             mChannel50CheckBox = (CheckBoxPreference)
166                     findPreference(KEY_ENABLE_CHANNEL_50_ALERTS);
167             mCmasTestCheckBox = (CheckBoxPreference)
168                     findPreference(KEY_ENABLE_CMAS_TEST_ALERTS);
169             mAlertCategory = (PreferenceCategory)
170                     findPreference(KEY_CATEGORY_ALERT_SETTINGS);
171             mETWSSettingCategory = (PreferenceCategory)
172                     findPreference(KEY_CATEGORY_ETWS_SETTINGS);
173 
174             // Handler for settings that require us to reconfigure enabled channels in radio
175             Preference.OnPreferenceChangeListener startConfigServiceListener =
176                     new Preference.OnPreferenceChangeListener() {
177                         @Override
178                         public boolean onPreferenceChange(Preference pref, Object newValue) {
179                             CellBroadcastReceiver.startConfigService(pref.getContext());
180 
181                             if (pref.getKey().equals(KEY_ENABLE_CMAS_EXTREME_THREAT_ALERTS)) {
182                                 boolean isExtremeAlertChecked = (Boolean)newValue;
183                                 if (mSevereCheckBox != null) {
184                                     mSevereCheckBox.setEnabled(isExtremeAlertChecked);
185                                     mSevereCheckBox.setChecked(false);
186                                 }
187                             }
188 
189                             return true;
190                         }
191                     };
192 
193             // Show extra settings when developer options is enabled in settings.
194             boolean enableDevSettings = Settings.Global.getInt(getActivity().getContentResolver(),
195                     Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0) != 0;
196 
197             Resources res = getResources();
198             boolean showEtwsSettings = res.getBoolean(R.bool.show_etws_settings);
199 
200             // alert reminder interval
201             mReminderInterval.setSummary(mReminderInterval.getEntry());
202             mReminderInterval.setOnPreferenceChangeListener(
203                     new Preference.OnPreferenceChangeListener() {
204                 @Override
205                 public boolean onPreferenceChange(Preference pref, Object newValue) {
206                     final ListPreference listPref = (ListPreference) pref;
207                     final int idx = listPref.findIndexOfValue((String) newValue);
208                     listPref.setSummary(listPref.getEntries()[idx]);
209                     return true;
210                 }
211             });
212 
213             boolean forceDisableEtwsCmasTest =
214                     isEtwsCmasTestMessageForcedDisabled(getActivity());
215 
216             boolean emergencyAlertOnOffOptionEnabled =
217                     isEmergencyAlertOnOffOptionEnabled(getActivity());
218 
219             if (enableDevSettings || showEtwsSettings || emergencyAlertOnOffOptionEnabled) {
220                 // enable/disable all alerts except CMAS presidential alerts.
221                 if (mEmergencyCheckBox != null) {
222                     mEmergencyCheckBox.setOnPreferenceChangeListener(startConfigServiceListener);
223                 }
224             } else {
225                 mAlertCategory.removePreference(mEmergencyCheckBox);
226             }
227 
228             // Show alert settings and ETWS categories for ETWS builds and developer mode.
229             if (enableDevSettings || showEtwsSettings) {
230                 // alert sound duration
231                 ListPreference duration = mAlertDuration;
232                 duration.setSummary(duration.getEntry());
233                 duration.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
234                     @Override
235                     public boolean onPreferenceChange(Preference pref, Object newValue) {
236                         final ListPreference listPref = (ListPreference) pref;
237                         final int idx = listPref.findIndexOfValue((String) newValue);
238                         listPref.setSummary(listPref.getEntries()[idx]);
239                         return true;
240                     }
241                 });
242 
243                 if (forceDisableEtwsCmasTest) {
244                     // Remove ETWS test preference.
245                     preferenceScreen.removePreference(mETWSSettingCategory);
246 
247                     PreferenceCategory devSettingCategory =
248                             (PreferenceCategory) findPreference(KEY_CATEGORY_DEV_SETTINGS);
249 
250                     // Remove CMAS test preference.
251                     if (devSettingCategory != null) {
252                         devSettingCategory.removePreference(mCmasTestCheckBox);
253                     }
254                 }
255             } else {
256                 mAlertCategory.removePreference(mAlertDuration);
257                 mAlertCategory.removePreference(mSpeechCheckBox);
258                 // Remove ETWS test preference category.
259                 preferenceScreen.removePreference(mETWSSettingCategory);
260             }
261 
262             if (!res.getBoolean(R.bool.show_cmas_settings)) {
263                 // Remove CMAS preference items in emergency alert category.
264                 mAlertCategory.removePreference(mExtremeCheckBox);
265                 mAlertCategory.removePreference(mSevereCheckBox);
266                 mAlertCategory.removePreference(mAmberCheckBox);
267             }
268 
269             TelephonyManager tm = (TelephonyManager) getActivity().getSystemService(
270                     Context.TELEPHONY_SERVICE);
271 
272             int subId = SubscriptionManager.getDefaultSmsSubscriptionId();
273             if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
274                 subId = SubscriptionManager.getDefaultSubscriptionId();
275             }
276 
277             boolean enableChannel50Support = res.getBoolean(R.bool.show_brazil_settings) ||
278                     COUNTRY_BRAZIL.equals(tm.getSimCountryIso(subId));
279 
280             if (!enableChannel50Support) {
281                 preferenceScreen.removePreference(findPreference(KEY_CATEGORY_BRAZIL_SETTINGS));
282             }
283             if (!enableDevSettings) {
284                 preferenceScreen.removePreference(findPreference(KEY_CATEGORY_DEV_SETTINGS));
285             }
286 
287             if (mChannel50CheckBox != null) {
288                 mChannel50CheckBox.setOnPreferenceChangeListener(startConfigServiceListener);
289             }
290             if (mEtwsTestCheckBox != null) {
291                 mEtwsTestCheckBox.setOnPreferenceChangeListener(startConfigServiceListener);
292             }
293             if (mExtremeCheckBox != null) {
294                 mExtremeCheckBox.setOnPreferenceChangeListener(startConfigServiceListener);
295             }
296             if (mSevereCheckBox != null) {
297                 mSevereCheckBox.setOnPreferenceChangeListener(startConfigServiceListener);
298                 if (mExtremeCheckBox != null) {
299                     mSevereCheckBox.setEnabled(mExtremeCheckBox.isChecked());
300                 }
301             }
302             if (mAmberCheckBox != null) {
303                 mAmberCheckBox.setOnPreferenceChangeListener(startConfigServiceListener);
304             }
305             if (mCmasTestCheckBox != null) {
306                 mCmasTestCheckBox.setOnPreferenceChangeListener(startConfigServiceListener);
307             }
308         }
309     }
310 
311     // Check if ETWS/CMAS test message is forced disabled on the device.
isEtwsCmasTestMessageForcedDisabled(Context context)312     public static boolean isEtwsCmasTestMessageForcedDisabled(Context context) {
313 
314         if (context == null) {
315             return false;
316         }
317 
318         int subId = SubscriptionManager.getDefaultSmsSubscriptionId();
319         if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
320             subId = SubscriptionManager.getDefaultSubscriptionId();
321             if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID)
322                 return false;
323         }
324 
325         CarrierConfigManager configManager =
326                 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
327 
328         if (configManager != null) {
329             PersistableBundle carrierConfig =
330                     configManager.getConfigForSubId(subId);
331 
332             if (carrierConfig != null) {
333                 return carrierConfig.getBoolean(
334                         CarrierConfigManager.KEY_CARRIER_FORCE_DISABLE_ETWS_CMAS_TEST_BOOL);
335             }
336         }
337 
338         return false;
339     }
340 
341     // Check if "Turn on Notifications" option should be always displayed regardless of developer
342     // options turned on or not.
isEmergencyAlertOnOffOptionEnabled(Context context)343     public static boolean isEmergencyAlertOnOffOptionEnabled(Context context) {
344 
345         if (context == null) {
346             return false;
347         }
348 
349         int subId = SubscriptionManager.getDefaultSmsSubscriptionId();
350         if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
351             subId = SubscriptionManager.getDefaultSubscriptionId();
352             if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID)
353                 return false;
354         }
355 
356         CarrierConfigManager configManager =
357                 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
358 
359         if (configManager != null) {
360             PersistableBundle carrierConfig =
361                     configManager.getConfigForSubId(subId);
362 
363             if (carrierConfig != null) {
364                 return carrierConfig.getBoolean(
365                     CarrierConfigManager.KEY_ALWAYS_SHOW_EMERGENCY_ALERT_ONOFF_BOOL);
366             }
367         }
368 
369         return false;
370     }
371 }
372