• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of 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,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.cellbroadcastreceiver;
18 
19 import static com.android.cellbroadcastreceiver.CellBroadcastReceiver.VDBG;
20 
21 import android.app.IntentService;
22 import android.content.Intent;
23 import android.content.SharedPreferences;
24 import android.content.res.Resources;
25 import android.preference.PreferenceManager;
26 import android.telephony.SmsManager;
27 import android.telephony.SubscriptionManager;
28 import android.util.Log;
29 
30 import com.android.cellbroadcastreceiver.CellBroadcastChannelManager.CellBroadcastChannelRange;
31 import com.android.internal.annotations.VisibleForTesting;
32 
33 import java.util.ArrayList;
34 import java.util.Arrays;
35 import java.util.List;
36 
37 /**
38  * This service manages enabling and disabling ranges of message identifiers
39  * that the radio should listen for. It operates independently of the other
40  * services and runs at boot time and after exiting airplane mode.
41  *
42  * Note that the entire range of emergency channels is enabled. Test messages
43  * and lower priority broadcasts are filtered out in CellBroadcastAlertService
44  * if the user has not enabled them in settings.
45  *
46  * TODO: add notification to re-enable channels after a radio reset.
47  */
48 public class CellBroadcastConfigService extends IntentService {
49     private static final String TAG = "CellBroadcastConfigService";
50 
51     static final String ACTION_ENABLE_CHANNELS = "ACTION_ENABLE_CHANNELS";
52 
CellBroadcastConfigService()53     public CellBroadcastConfigService() {
54         super(TAG);          // use class name for worker thread name
55     }
56 
57     @Override
onHandleIntent(Intent intent)58     protected void onHandleIntent(Intent intent) {
59         if (ACTION_ENABLE_CHANNELS.equals(intent.getAction())) {
60             try {
61 
62                 SubscriptionManager subManager = SubscriptionManager.from(getApplicationContext());
63                 int subId = SubscriptionManager.getDefaultSmsSubscriptionId();
64                 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
65                     subId = SubscriptionManager.getDefaultSubscriptionId();
66                     if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID &&
67                             subManager != null) {
68                         int [] subIds = subManager.getActiveSubscriptionIdList();
69                         if (subIds.length != 0) {
70                             subId = subIds[0];
71                         }
72                     }
73                 }
74 
75                 if (subManager != null) {
76                     // Retrieve all the active sub ids. We only want to enable
77                     // cell broadcast on the sub we are interested in and we'll disable
78                     // it on other subs so the users will not receive duplicate messages from
79                     // multiple carriers (e.g. for multi-sim users).
80                     int [] subIds = subManager.getActiveSubscriptionIdList();
81                     if (subIds.length != 0)
82                     {
83                         for (int id : subIds) {
84                             SmsManager manager = SmsManager.getSmsManagerForSubscriptionId(id);
85                             if (manager != null) {
86                                 if (id == subId) {
87                                     // Enable cell broadcast messages on this sub.
88                                     log("Enable CellBroadcast on sub " + id);
89                                     setCellBroadcastOnSub(manager, true);
90                                 }
91                                 else {
92                                     // Disable all cell broadcast message on this sub.
93                                     // This is only for multi-sim scenario. For single SIM device
94                                     // we should not reach here.
95                                     log("Disable CellBroadcast on sub " + id);
96                                     setCellBroadcastOnSub(manager, false);
97                                 }
98                             }
99                         }
100                     }
101                     else {
102                         // For no sim scenario.
103                         SmsManager manager = SmsManager.getDefault();
104                         if (manager != null) {
105                             setCellBroadcastOnSub(manager, true);
106                         }
107                     }
108                 }
109             } catch (Exception ex) {
110                 Log.e(TAG, "exception enabling cell broadcast channels", ex);
111             }
112         }
113     }
114 
115     /**
116      * Enable/disable cell broadcast messages id on one subscription
117      * This includes all ETWS and CMAS alerts.
118      * @param manager SMS manager
119      * @param enableForSub True if want to enable messages on this sub (e.g default SMS). False
120      *                     will disable all messages
121      */
122     @VisibleForTesting
setCellBroadcastOnSub(SmsManager manager, boolean enableForSub)123     public void setCellBroadcastOnSub(SmsManager manager, boolean enableForSub) {
124 
125         SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
126 
127         // boolean for each user preference checkbox, true for checked, false for unchecked
128         // Note: If enableAlertsMasterToggle is false, it disables ALL emergency broadcasts
129         // except for CMAS presidential. i.e. to receive CMAS severe alerts, both
130         // enableAlertsMasterToggle AND enableCmasSevereAlerts must be true.
131         boolean enableAlertsMasterToggle = enableForSub && prefs.getBoolean(
132                 CellBroadcastSettings.KEY_ENABLE_ALERTS_MASTER_TOGGLE, true);
133 
134         boolean enableEtwsAlerts = enableAlertsMasterToggle;
135 
136         // CMAS Presidential must be always on (See 3GPP TS 22.268 Section 6.2) regardless
137         // user's preference
138         boolean enablePresidential = enableForSub;
139 
140         boolean enableCmasExtremeAlerts = enableAlertsMasterToggle && prefs.getBoolean(
141                 CellBroadcastSettings.KEY_ENABLE_CMAS_EXTREME_THREAT_ALERTS, true);
142 
143         boolean enableCmasSevereAlerts = enableAlertsMasterToggle && prefs.getBoolean(
144                 CellBroadcastSettings.KEY_ENABLE_CMAS_SEVERE_THREAT_ALERTS, true);
145 
146         boolean enableCmasAmberAlerts = enableAlertsMasterToggle && prefs.getBoolean(
147                 CellBroadcastSettings.KEY_ENABLE_CMAS_AMBER_ALERTS, true);
148 
149         boolean enableTestAlerts = enableAlertsMasterToggle
150                 && prefs.getBoolean(CellBroadcastSettings.KEY_ENABLE_TEST_ALERTS, false);
151 
152         boolean enableAreaUpdateInfoAlerts = Resources.getSystem().getBoolean(
153                 com.android.internal.R.bool.config_showAreaUpdateInfoSettings)
154                 && prefs.getBoolean(CellBroadcastSettings.KEY_ENABLE_AREA_UPDATE_INFO_ALERTS,
155                 false);
156 
157         boolean enablePublicSafetyMessagesChannelAlerts = enableAlertsMasterToggle
158                 && prefs.getBoolean(CellBroadcastSettings.KEY_ENABLE_PUBLIC_SAFETY_MESSAGES,
159                 true);
160         boolean enableStateLocalTestAlerts = enableAlertsMasterToggle
161                 && prefs.getBoolean(CellBroadcastSettings.KEY_ENABLE_STATE_LOCAL_TEST_ALERTS,
162                 false);
163 
164         boolean enableEmergencyAlerts = enableAlertsMasterToggle && prefs.getBoolean(
165                 CellBroadcastSettings.KEY_ENABLE_EMERGENCY_ALERTS, true);
166 
167         if (VDBG) {
168             log("enableAlertsMasterToggle = " + enableAlertsMasterToggle);
169             log("enableEtwsAlerts = " + enableEtwsAlerts);
170             log("enablePresidential = " + enablePresidential);
171             log("enableCmasExtremeAlerts = " + enableCmasExtremeAlerts);
172             log("enableCmasSevereAlerts = " + enableCmasExtremeAlerts);
173             log("enableCmasAmberAlerts = " + enableCmasAmberAlerts);
174             log("enableTestAlerts = " + enableTestAlerts);
175             log("enableAreaUpdateInfoAlerts = " + enableAreaUpdateInfoAlerts);
176             log("enablePublicSafetyMessagesChannelAlerts = "
177                     + enablePublicSafetyMessagesChannelAlerts);
178             log("enableStateLocalTestAlerts = " + enableStateLocalTestAlerts);
179             log("enableEmergencyAlerts = " + enableEmergencyAlerts);
180         }
181 
182         /** Enable CMAS series messages. */
183 
184         // Enable/Disable Presidential messages.
185         setCellBroadcastRange(manager, enablePresidential,
186                 CellBroadcastChannelManager.getInstance().getCellBroadcastChannelRanges(this,
187                 R.array.cmas_presidential_alerts_channels_range_strings));
188 
189         // Enable/Disable CMAS extreme messages.
190         setCellBroadcastRange(manager, enableCmasExtremeAlerts,
191                 CellBroadcastChannelManager.getInstance().getCellBroadcastChannelRanges(this,
192                 R.array.cmas_alert_extreme_channels_range_strings));
193 
194         // Enable/Disable CMAS severe messages.
195         setCellBroadcastRange(manager, enableCmasSevereAlerts,
196                 CellBroadcastChannelManager.getInstance().getCellBroadcastChannelRanges(this,
197                 R.array.cmas_alerts_severe_range_strings));
198 
199         // Enable/Disable CMAS amber alert messages.
200         setCellBroadcastRange(manager, enableCmasAmberAlerts,
201                 CellBroadcastChannelManager.getInstance().getCellBroadcastChannelRanges(this,
202                 R.array.cmas_amber_alerts_channels_range_strings));
203 
204         // Enable/Disable test messages.
205         setCellBroadcastRange(manager, enableTestAlerts,
206                 CellBroadcastChannelManager.getInstance().getCellBroadcastChannelRanges(this,
207                 R.array.required_monthly_test_range_strings));
208         setCellBroadcastRange(manager, enableTestAlerts,
209                 CellBroadcastChannelManager.getInstance().getCellBroadcastChannelRanges(this,
210                         R.array.exercise_alert_range_strings));
211         setCellBroadcastRange(manager, enableTestAlerts,
212                 CellBroadcastChannelManager.getInstance().getCellBroadcastChannelRanges(this,
213                         R.array.operator_defined_alert_range_strings));
214 
215         // Enable/Disable GSM ETWS messages.
216         setCellBroadcastRange(manager, enableEtwsAlerts,
217                 CellBroadcastChannelManager.getInstance().getCellBroadcastChannelRanges(this,
218                 R.array.etws_alerts_range_strings));
219 
220         // Enable/Disable GSM ETWS test messages.
221         setCellBroadcastRange(manager, enableTestAlerts,
222                 CellBroadcastChannelManager.getInstance().getCellBroadcastChannelRanges(this,
223                 R.array.etws_test_alerts_range_strings));
224 
225         // Enable/Disable GSM public safety messages.
226         setCellBroadcastRange(manager, enablePublicSafetyMessagesChannelAlerts,
227                 CellBroadcastChannelManager.getInstance().getCellBroadcastChannelRanges(this,
228                         R.array.public_safety_messages_channels_range_strings));
229 
230         // Enable/Disable GSM state/local test alerts.
231         setCellBroadcastRange(manager, enableStateLocalTestAlerts,
232                 CellBroadcastChannelManager.getInstance().getCellBroadcastChannelRanges(this,
233                         R.array.state_local_test_alert_range_strings));
234 
235         /** Enable non-CMAS series messages. */
236 
237         setCellBroadcastRange(manager, enableEmergencyAlerts,
238                 CellBroadcastChannelManager.getInstance().getCellBroadcastChannelRanges(this,
239                 R.array.emergency_alerts_channels_range_strings));
240 
241         // Enable/Disable additional channels based on carrier specific requirement.
242         ArrayList<CellBroadcastChannelRange> ranges = CellBroadcastChannelManager
243                 .getInstance().getCellBroadcastChannelRanges(this,
244                 R.array.additional_cbs_channels_strings);
245         if (ranges != null) {
246             for (CellBroadcastChannelRange range: ranges) {
247                 boolean enableAlerts;
248                 switch (range.mAlertType) {
249                     case AREA:
250                         enableAlerts = enableAreaUpdateInfoAlerts;
251                         break;
252                     case TEST:
253                         enableAlerts = enableTestAlerts;
254                         break;
255                     default:
256                         enableAlerts = enableAlertsMasterToggle;
257                 }
258                 setCellBroadcastRange(manager, enableAlerts, new ArrayList<>(Arrays.asList(range)));
259             }
260         }
261     }
262     /**
263      * Enable/disable cell broadcast with messages id range
264      * @param manager SMS manager
265      * @param enable True for enabling cell broadcast with id range, otherwise for disabling.
266      * @param ranges Cell broadcast id ranges
267      */
setCellBroadcastRange( SmsManager manager, boolean enable, List<CellBroadcastChannelRange> ranges)268     private void setCellBroadcastRange(
269             SmsManager manager, boolean enable, List<CellBroadcastChannelRange> ranges) {
270         if (ranges != null) {
271             for (CellBroadcastChannelRange range: ranges) {
272                 if (enable) {
273                     manager.enableCellBroadcastRange(range.mStartId, range.mEndId, range.mRat);
274                 } else {
275                     manager.disableCellBroadcastRange(range.mStartId, range.mEndId, range.mRat);
276                 }
277             }
278         }
279     }
280 
log(String msg)281     private static void log(String msg) {
282         Log.d(TAG, msg);
283     }
284 }
285