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.annotation.NonNull;
20 import android.app.ActionBar;
21 import android.app.ActivityManager;
22 import android.app.Fragment;
23 import android.app.backup.BackupManager;
24 import android.content.BroadcastReceiver;
25 import android.content.Context;
26 import android.content.Intent;
27 import android.content.IntentFilter;
28 import android.content.SharedPreferences;
29 import android.content.pm.PackageManager;
30 import android.content.res.Configuration;
31 import android.content.res.Resources;
32 import android.os.Bundle;
33 import android.os.UserManager;
34 import android.os.Vibrator;
35 import android.telephony.SubscriptionManager;
36 import android.util.Log;
37 import android.view.LayoutInflater;
38 import android.view.MenuItem;
39 import android.view.View;
40 import android.view.ViewGroup;
41 import android.widget.CompoundButton;
42 import android.widget.CompoundButton.OnCheckedChangeListener;
43 
44 import androidx.localbroadcastmanager.content.LocalBroadcastManager;
45 import androidx.preference.ListPreference;
46 import androidx.preference.Preference;
47 import androidx.preference.PreferenceCategory;
48 import androidx.preference.PreferenceFragment;
49 import androidx.preference.PreferenceManager;
50 import androidx.preference.PreferenceScreen;
51 import androidx.preference.TwoStatePreference;
52 
53 import com.android.internal.annotations.VisibleForTesting;
54 import com.android.modules.utils.build.SdkLevel;
55 import com.android.settingslib.collapsingtoolbar.CollapsingToolbarBaseActivity;
56 import com.android.settingslib.widget.MainSwitchPreference;
57 
58 import java.util.HashMap;
59 import java.util.Map;
60 
61 /**
62  * Settings activity for the cell broadcast receiver.
63  */
64 public class CellBroadcastSettings extends CollapsingToolbarBaseActivity {
65 
66     private static final String TAG = "CellBroadcastSettings";
67 
68     private static final boolean DBG = false;
69 
70     @VisibleForTesting
71     public CellBroadcastSettings.CellBroadcastSettingsFragment mCellBroadcastSettingsFragment;
72 
73     /**
74      * Keys for user preferences.
75      * When adding a new preference, make sure to clear its value in resetAllPreferences.
76      */
77     // Preference key for alert header (A text view, not clickable).
78     public static final String KEY_ALERTS_HEADER = "alerts_header";
79 
80     // Preference key for a main toggle to enable/disable all alerts message (default enabled).
81     public static final String KEY_ENABLE_ALERTS_MASTER_TOGGLE = "enable_alerts_master_toggle";
82 
83     // Preference key for whether to enable public safety messages (default enabled).
84     public static final String KEY_ENABLE_PUBLIC_SAFETY_MESSAGES = "enable_public_safety_messages";
85 
86     // Preference key for whether to show full-screen public safety message (pop-up dialog), If set
87     // to false, only display from message history and sms inbox if enabled. A foreground
88     // notification might also be shown if enabled.
89     public static final String KEY_ENABLE_PUBLIC_SAFETY_MESSAGES_FULL_SCREEN =
90             "enable_public_safety_messages_full_screen";
91 
92     // Preference key for whether to enable emergency alerts (default enabled).
93     public static final String KEY_ENABLE_EMERGENCY_ALERTS = "enable_emergency_alerts";
94 
95     // Enable vibration on alert (unless main volume is silent).
96     public static final String KEY_ENABLE_ALERT_VIBRATE = "enable_alert_vibrate";
97 
98     // Speak contents of alert after playing the alert sound.
99     public static final String KEY_ENABLE_ALERT_SPEECH = "enable_alert_speech";
100 
101     // Play alert sound in full volume regardless Do Not Disturb is on.
102     public static final String KEY_OVERRIDE_DND = "override_dnd";
103 
104     public static final String KEY_OVERRIDE_DND_SETTINGS_CHANGED =
105             "override_dnd_settings_changed";
106 
107     // Preference category for emergency alert and CMAS settings.
108     public static final String KEY_CATEGORY_EMERGENCY_ALERTS = "category_emergency_alerts";
109 
110     // Preference category for alert preferences.
111     public static final String KEY_CATEGORY_ALERT_PREFERENCES = "category_alert_preferences";
112 
113     // Show checkbox for Presidential alerts in settings
114     // Whether to display CMAS presidential alert notifications (always enabled).
115     public static final String KEY_ENABLE_CMAS_PRESIDENTIAL_ALERTS =
116             "enable_cmas_presidential_alerts";
117 
118     // Whether to display CMAS extreme threat notifications (default is enabled).
119     public static final String KEY_ENABLE_CMAS_EXTREME_THREAT_ALERTS =
120             "enable_cmas_extreme_threat_alerts";
121 
122     // Whether to display CMAS severe threat notifications (default is enabled).
123     public static final String KEY_ENABLE_CMAS_SEVERE_THREAT_ALERTS =
124             "enable_cmas_severe_threat_alerts";
125 
126     // Whether to display CMAS amber alert messages (default is enabled).
127     public static final String KEY_ENABLE_CMAS_AMBER_ALERTS = "enable_cmas_amber_alerts";
128 
129     // Whether to display monthly test messages (default is disabled).
130     public static final String KEY_ENABLE_TEST_ALERTS = "enable_test_alerts";
131 
132     // Whether to display exercise test alerts.
133     public static final String KEY_ENABLE_EXERCISE_ALERTS = "enable_exercise_alerts";
134 
135     // Whether to display operator defined test alerts
136     public static final String KEY_OPERATOR_DEFINED_ALERTS = "enable_operator_defined_alerts";
137 
138     // Whether to display state/local test messages (default disabled).
139     public static final String KEY_ENABLE_STATE_LOCAL_TEST_ALERTS =
140             "enable_state_local_test_alerts";
141 
142     // Preference key for whether to enable area update information notifications
143     // Enabled by default for phones sold in Brazil and India, otherwise this setting may be hidden.
144     public static final String KEY_ENABLE_AREA_UPDATE_INFO_ALERTS =
145             "enable_area_update_info_alerts";
146 
147     // Preference key for initial opt-in/opt-out dialog.
148     public static final String KEY_SHOW_CMAS_OPT_OUT_DIALOG = "show_cmas_opt_out_dialog";
149 
150     // Alert reminder interval ("once" = single 2 minute reminder).
151     public static final String KEY_ALERT_REMINDER_INTERVAL = "alert_reminder_interval";
152 
153     // Preference key for emergency alerts history
154     public static final String KEY_EMERGENCY_ALERT_HISTORY = "emergency_alert_history";
155 
156     // For top introduction info
157     @VisibleForTesting
158     public static final String KEY_PREFS_TOP_INTRO = "alert_prefs_top_intro";
159 
160     // Whether to receive alert in second language code
161     public static final String KEY_RECEIVE_CMAS_IN_SECOND_LANGUAGE =
162             "receive_cmas_in_second_language";
163 
164     /* End of user preferences keys section. */
165 
166     // Key for shared preference which represents whether user has changed any preference
167     @VisibleForTesting
168     public static final String ANY_PREFERENCE_CHANGED_BY_USER = "any_preference_changed_by_user";
169 
170     // Resource cache per operator
171     @VisibleForTesting
172     public static final Map<String, Resources> sResourcesCacheByOperator = new HashMap<>();
173     private static final Object sCacheLock = new Object();
174 
175     // Intent sent from cellbroadcastreceiver to notify cellbroadcastservice that area info update
176     // is disabled/enabled.
177     private static final String AREA_INFO_UPDATE_ACTION =
178             "com.android.cellbroadcastreceiver.action.AREA_UPDATE_INFO_ENABLED";
179     private static final String AREA_INFO_UPDATE_ENABLED_EXTRA = "enable";
180 
181     /**
182      * This permission is only granted to the cellbroadcast mainline module and thus can be
183      * used for permission check within CBR and CBS.
184      */
185     private static final String CBR_MODULE_PERMISSION =
186             "com.android.cellbroadcastservice.FULL_ACCESS_CELL_BROADCAST_HISTORY";
187 
188     @Override
onCreate(Bundle savedInstanceState)189     public void onCreate(Bundle savedInstanceState) {
190         boolean isWatch = getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH);
191         // for backward compatibility on R devices or wearable devices due to small screen device.
192         boolean hideToolbar = !SdkLevel.isAtLeastS() || isWatch;
193         if (hideToolbar) {
194             setCustomizeContentView(R.layout.cell_broadcast_list_collapsing_no_toobar);
195         }
196 
197         super.onCreate(savedInstanceState);
198 
199         if (hideToolbar) {
200             ActionBar actionBar = getActionBar();
201             if (actionBar != null) {
202                 // android.R.id.home will be triggered in onOptionsItemSelected()
203                 actionBar.setDisplayHomeAsUpEnabled(true);
204             }
205         }
206 
207         UserManager userManager = (UserManager) getSystemService(Context.USER_SERVICE);
208         if (userManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_CELL_BROADCASTS)) {
209             setContentView(R.layout.cell_broadcast_disallowed_preference_screen);
210             return;
211         }
212 
213         // We only add new CellBroadcastSettingsFragment if no fragment is restored.
214         Fragment fragment = getFragmentManager().findFragmentById(
215                 com.android.settingslib.collapsingtoolbar.R.id.content_frame);
216         if (fragment == null) {
217             mCellBroadcastSettingsFragment = new CellBroadcastSettingsFragment();
218             getFragmentManager()
219                     .beginTransaction()
220                     .add(com.android.settingslib.collapsingtoolbar.R.id.content_frame,
221                             mCellBroadcastSettingsFragment)
222                     .commit();
223         }
224     }
225 
226     @Override
onStart()227     public void onStart() {
228         super.onStart();
229         getWindow().addSystemFlags(
230                 android.view.WindowManager.LayoutParams
231                         .SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
232     }
233 
234     @Override
onOptionsItemSelected(MenuItem item)235     public boolean onOptionsItemSelected(MenuItem item) {
236         switch (item.getItemId()) {
237             // Respond to the action bar's Up/Home button
238             case android.R.id.home:
239                 finish();
240                 return true;
241         }
242         return super.onOptionsItemSelected(item);
243     }
244 
245     /**
246      * Reset all user values for preferences (stored in shared preferences).
247      *
248      * @param c the application context
249      */
resetAllPreferences(Context c)250     public static void resetAllPreferences(Context c) {
251         SharedPreferences.Editor e = PreferenceManager.getDefaultSharedPreferences(c).edit();
252         e.remove(KEY_ENABLE_CMAS_EXTREME_THREAT_ALERTS)
253                 .remove(KEY_ENABLE_CMAS_SEVERE_THREAT_ALERTS)
254                 .remove(KEY_ENABLE_CMAS_AMBER_ALERTS)
255                 .remove(KEY_ENABLE_PUBLIC_SAFETY_MESSAGES)
256                 .remove(KEY_ENABLE_PUBLIC_SAFETY_MESSAGES_FULL_SCREEN)
257                 .remove(KEY_ENABLE_EMERGENCY_ALERTS)
258                 .remove(KEY_ALERT_REMINDER_INTERVAL)
259                 .remove(KEY_ENABLE_ALERT_SPEECH)
260                 .remove(KEY_OVERRIDE_DND)
261                 .remove(KEY_ENABLE_AREA_UPDATE_INFO_ALERTS)
262                 .remove(KEY_ENABLE_TEST_ALERTS)
263                 .remove(KEY_ENABLE_STATE_LOCAL_TEST_ALERTS)
264                 .remove(KEY_ENABLE_ALERT_VIBRATE)
265                 .remove(KEY_ENABLE_CMAS_PRESIDENTIAL_ALERTS)
266                 .remove(KEY_RECEIVE_CMAS_IN_SECOND_LANGUAGE)
267                 .remove(KEY_ENABLE_EXERCISE_ALERTS)
268                 .remove(KEY_OPERATOR_DEFINED_ALERTS);
269         // If the device is in test harness mode, reset main toggle should only happen on the
270         // first boot.
271         if (!ActivityManager.isRunningInUserTestHarness()) {
272           Log.d(TAG, "In not test harness mode. reset main toggle.");
273           e.remove(KEY_ENABLE_ALERTS_MASTER_TOGGLE);
274         }
275         e.commit();
276 
277         PackageManager pm = c.getPackageManager();
278         if (pm.hasSystemFeature(PackageManager.FEATURE_WATCH)) {
279             PreferenceManager.setDefaultValues(c, R.xml.watch_preferences, true);
280         } else {
281             PreferenceManager.setDefaultValues(c, R.xml.preferences, true);
282         }
283         setPreferenceChanged(c, false);
284     }
285 
286     /**
287      * Return true if user has modified any preference manually.
288      * @param c the application context
289      * @return
290      */
hasAnyPreferenceChanged(Context c)291     public static boolean hasAnyPreferenceChanged(Context c) {
292         return PreferenceManager.getDefaultSharedPreferences(c)
293                 .getBoolean(ANY_PREFERENCE_CHANGED_BY_USER, false);
294     }
295 
setPreferenceChanged(Context c, boolean changed)296     private static void setPreferenceChanged(Context c, boolean changed) {
297         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(c);
298         sp.edit().putBoolean(ANY_PREFERENCE_CHANGED_BY_USER, changed).apply();
299     }
300 
301     /**
302      * New fragment-style implementation of preferences.
303      */
304     public static class CellBroadcastSettingsFragment extends PreferenceFragment {
305 
306         private TwoStatePreference mExtremeCheckBox;
307         private TwoStatePreference mSevereCheckBox;
308         private TwoStatePreference mAmberCheckBox;
309         private TwoStatePreference mMasterToggle;
310         private TwoStatePreference mPublicSafetyMessagesChannelCheckBox;
311         private TwoStatePreference mPublicSafetyMessagesChannelFullScreenCheckBox;
312         private TwoStatePreference mEmergencyAlertsCheckBox;
313         private ListPreference mReminderInterval;
314         private TwoStatePreference mSpeechCheckBox;
315         private TwoStatePreference mOverrideDndCheckBox;
316         private TwoStatePreference mAreaUpdateInfoCheckBox;
317         private TwoStatePreference mTestCheckBox;
318         private TwoStatePreference mExerciseTestCheckBox;
319         private TwoStatePreference mOperatorDefinedCheckBox;
320         private TwoStatePreference mStateLocalTestCheckBox;
321         private TwoStatePreference mEnableVibrateCheckBox;
322         private Preference mAlertHistory;
323         private Preference mAlertsHeader;
324         private PreferenceCategory mAlertCategory;
325         private PreferenceCategory mAlertPreferencesCategory;
326         private boolean mDisableSevereWhenExtremeDisabled = true;
327 
328         // Show checkbox for Presidential alerts in settings
329         private TwoStatePreference mPresidentialCheckBox;
330 
331         // on/off switch in settings for receiving alert in second language code
332         private TwoStatePreference mReceiveCmasInSecondLanguageCheckBox;
333 
334         // Show the top introduction
335         private Preference mTopIntroPreference;
336 
337         private final BroadcastReceiver mTestingModeChangedReceiver = new BroadcastReceiver() {
338             @Override
339             public void onReceive(Context context, Intent intent) {
340                 switch (intent.getAction()) {
341                     case CellBroadcastReceiver.ACTION_TESTING_MODE_CHANGED:
342                         updatePreferenceVisibility();
343                         break;
344                 }
345             }
346         };
347 
initPreferences()348         private void initPreferences() {
349             mExtremeCheckBox = (TwoStatePreference)
350                     findPreference(KEY_ENABLE_CMAS_EXTREME_THREAT_ALERTS);
351             mSevereCheckBox = (TwoStatePreference)
352                     findPreference(KEY_ENABLE_CMAS_SEVERE_THREAT_ALERTS);
353             mAmberCheckBox = (TwoStatePreference)
354                     findPreference(KEY_ENABLE_CMAS_AMBER_ALERTS);
355             mMasterToggle = (TwoStatePreference)
356                     findPreference(KEY_ENABLE_ALERTS_MASTER_TOGGLE);
357             mPublicSafetyMessagesChannelCheckBox = (TwoStatePreference)
358                     findPreference(KEY_ENABLE_PUBLIC_SAFETY_MESSAGES);
359             mPublicSafetyMessagesChannelFullScreenCheckBox = (TwoStatePreference)
360                     findPreference(KEY_ENABLE_PUBLIC_SAFETY_MESSAGES_FULL_SCREEN);
361             mEmergencyAlertsCheckBox = (TwoStatePreference)
362                     findPreference(KEY_ENABLE_EMERGENCY_ALERTS);
363             mReminderInterval = (ListPreference)
364                     findPreference(KEY_ALERT_REMINDER_INTERVAL);
365             mSpeechCheckBox = (TwoStatePreference)
366                     findPreference(KEY_ENABLE_ALERT_SPEECH);
367             mOverrideDndCheckBox = (TwoStatePreference)
368                     findPreference(KEY_OVERRIDE_DND);
369             mAreaUpdateInfoCheckBox = (TwoStatePreference)
370                     findPreference(KEY_ENABLE_AREA_UPDATE_INFO_ALERTS);
371             mTestCheckBox = (TwoStatePreference)
372                     findPreference(KEY_ENABLE_TEST_ALERTS);
373             mExerciseTestCheckBox = (TwoStatePreference) findPreference(KEY_ENABLE_EXERCISE_ALERTS);
374             mOperatorDefinedCheckBox = (TwoStatePreference)
375                     findPreference(KEY_OPERATOR_DEFINED_ALERTS);
376             mStateLocalTestCheckBox = (TwoStatePreference)
377                     findPreference(KEY_ENABLE_STATE_LOCAL_TEST_ALERTS);
378             mAlertHistory = findPreference(KEY_EMERGENCY_ALERT_HISTORY);
379             mAlertsHeader = findPreference(KEY_ALERTS_HEADER);
380             mReceiveCmasInSecondLanguageCheckBox = (TwoStatePreference) findPreference
381                     (KEY_RECEIVE_CMAS_IN_SECOND_LANGUAGE);
382             mEnableVibrateCheckBox = findPreference(KEY_ENABLE_ALERT_VIBRATE);
383 
384             // Show checkbox for Presidential alerts in settings
385             mPresidentialCheckBox = (TwoStatePreference)
386                     findPreference(KEY_ENABLE_CMAS_PRESIDENTIAL_ALERTS);
387 
388             PackageManager pm = getActivity().getPackageManager();
389             if (!pm.hasSystemFeature(PackageManager.FEATURE_WATCH)) {
390                 mAlertPreferencesCategory = (PreferenceCategory)
391                         findPreference(KEY_CATEGORY_ALERT_PREFERENCES);
392                 mAlertCategory = (PreferenceCategory)
393                         findPreference(KEY_CATEGORY_EMERGENCY_ALERTS);
394             }
395             mTopIntroPreference = findPreference(KEY_PREFS_TOP_INTRO);
396         }
397 
398         @Override
onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)399         public View onCreateView(LayoutInflater inflater, ViewGroup container,
400                 Bundle savedInstanceState) {
401             View root = super.onCreateView(inflater, container, savedInstanceState);
402             PackageManager pm = getActivity().getPackageManager();
403             if (pm != null
404                     && pm.hasSystemFeature(
405                     PackageManager.FEATURE_WATCH)) {
406                 ViewGroup.LayoutParams layoutParams = getListView().getLayoutParams();
407                 if (layoutParams instanceof ViewGroup.MarginLayoutParams) {
408                     int watchMarginInPixel = (int) getResources().getDimension(
409                             R.dimen.pref_top_margin);
410                     ((ViewGroup.MarginLayoutParams) layoutParams).topMargin = watchMarginInPixel;
411                     ((ViewGroup.MarginLayoutParams) layoutParams).bottomMargin = watchMarginInPixel;
412                     getListView().setLayoutParams(layoutParams);
413                 }
414             }
415             return root;
416         }
417 
418         @Override
onCreatePreferences(Bundle savedInstanceState, String rootKey)419         public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
420 
421             LocalBroadcastManager.getInstance(getContext())
422                     .registerReceiver(mTestingModeChangedReceiver, new IntentFilter(
423                             CellBroadcastReceiver.ACTION_TESTING_MODE_CHANGED));
424 
425             // Load the preferences from an XML resource
426             PackageManager pm = getActivity().getPackageManager();
427             if (pm.hasSystemFeature(PackageManager.FEATURE_WATCH)) {
428                 addPreferencesFromResource(R.xml.watch_preferences);
429             } else {
430                 addPreferencesFromResource(R.xml.preferences);
431             }
432 
433             initPreferences();
434 
435             Resources res = CellBroadcastSettings.getResourcesForDefaultSubId(getContext());
436 
437             mDisableSevereWhenExtremeDisabled = res.getBoolean(
438                     R.bool.disable_severe_when_extreme_disabled);
439 
440             // Handler for settings that require us to reconfigure enabled channels in radio
441             Preference.OnPreferenceChangeListener startConfigServiceListener =
442                     new Preference.OnPreferenceChangeListener() {
443                         @Override
444                         public boolean onPreferenceChange(Preference pref, Object newValue) {
445                             if (mDisableSevereWhenExtremeDisabled) {
446                                 if (pref.getKey().equals(KEY_ENABLE_CMAS_EXTREME_THREAT_ALERTS)) {
447                                     boolean isExtremeAlertChecked = (Boolean) newValue;
448                                     if (mSevereCheckBox != null) {
449                                         mSevereCheckBox.setEnabled(isExtremeAlertChecked);
450                                         mSevereCheckBox.setChecked(false);
451                                     }
452                                 }
453                             }
454 
455                             // check if area update was disabled
456                             if (pref.getKey().equals(KEY_ENABLE_AREA_UPDATE_INFO_ALERTS)) {
457                                 boolean isEnabledAlert = (Boolean) newValue;
458                                 notifyAreaInfoUpdate(isEnabledAlert);
459                             }
460 
461                             onPreferenceChangedByUser(getContext());
462                             return true;
463                         }
464                     };
465 
466             initReminderIntervalList();
467 
468             if (mMasterToggle != null) {
469 
470                 initAlertsToggleDisabledAsNeeded();
471 
472                 if (mMasterToggle instanceof MainSwitchPreference) {
473                     MainSwitchPreference mainSwitchPreference =
474                             (MainSwitchPreference) mMasterToggle;
475                     final OnCheckedChangeListener mainSwitchListener =
476                             new OnCheckedChangeListener() {
477                         @Override
478                         public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
479                             setAlertsEnabled(isChecked);
480                             onPreferenceChangedByUser(getContext());
481                         }
482                     };
483                     mainSwitchPreference.addOnSwitchChangeListener(mainSwitchListener);
484                 } else {
485                     Preference.OnPreferenceChangeListener mainSwitchListener =
486                             new Preference.OnPreferenceChangeListener() {
487                                 @Override
488                                 public boolean onPreferenceChange(
489                                         Preference pref, Object newValue) {
490                                     setAlertsEnabled((Boolean) newValue);
491                                     onPreferenceChangedByUser(getContext());
492                                     return true;
493                                 }
494                             };
495                     mMasterToggle.setOnPreferenceChangeListener(mainSwitchListener);
496                 }
497                 // If allow alerts are disabled, we turn all sub-alerts off. If it's enabled, we
498                 // leave them as they are.
499                 if (!mMasterToggle.isChecked()) {
500                     setAlertsEnabled(false);
501                 }
502             }
503             // note that mPresidentialCheckBox does not use the startConfigServiceListener because
504             // the user is never allowed to change the preference
505             if (mAreaUpdateInfoCheckBox != null) {
506                 mAreaUpdateInfoCheckBox.setOnPreferenceChangeListener(startConfigServiceListener);
507             }
508             if (mExtremeCheckBox != null) {
509                 mExtremeCheckBox.setOnPreferenceChangeListener(startConfigServiceListener);
510             }
511             if (mPublicSafetyMessagesChannelCheckBox != null) {
512                 mPublicSafetyMessagesChannelCheckBox.setOnPreferenceChangeListener(
513                         startConfigServiceListener);
514             }
515             if (mPublicSafetyMessagesChannelFullScreenCheckBox != null) {
516                 mPublicSafetyMessagesChannelFullScreenCheckBox.setOnPreferenceChangeListener(
517                         startConfigServiceListener);
518             }
519             if (mEmergencyAlertsCheckBox != null) {
520                 mEmergencyAlertsCheckBox.setOnPreferenceChangeListener(startConfigServiceListener);
521             }
522             if (mSevereCheckBox != null) {
523                 mSevereCheckBox.setOnPreferenceChangeListener(startConfigServiceListener);
524                 if (mDisableSevereWhenExtremeDisabled) {
525                     if (mExtremeCheckBox != null) {
526                         mSevereCheckBox.setEnabled(mExtremeCheckBox.isChecked());
527                     }
528                 }
529             }
530             if (mAmberCheckBox != null) {
531                 mAmberCheckBox.setOnPreferenceChangeListener(startConfigServiceListener);
532             }
533             if (mTestCheckBox != null) {
534                 mTestCheckBox.setOnPreferenceChangeListener(startConfigServiceListener);
535             }
536             if (mExerciseTestCheckBox != null) {
537                 mExerciseTestCheckBox.setOnPreferenceChangeListener(startConfigServiceListener);
538             }
539             if (mOperatorDefinedCheckBox != null) {
540                 mOperatorDefinedCheckBox.setOnPreferenceChangeListener(startConfigServiceListener);
541             }
542             if (mStateLocalTestCheckBox != null) {
543                 mStateLocalTestCheckBox.setOnPreferenceChangeListener(
544                         startConfigServiceListener);
545             }
546 
547             SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
548 
549             if (mOverrideDndCheckBox != null) {
550                 if (!sp.getBoolean(KEY_OVERRIDE_DND_SETTINGS_CHANGED, false)) {
551                     // If the user hasn't changed this settings yet, use the default settings
552                     // from resource overlay.
553                     mOverrideDndCheckBox.setChecked(res.getBoolean(R.bool.override_dnd_default));
554                 }
555                 mOverrideDndCheckBox.setOnPreferenceChangeListener(
556                         (pref, newValue) -> {
557                             sp.edit().putBoolean(KEY_OVERRIDE_DND_SETTINGS_CHANGED,
558                                     true).apply();
559                             updateVibrationPreference((boolean) newValue);
560                             return true;
561                         });
562             }
563 
564             if (mAlertHistory != null) {
565                 mAlertHistory.setOnPreferenceClickListener(
566                         preference -> {
567                             final Intent intent = new Intent(getContext(),
568                                     CellBroadcastListActivity.class);
569                             startActivity(intent);
570                             return true;
571                         });
572             }
573 
574             updateVibrationPreference(sp.getBoolean(CellBroadcastSettings.KEY_OVERRIDE_DND,
575                     false));
576             updatePreferenceVisibility();
577         }
578 
579         /**
580          * Update the vibration preference based on override DND. If DND is overridden, then do
581          * not allow users to turn off vibration.
582          *
583          * @param overrideDnd {@code true} if the alert will be played at full volume, regardless
584          * DND settings.
585          */
updateVibrationPreference(boolean overrideDnd)586         private void updateVibrationPreference(boolean overrideDnd) {
587             if (mEnableVibrateCheckBox != null) {
588                 if (overrideDnd) {
589                     // If DND is enabled, always enable vibration.
590                     mEnableVibrateCheckBox.setChecked(true);
591                 }
592                 // Grey out the preference if DND is overridden.
593                 mEnableVibrateCheckBox.setEnabled(!overrideDnd);
594             }
595         }
596 
597         /**
598          * Dynamically update each preference's visibility based on configuration.
599          */
updatePreferenceVisibility()600         private void updatePreferenceVisibility() {
601             Resources res = CellBroadcastSettings.getResourcesForDefaultSubId(getContext());
602 
603             // The settings should be based on the config by the subscription
604             CellBroadcastChannelManager channelManager = new CellBroadcastChannelManager(
605                     getContext(), SubscriptionManager.getDefaultSubscriptionId(), null);
606 
607             PreferenceScreen preferenceScreen = getPreferenceScreen();
608             boolean isWatch = getActivity().getPackageManager().hasSystemFeature(
609                     PackageManager.FEATURE_WATCH);
610 
611             if (mMasterToggle != null) {
612                 mMasterToggle.setVisible(res.getBoolean(R.bool.show_main_switch_settings));
613             }
614 
615             if (mPresidentialCheckBox != null) {
616                 mPresidentialCheckBox.setVisible(
617                         res.getBoolean(R.bool.show_presidential_alerts_settings));
618                 if (isWatch && !mPresidentialCheckBox.isVisible()) {
619                     preferenceScreen.removePreference(mPresidentialCheckBox);
620                 }
621             }
622 
623             if (mExtremeCheckBox != null) {
624                 mExtremeCheckBox.setVisible(res.getBoolean(R.bool.show_extreme_alert_settings)
625                         && !channelManager.getCellBroadcastChannelRanges(
626                         R.array.cmas_alert_extreme_channels_range_strings).isEmpty());
627                 if (isWatch && !mExtremeCheckBox.isVisible()) {
628                     preferenceScreen.removePreference(mExtremeCheckBox);
629                 }
630             }
631 
632             if (mSevereCheckBox != null) {
633                 mSevereCheckBox.setVisible(res.getBoolean(R.bool.show_severe_alert_settings)
634                         && !channelManager.getCellBroadcastChannelRanges(
635                         R.array.cmas_alerts_severe_range_strings).isEmpty());
636                 if (isWatch && !mSevereCheckBox.isVisible()) {
637                     preferenceScreen.removePreference(mSevereCheckBox);
638                 }
639             }
640 
641             if (mAmberCheckBox != null) {
642                 mAmberCheckBox.setVisible(res.getBoolean(R.bool.show_amber_alert_settings)
643                         && !channelManager.getCellBroadcastChannelRanges(
644                                 R.array.cmas_amber_alerts_channels_range_strings).isEmpty());
645                 if (isWatch && !mAmberCheckBox.isVisible()) {
646                     preferenceScreen.removePreference(mAmberCheckBox);
647                 }
648             }
649 
650             if (mPublicSafetyMessagesChannelCheckBox != null) {
651                 mPublicSafetyMessagesChannelCheckBox.setVisible(
652                         res.getBoolean(R.bool.show_public_safety_settings)
653                                 && !channelManager.getCellBroadcastChannelRanges(
654                                         R.array.public_safety_messages_channels_range_strings)
655                                 .isEmpty());
656                 if (isWatch && !mPublicSafetyMessagesChannelCheckBox.isVisible()) {
657                     preferenceScreen.removePreference(mPublicSafetyMessagesChannelCheckBox);
658                 }
659             }
660             // this is the matching full screen settings for public safety toggle. shown only if
661             // public safety toggle is displayed.
662             if (mPublicSafetyMessagesChannelFullScreenCheckBox != null) {
663                 mPublicSafetyMessagesChannelFullScreenCheckBox.setVisible(
664                         res.getBoolean(R.bool.show_public_safety_full_screen_settings)
665                                 && (mPublicSafetyMessagesChannelCheckBox != null
666                                 && mPublicSafetyMessagesChannelCheckBox.isVisible()));
667             }
668 
669             if (mTestCheckBox != null) {
670                 mTestCheckBox.setVisible(isTestAlertsToggleVisible(getContext()));
671             }
672 
673             if (mExerciseTestCheckBox != null) {
674                 boolean visible = false;
675                 if (res.getBoolean(R.bool.show_separate_exercise_settings)) {
676                     if (res.getBoolean(R.bool.show_exercise_settings)
677                             || CellBroadcastReceiver.isTestingMode(getContext())) {
678                         if (!channelManager.getCellBroadcastChannelRanges(
679                                 R.array.exercise_alert_range_strings).isEmpty()) {
680                             visible = true;
681                         }
682                     }
683                 }
684                 mExerciseTestCheckBox.setVisible(visible);
685             }
686 
687             if (mOperatorDefinedCheckBox != null) {
688                 boolean visible = false;
689                 if (res.getBoolean(R.bool.show_separate_operator_defined_settings)) {
690                     if (res.getBoolean(R.bool.show_operator_defined_settings)
691                             || CellBroadcastReceiver.isTestingMode(getContext())) {
692                         if (!channelManager.getCellBroadcastChannelRanges(
693                                 R.array.operator_defined_alert_range_strings).isEmpty()) {
694                             visible = true;
695                         }
696                     }
697                 }
698                 mOperatorDefinedCheckBox.setVisible(visible);
699             }
700 
701             if (mEmergencyAlertsCheckBox != null) {
702                 mEmergencyAlertsCheckBox.setVisible(!channelManager.getCellBroadcastChannelRanges(
703                         R.array.emergency_alerts_channels_range_strings).isEmpty());
704                 if (isWatch && !mEmergencyAlertsCheckBox.isVisible()) {
705                     preferenceScreen.removePreference(mEmergencyAlertsCheckBox);
706                 }
707             }
708 
709             if (mStateLocalTestCheckBox != null) {
710                 mStateLocalTestCheckBox.setVisible(
711                         res.getBoolean(R.bool.show_state_local_test_settings)
712                                 && !channelManager.getCellBroadcastChannelRanges(
713                                 R.array.state_local_test_alert_range_strings).isEmpty());
714                 if (isWatch && !mStateLocalTestCheckBox.isVisible()) {
715                     preferenceScreen.removePreference(mStateLocalTestCheckBox);
716                 }
717             }
718 
719             if (mReceiveCmasInSecondLanguageCheckBox != null) {
720                 mReceiveCmasInSecondLanguageCheckBox.setVisible(!res.getString(
721                         R.string.emergency_alert_second_language_code).isEmpty());
722                 if (isWatch && !mReceiveCmasInSecondLanguageCheckBox.isVisible()) {
723                     preferenceScreen.removePreference(mReceiveCmasInSecondLanguageCheckBox);
724                 }
725             }
726 
727             if (mAreaUpdateInfoCheckBox != null) {
728                 mAreaUpdateInfoCheckBox.setVisible(
729                         res.getBoolean(R.bool.config_showAreaUpdateInfoSettings));
730                 if (isWatch && !mAreaUpdateInfoCheckBox.isVisible()) {
731                     preferenceScreen.removePreference(mAreaUpdateInfoCheckBox);
732                 }
733             }
734 
735             if (mOverrideDndCheckBox != null) {
736                 mOverrideDndCheckBox.setVisible(res.getBoolean(R.bool.show_override_dnd_settings));
737                 if (isWatch && !mOverrideDndCheckBox.isVisible()) {
738                     preferenceScreen.removePreference(mOverrideDndCheckBox);
739                 }
740             }
741 
742             if (mEnableVibrateCheckBox != null) {
743                 // Only show vibrate toggle when override DND toggle is available to users, or when
744                 // override DND default is turned off.
745                 // In some countries, override DND is always on, which means vibration is always on.
746                 // In that case, no need to show vibration toggle for users.
747                 mEnableVibrateCheckBox.setVisible(isVibrationToggleVisible(getContext(), res));
748                 if (isWatch && !mEnableVibrateCheckBox.isVisible()) {
749                     preferenceScreen.removePreference(mEnableVibrateCheckBox);
750                 }
751             }
752             if (mAlertsHeader != null) {
753                 mAlertsHeader.setVisible(
754                         !getContext().getString(R.string.alerts_header_summary).isEmpty());
755                 if (isWatch && !mAlertsHeader.isVisible()) {
756                     preferenceScreen.removePreference(mAlertsHeader);
757                 }
758             }
759 
760             if (mSpeechCheckBox != null) {
761                 mSpeechCheckBox.setVisible(res.getBoolean(R.bool.show_alert_speech_setting)
762                         || getActivity().getPackageManager()
763                         .hasSystemFeature(PackageManager.FEATURE_WATCH));
764             }
765 
766             if (mTopIntroPreference != null) {
767                 mTopIntroPreference.setTitle(getTopIntroduction());
768             }
769         }
770 
getTopIntroduction()771         private int getTopIntroduction() {
772             // Only set specific top introduction for roaming support now
773             if (!CellBroadcastReceiver.getRoamingOperatorSupported(getContext()).isEmpty()) {
774                 return R.string.top_intro_roaming_text;
775             }
776             return R.string.top_intro_default_text;
777         }
778 
initReminderIntervalList()779         private void initReminderIntervalList() {
780             Resources res = CellBroadcastSettings.getResourcesForDefaultSubId(getContext());
781 
782             String[] activeValues =
783                     res.getStringArray(R.array.alert_reminder_interval_active_values);
784             String[] allEntries = res.getStringArray(R.array.alert_reminder_interval_entries);
785             String[] newEntries = new String[activeValues.length];
786 
787             // Only add active interval to the list
788             for (int i = 0; i < activeValues.length; i++) {
789                 int index = mReminderInterval.findIndexOfValue(activeValues[i]);
790                 if (index != -1) {
791                     newEntries[i] = allEntries[index];
792                     if (DBG) Log.d(TAG, "Added " + allEntries[index]);
793                 } else {
794                     Log.e(TAG, "Can't find " + activeValues[i]);
795                 }
796             }
797 
798             mReminderInterval.setEntries(newEntries);
799             mReminderInterval.setEntryValues(activeValues);
800             mReminderInterval.setSummary(mReminderInterval.getEntry());
801             mReminderInterval.setOnPreferenceChangeListener(
802                     new Preference.OnPreferenceChangeListener() {
803                         @Override
804                         public boolean onPreferenceChange(Preference pref, Object newValue) {
805                             final ListPreference listPref = (ListPreference) pref;
806                             final int idx = listPref.findIndexOfValue((String) newValue);
807                             listPref.setSummary(listPref.getEntries()[idx]);
808                             return true;
809                         }
810                     });
811         }
812 
813         /**
814          * Set the extreme toggle disabled as needed.
815          */
816         @VisibleForTesting
initAlertsToggleDisabledAsNeeded()817         public void initAlertsToggleDisabledAsNeeded() {
818             Resources res = CellBroadcastSettings.getResourcesForDefaultSubId(getContext());
819             if (res.getBoolean(R.bool.disable_extreme_alert_settings)) {
820                 mExtremeCheckBox.setEnabled(false);
821                 mExtremeCheckBox.setChecked(
822                         res.getBoolean(R.bool.extreme_threat_alerts_enabled_default));
823             }
824         }
825 
setAlertsEnabled(boolean alertsEnabled)826         private void setAlertsEnabled(boolean alertsEnabled) {
827             Resources res = CellBroadcastSettings.getResourcesForDefaultSubId(getContext());
828 
829             if (mSevereCheckBox != null) {
830                 mSevereCheckBox.setEnabled(alertsEnabled);
831                 mSevereCheckBox.setChecked(alertsEnabled);
832             }
833             if (!res.getBoolean(R.bool.disable_extreme_alert_settings)
834                     && mExtremeCheckBox != null) {
835                 mExtremeCheckBox.setEnabled(alertsEnabled);
836                 mExtremeCheckBox.setChecked(alertsEnabled);
837             }
838             if (mAmberCheckBox != null) {
839                 mAmberCheckBox.setEnabled(alertsEnabled);
840                 mAmberCheckBox.setChecked(alertsEnabled);
841             }
842             if (mAreaUpdateInfoCheckBox != null) {
843                 mAreaUpdateInfoCheckBox.setEnabled(alertsEnabled);
844                 mAreaUpdateInfoCheckBox.setChecked(alertsEnabled);
845                 notifyAreaInfoUpdate(alertsEnabled);
846             }
847             if (mEmergencyAlertsCheckBox != null) {
848                 mEmergencyAlertsCheckBox.setEnabled(alertsEnabled);
849                 mEmergencyAlertsCheckBox.setChecked(alertsEnabled);
850             }
851             if (mPublicSafetyMessagesChannelCheckBox != null) {
852                 mPublicSafetyMessagesChannelCheckBox.setEnabled(alertsEnabled);
853                 mPublicSafetyMessagesChannelCheckBox.setChecked(alertsEnabled);
854             }
855             if (mStateLocalTestCheckBox != null) {
856                 mStateLocalTestCheckBox.setEnabled(alertsEnabled);
857                 mStateLocalTestCheckBox.setChecked(alertsEnabled);
858             }
859             if (mTestCheckBox != null) {
860                 mTestCheckBox.setEnabled(alertsEnabled);
861                 mTestCheckBox.setChecked(alertsEnabled);
862             }
863             if (mExerciseTestCheckBox != null) {
864                 mExerciseTestCheckBox.setEnabled(alertsEnabled);
865                 mExerciseTestCheckBox.setChecked(alertsEnabled);
866             }
867             if (mOperatorDefinedCheckBox != null) {
868                 mOperatorDefinedCheckBox.setEnabled(alertsEnabled);
869                 mOperatorDefinedCheckBox.setChecked(alertsEnabled);
870             }
871         }
872 
notifyAreaInfoUpdate(boolean enabled)873         private void notifyAreaInfoUpdate(boolean enabled) {
874             Intent areaInfoIntent = new Intent(AREA_INFO_UPDATE_ACTION);
875             areaInfoIntent.putExtra(AREA_INFO_UPDATE_ENABLED_EXTRA, enabled);
876             // sending broadcast protected by the permission which is only
877             // granted for CBR mainline module.
878             getContext().sendBroadcast(areaInfoIntent, CBR_MODULE_PERMISSION);
879         }
880 
881 
882         @Override
onResume()883         public void onResume() {
884             super.onResume();
885             updatePreferenceVisibility();
886         }
887 
888         @Override
onDestroy()889         public void onDestroy() {
890             super.onDestroy();
891             LocalBroadcastManager.getInstance(getContext())
892                     .unregisterReceiver(mTestingModeChangedReceiver);
893         }
894 
895         /**
896          * Callback to be called when preference or master toggle is changed by user
897          *
898          * @param context Context to use
899          */
onPreferenceChangedByUser(Context context)900         public void onPreferenceChangedByUser(Context context) {
901             CellBroadcastReceiver.startConfigService(context,
902                     CellBroadcastConfigService.ACTION_ENABLE_CHANNELS);
903             setPreferenceChanged(context, true);
904 
905             // Notify backup manager a backup pass is needed.
906             new BackupManager(context).dataChanged();
907         }
908     }
909 
910     /**
911      * Check whether vibration toggle is visible
912      * @param context Context
913      * @param res resources
914      */
isVibrationToggleVisible(Context context, Resources res)915     public static boolean isVibrationToggleVisible(Context context, Resources res) {
916         Vibrator vibrator = context.getSystemService(Vibrator.class);
917         boolean supportVibration = (vibrator != null) && vibrator.hasVibrator();
918         boolean isVibrationToggleVisible = supportVibration
919                 && (res.getBoolean(R.bool.show_override_dnd_settings)
920                 || !res.getBoolean(R.bool.override_dnd));
921         return isVibrationToggleVisible;
922     }
923 
isTestAlertsToggleVisible(Context context)924     public static boolean isTestAlertsToggleVisible(Context context) {
925         return isTestAlertsToggleVisible(context, null);
926     }
927 
928     /**
929      * Check whether test alert toggle is visible
930      * @param context Context
931      * @param operator Opeator numeric
932      */
isTestAlertsToggleVisible(Context context, String operator)933     public static boolean isTestAlertsToggleVisible(Context context, String operator) {
934         CellBroadcastChannelManager channelManager = new CellBroadcastChannelManager(context,
935                 SubscriptionManager.getDefaultSubscriptionId(), operator);
936         Resources res = operator == null ? getResourcesForDefaultSubId(context)
937                 : getResourcesByOperator(context,
938                         SubscriptionManager.getDefaultSubscriptionId(), operator);
939         boolean isTestAlertsAvailable = !channelManager.getCellBroadcastChannelRanges(
940                 R.array.required_monthly_test_range_strings).isEmpty()
941                 || (!channelManager.getCellBroadcastChannelRanges(
942                 R.array.exercise_alert_range_strings).isEmpty()
943                 /** exercise toggle is controlled under the main test toggle */
944                 && (!res.getBoolean(R.bool.show_separate_exercise_settings)))
945                 || (!channelManager.getCellBroadcastChannelRanges(
946                 R.array.operator_defined_alert_range_strings).isEmpty()
947                 /** operator defined toggle is controlled under the main test toggle */
948                 && (!res.getBoolean(R.bool.show_separate_operator_defined_settings)))
949                 || !channelManager.getCellBroadcastChannelRanges(
950                 R.array.etws_test_alerts_range_strings).isEmpty();
951 
952         return (res.getBoolean(R.bool.show_test_settings)
953                 || CellBroadcastReceiver.isTestingMode(context))
954                 && isTestAlertsAvailable;
955     }
956 
957     /**
958      * Get the device resource based on SIM
959      *
960      * @param context Context
961      * @param subId Subscription index
962      *
963      * @return The resource
964      */
getResources(@onNull Context context, int subId)965     public static @NonNull Resources getResources(@NonNull Context context, int subId) {
966 
967         if (subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID
968                 || !SubscriptionManager.isValidSubscriptionId(subId)) {
969             return context.getResources();
970         }
971 
972         return SubscriptionManager.getResourcesForSubId(context, subId);
973     }
974 
975     /**
976      * Get the resources using the default subscription ID.
977      * @param context Context
978      * @return the Resources for the default subscription ID, or if there is no default subscription
979      * from SubscriptionManager, the resources for the latest loaded SIM.
980      */
getResourcesForDefaultSubId(@onNull Context context)981     public static @NonNull Resources getResourcesForDefaultSubId(@NonNull Context context) {
982         return getResources(context, SubscriptionManager.getDefaultSubscriptionId());
983     }
984 
985     /**
986      * Get the resources per network operator
987      * @param context Context
988      * @param operator Opeator numeric
989      * @return the Resources based on network operator
990      */
getResourcesByOperator( @onNull Context context, int subId, @NonNull String operator)991     public static @NonNull Resources getResourcesByOperator(
992             @NonNull Context context, int subId, @NonNull String operator) {
993         if (operator == null || operator.isEmpty()) {
994             return getResources(context, subId);
995         }
996 
997         synchronized (sCacheLock) {
998             Resources res = sResourcesCacheByOperator.get(operator);
999             if (res != null) {
1000                 return res;
1001             }
1002 
1003             Configuration overrideConfig = new Configuration();
1004             try {
1005                 int mcc = Integer.parseInt(operator.substring(0, 3));
1006                 int mnc = operator.length() > 3 ? Integer.parseInt(operator.substring(3))
1007                         : Configuration.MNC_ZERO;
1008 
1009                 overrideConfig.mcc = mcc;
1010                 overrideConfig.mnc = mnc;
1011             } catch (NumberFormatException e) {
1012                 // should not happen
1013                 Log.e(TAG, "invalid operator: " + operator);
1014                 return context.getResources();
1015             }
1016 
1017             Context newContext = context.createConfigurationContext(overrideConfig);
1018             res = newContext.getResources();
1019 
1020             sResourcesCacheByOperator.put(operator, res);
1021             return res;
1022         }
1023     }
1024 
1025     /**
1026      * Get the resources id which is used for the default value of the preference
1027      * @param key the preference key
1028      * @return a valid resources id if the key is valid and the default value is
1029      * defined, otherwise 0
1030      */
getResourcesIdForDefaultPrefValue(String key)1031     public static int getResourcesIdForDefaultPrefValue(String key) {
1032         switch (key) {
1033             case KEY_ENABLE_ALERTS_MASTER_TOGGLE:
1034                 return R.bool.master_toggle_enabled_default;
1035             case KEY_ENABLE_PUBLIC_SAFETY_MESSAGES:
1036                 return R.bool.public_safety_messages_enabled_default;
1037             case KEY_ENABLE_PUBLIC_SAFETY_MESSAGES_FULL_SCREEN:
1038                 return R.bool.public_safety_messages_full_screen_enabled_default;
1039             case KEY_ENABLE_EMERGENCY_ALERTS:
1040                 return R.bool.emergency_alerts_enabled_default;
1041             case KEY_ENABLE_ALERT_SPEECH:
1042                 return R.bool.enable_alert_speech_default;
1043             case KEY_OVERRIDE_DND:
1044                 return R.bool.override_dnd_default;
1045             case KEY_ENABLE_CMAS_EXTREME_THREAT_ALERTS:
1046                 return R.bool.extreme_threat_alerts_enabled_default;
1047             case KEY_ENABLE_CMAS_SEVERE_THREAT_ALERTS:
1048                 return R.bool.severe_threat_alerts_enabled_default;
1049             case KEY_ENABLE_CMAS_AMBER_ALERTS:
1050                 return R.bool.amber_alerts_enabled_default;
1051             case KEY_ENABLE_TEST_ALERTS:
1052                 return R.bool.test_alerts_enabled_default;
1053             case KEY_ENABLE_EXERCISE_ALERTS:
1054                 return R.bool.test_exercise_alerts_enabled_default;
1055             case KEY_OPERATOR_DEFINED_ALERTS:
1056                 return R.bool.test_operator_defined_alerts_enabled_default;
1057             case KEY_ENABLE_STATE_LOCAL_TEST_ALERTS:
1058                 return R.bool.state_local_test_alerts_enabled_default;
1059             case KEY_ENABLE_AREA_UPDATE_INFO_ALERTS:
1060                 return R.bool.area_update_info_alerts_enabled_default;
1061             default:
1062                 return 0;
1063         }
1064     }
1065 
1066     /**
1067      * Reset the resources cache.
1068      */
1069     @VisibleForTesting
resetResourcesCache()1070     public static void resetResourcesCache() {
1071         synchronized (sCacheLock) {
1072             sResourcesCacheByOperator.clear();
1073         }
1074     }
1075 }
1076