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 android.app.IntentService;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.content.SharedPreferences;
23 import android.content.res.Resources;
24 import android.os.SystemProperties;
25 import android.preference.PreferenceManager;
26 import android.telephony.CellBroadcastMessage;
27 import android.telephony.SmsManager;
28 import android.telephony.TelephonyManager;
29 import android.text.TextUtils;
30 import android.util.Log;
31 
32 import com.android.internal.telephony.cdma.sms.SmsEnvelope;
33 import com.android.internal.telephony.gsm.SmsCbConstants;
34 
35 import static com.android.cellbroadcastreceiver.CellBroadcastReceiver.DBG;
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 
53     static final String EMERGENCY_BROADCAST_RANGE_GSM =
54             "ro.cb.gsm.emergencyids";
55 
CellBroadcastConfigService()56     public CellBroadcastConfigService() {
57         super(TAG);          // use class name for worker thread name
58     }
59 
setChannelRange(SmsManager manager, String ranges, boolean enable)60     private static void setChannelRange(SmsManager manager, String ranges, boolean enable) {
61         if (DBG)log("setChannelRange: " + ranges);
62 
63         try {
64             for (String channelRange : ranges.split(",")) {
65                 int dashIndex = channelRange.indexOf('-');
66                 if (dashIndex != -1) {
67                     int startId = Integer.decode(channelRange.substring(0, dashIndex).trim());
68                     int endId = Integer.decode(channelRange.substring(dashIndex + 1).trim());
69                     if (enable) {
70                         if (DBG) log("enabling emergency IDs " + startId + '-' + endId);
71                         manager.enableCellBroadcastRange(startId, endId, SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
72                     } else {
73                         if (DBG) log("disabling emergency IDs " + startId + '-' + endId);
74                         manager.disableCellBroadcastRange(startId, endId, SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
75                     }
76                 } else {
77                     int messageId = Integer.decode(channelRange.trim());
78                     if (enable) {
79                         if (DBG) log("enabling emergency message ID " + messageId);
80                         manager.enableCellBroadcast(messageId, SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
81                     } else {
82                         if (DBG) log("disabling emergency message ID " + messageId);
83                         manager.disableCellBroadcast(messageId, SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
84                     }
85                 }
86             }
87         } catch (NumberFormatException e) {
88             Log.e(TAG, "Number Format Exception parsing emergency channel range", e);
89         }
90 
91         // Make sure CMAS Presidential is enabled (See 3GPP TS 22.268 Section 6.2).
92         if (DBG) log("setChannelRange: enabling CMAS Presidential");
93         manager.enableCellBroadcast(SmsCbConstants.MESSAGE_ID_CMAS_ALERT_PRESIDENTIAL_LEVEL,
94                 SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
95         // register Taiwan PWS 4383 also, by default
96         manager.enableCellBroadcast(
97                 SmsCbConstants.MESSAGE_ID_CMAS_ALERT_PRESIDENTIAL_LEVEL_LANGUAGE,
98                 SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
99         manager.enableCellBroadcast(SmsEnvelope.SERVICE_CATEGORY_CMAS_PRESIDENTIAL_LEVEL_ALERT,
100                 SmsManager.CELL_BROADCAST_RAN_TYPE_CDMA);
101     }
102 
103     /**
104      * Returns true if this is a standard or operator-defined emergency alert message.
105      * This includes all ETWS and CMAS alerts, except for AMBER alerts.
106      * @param message the message to test
107      * @return true if the message is an emergency alert; false otherwise
108      */
isEmergencyAlertMessage(CellBroadcastMessage message)109     static boolean isEmergencyAlertMessage(CellBroadcastMessage message) {
110         if (message.isEmergencyAlertMessage()) {
111             return true;
112         }
113 
114         // Check for system property defining the emergency channel ranges to enable
115         String emergencyIdRange = (CellBroadcastReceiver.phoneIsCdma()) ?
116                 "" : SystemProperties.get(EMERGENCY_BROADCAST_RANGE_GSM);
117 
118         if (TextUtils.isEmpty(emergencyIdRange)) {
119             return false;
120         }
121         try {
122             int messageId = message.getServiceCategory();
123             for (String channelRange : emergencyIdRange.split(",")) {
124                 int dashIndex = channelRange.indexOf('-');
125                 if (dashIndex != -1) {
126                     int startId = Integer.decode(channelRange.substring(0, dashIndex).trim());
127                     int endId = Integer.decode(channelRange.substring(dashIndex + 1).trim());
128                     if (messageId >= startId && messageId <= endId) {
129                         return true;
130                     }
131                 } else {
132                     int emergencyMessageId = Integer.decode(channelRange.trim());
133                     if (emergencyMessageId == messageId) {
134                         return true;
135                     }
136                 }
137             }
138         } catch (NumberFormatException e) {
139             Log.e(TAG, "Number Format Exception parsing emergency channel range", e);
140         }
141         return false;
142     }
143 
144     @Override
onHandleIntent(Intent intent)145     protected void onHandleIntent(Intent intent) {
146         if (ACTION_ENABLE_CHANNELS.equals(intent.getAction())) {
147             try {
148                 SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
149                 Resources res = getResources();
150 
151                 // boolean for each user preference checkbox, true for checked, false for unchecked
152                 // Note: If enableEmergencyAlerts is false, it disables ALL emergency broadcasts
153                 // except for cmas presidential. i.e. to receive cmas severe alerts, both
154                 // enableEmergencyAlerts AND enableCmasSevereAlerts must be true.
155                 boolean enableEmergencyAlerts = prefs.getBoolean(
156                         CellBroadcastSettings.KEY_ENABLE_EMERGENCY_ALERTS, true);
157 
158                 TelephonyManager tm = (TelephonyManager) getSystemService(
159                         Context.TELEPHONY_SERVICE);
160 
161                 boolean enableChannel50Support = res.getBoolean(R.bool.show_brazil_settings) ||
162                         "br".equals(tm.getSimCountryIso());
163 
164                 boolean enableChannel50Alerts = enableChannel50Support &&
165                         prefs.getBoolean(CellBroadcastSettings.KEY_ENABLE_CHANNEL_50_ALERTS, true);
166 
167                 // Note:  ETWS is for 3GPP only
168                 boolean enableEtwsTestAlerts = prefs.getBoolean(
169                         CellBroadcastSettings.KEY_ENABLE_ETWS_TEST_ALERTS, false);
170 
171                 boolean enableCmasExtremeAlerts = prefs.getBoolean(
172                         CellBroadcastSettings.KEY_ENABLE_CMAS_EXTREME_THREAT_ALERTS, true);
173 
174                 boolean enableCmasSevereAlerts = prefs.getBoolean(
175                         CellBroadcastSettings.KEY_ENABLE_CMAS_SEVERE_THREAT_ALERTS, true);
176 
177                 boolean enableCmasAmberAlerts = prefs.getBoolean(
178                         CellBroadcastSettings.KEY_ENABLE_CMAS_AMBER_ALERTS, true);
179 
180                 boolean enableCmasTestAlerts = prefs.getBoolean(
181                         CellBroadcastSettings.KEY_ENABLE_CMAS_TEST_ALERTS, false);
182 
183                 // set up broadcast ID ranges to be used for each category
184                 int cmasExtremeStart =
185                         SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_OBSERVED;
186                 int cmasExtremeEnd = SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_LIKELY;
187                 int cmasSevereStart =
188                         SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_EXPECTED_OBSERVED;
189                 int cmasSevereEnd = SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_EXPECTED_LIKELY;
190                 int cmasAmber = SmsCbConstants.MESSAGE_ID_CMAS_ALERT_CHILD_ABDUCTION_EMERGENCY;
191                 int cmasTestStart = SmsCbConstants.MESSAGE_ID_CMAS_ALERT_REQUIRED_MONTHLY_TEST;
192                 int cmasTestEnd = SmsCbConstants.MESSAGE_ID_CMAS_ALERT_OPERATOR_DEFINED_USE;
193                 int cmasPresident = SmsCbConstants.MESSAGE_ID_CMAS_ALERT_PRESIDENTIAL_LEVEL;
194                 int cmasTaiwanPWS = SmsCbConstants.MESSAGE_ID_CMAS_ALERT_PRESIDENTIAL_LEVEL_LANGUAGE;
195 
196                 // set to CDMA broadcast ID rage if phone is in CDMA mode.
197                 boolean isCdma = CellBroadcastReceiver.phoneIsCdma();
198 
199                 SmsManager manager = SmsManager.getDefault();
200                 // Check for system property defining the emergency channel ranges to enable
201                 String emergencyIdRange = isCdma ?
202                         "" : SystemProperties.get(EMERGENCY_BROADCAST_RANGE_GSM);
203                 if (enableEmergencyAlerts) {
204                     if (DBG) log("enabling emergency cell broadcast channels");
205                     if (!TextUtils.isEmpty(emergencyIdRange)) {
206                         setChannelRange(manager, emergencyIdRange, true);
207                     } else {
208                         // No emergency channel system property, enable all emergency channels
209                         // that have checkbox checked
210                        manager.enableCellBroadcastRange(
211                                SmsCbConstants.MESSAGE_ID_ETWS_EARTHQUAKE_WARNING,
212                                SmsCbConstants.MESSAGE_ID_ETWS_EARTHQUAKE_AND_TSUNAMI_WARNING,
213                                SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
214 
215                        if (enableEtwsTestAlerts) {
216                             manager.enableCellBroadcast(
217                                     SmsCbConstants.MESSAGE_ID_ETWS_TEST_MESSAGE,
218                                     SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
219                        }
220 
221                        manager.enableCellBroadcast(
222                                     SmsCbConstants.MESSAGE_ID_ETWS_OTHER_EMERGENCY_TYPE,
223                                     SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
224 
225                         if (enableCmasExtremeAlerts) {
226                             manager.enableCellBroadcastRange(cmasExtremeStart, cmasExtremeEnd,
227                                     SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
228                             manager.enableCellBroadcast(
229                                     SmsEnvelope.SERVICE_CATEGORY_CMAS_EXTREME_THREAT,
230                                     SmsManager.CELL_BROADCAST_RAN_TYPE_CDMA);
231                         }
232                         if (enableCmasSevereAlerts) {
233                             manager.enableCellBroadcastRange(cmasSevereStart, cmasSevereEnd,
234                                     SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
235                             manager.enableCellBroadcast(
236                                     SmsEnvelope.SERVICE_CATEGORY_CMAS_SEVERE_THREAT,
237                                     SmsManager.CELL_BROADCAST_RAN_TYPE_CDMA);
238                         }
239                         if (enableCmasAmberAlerts) {
240                             manager.enableCellBroadcast(cmasAmber,
241                                     SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
242                             manager.enableCellBroadcast(
243                                     SmsEnvelope.SERVICE_CATEGORY_CMAS_CHILD_ABDUCTION_EMERGENCY,
244                                     SmsManager.CELL_BROADCAST_RAN_TYPE_CDMA);
245                         }
246                         if (enableCmasTestAlerts) {
247                             manager.enableCellBroadcastRange(cmasTestStart, cmasTestEnd,
248                                     SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
249                             manager.enableCellBroadcast(
250                                     SmsEnvelope.SERVICE_CATEGORY_CMAS_TEST_MESSAGE,
251                                     SmsManager.CELL_BROADCAST_RAN_TYPE_CDMA);
252                         }
253                         // CMAS Presidential must be on (See 3GPP TS 22.268 Section 6.2).
254                         manager.enableCellBroadcast(cmasPresident,
255                                 SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
256                         manager.enableCellBroadcast(
257                                 SmsEnvelope.SERVICE_CATEGORY_CMAS_PRESIDENTIAL_LEVEL_ALERT,
258                                 SmsManager.CELL_BROADCAST_RAN_TYPE_CDMA);
259                         // register Taiwan PWS 4383 also, by default
260                         manager.enableCellBroadcast(cmasTaiwanPWS,
261                                 SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
262                     }
263                     if (DBG) log("enabled emergency cell broadcast channels");
264                 } else {
265                     // we may have enabled these channels previously, so try to disable them
266                     if (DBG) log("disabling emergency cell broadcast channels");
267                     if (!TextUtils.isEmpty(emergencyIdRange)) {
268                         setChannelRange(manager, emergencyIdRange, false);
269                     } else {
270                         // No emergency channel system property, disable all emergency channels
271                         // except for CMAS Presidential (See 3GPP TS 22.268 Section 6.2)
272                         manager.disableCellBroadcastRange(
273                                 SmsCbConstants.MESSAGE_ID_ETWS_EARTHQUAKE_WARNING,
274                                 SmsCbConstants.MESSAGE_ID_ETWS_EARTHQUAKE_AND_TSUNAMI_WARNING,
275                                 SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
276                         manager.disableCellBroadcast(
277                                 SmsCbConstants.MESSAGE_ID_ETWS_TEST_MESSAGE,
278                                 SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
279                         manager.disableCellBroadcast(
280                                 SmsCbConstants.MESSAGE_ID_ETWS_OTHER_EMERGENCY_TYPE,
281                                 SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
282 
283                         manager.disableCellBroadcastRange(cmasExtremeStart, cmasExtremeEnd,
284                                 SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
285                         manager.disableCellBroadcastRange(cmasSevereStart, cmasSevereEnd,
286                                 SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
287                         manager.disableCellBroadcast(cmasAmber,
288                                 SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
289                         manager.disableCellBroadcastRange(cmasTestStart, cmasTestEnd,
290                                 SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
291 
292                         manager.disableCellBroadcast(
293                                 SmsEnvelope.SERVICE_CATEGORY_CMAS_EXTREME_THREAT,
294                                 SmsManager.CELL_BROADCAST_RAN_TYPE_CDMA);
295                         manager.disableCellBroadcast(
296                                 SmsEnvelope.SERVICE_CATEGORY_CMAS_SEVERE_THREAT,
297                                 SmsManager.CELL_BROADCAST_RAN_TYPE_CDMA);
298                         manager.disableCellBroadcast(
299                                 SmsEnvelope.SERVICE_CATEGORY_CMAS_CHILD_ABDUCTION_EMERGENCY,
300                                 SmsManager.CELL_BROADCAST_RAN_TYPE_CDMA);
301                         manager.disableCellBroadcast(
302                                 SmsEnvelope.SERVICE_CATEGORY_CMAS_TEST_MESSAGE ,
303                                 SmsManager.CELL_BROADCAST_RAN_TYPE_CDMA);
304                         // CMAS Presidential must be on (See 3GPP TS 22.268 Section 6.2).
305                         manager.enableCellBroadcast(cmasPresident,
306                                 SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
307                         manager.enableCellBroadcast(
308                                 SmsEnvelope.SERVICE_CATEGORY_CMAS_PRESIDENTIAL_LEVEL_ALERT,
309                                 SmsManager.CELL_BROADCAST_RAN_TYPE_CDMA);
310                         // register Taiwan PWS 4383 also, by default
311                         manager.enableCellBroadcast(cmasTaiwanPWS,
312                                 SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
313                     }
314                     if (DBG) log("disabled emergency cell broadcast channels");
315                 }
316 
317                 if (enableChannel50Alerts) {
318                     if (DBG) log("enabling cell broadcast channel 50");
319                     manager.enableCellBroadcast(50, SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
320                 } else {
321                     if (DBG) log("disabling cell broadcast channel 50");
322                     manager.disableCellBroadcast(50, SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
323                 }
324 
325                 if ("il".equals(tm.getSimCountryIso()) || "il".equals(tm.getNetworkCountryIso())) {
326                     if (DBG) log("enabling channels 919-928 for Israel");
327                     manager.enableCellBroadcastRange(919, 928,
328                             SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
329                 } else {
330                     if (DBG) log("disabling channels 919-928");
331                     manager.disableCellBroadcastRange(919, 928,
332                             SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
333                 }
334 
335                 // Disable per user preference/checkbox.
336                 // This takes care of the case where enableEmergencyAlerts is true,
337                 // but check box is unchecked to receive such as cmas severe alerts.
338                 if (!enableEtwsTestAlerts) {
339                     if (DBG) Log.d(TAG, "disabling cell broadcast ETWS test messages");
340                     manager.disableCellBroadcast(
341                             SmsCbConstants.MESSAGE_ID_ETWS_TEST_MESSAGE,
342                             SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
343                 }
344                 if (!enableCmasExtremeAlerts) {
345                     // Unregister Severe alerts also, if Extreme alerts are disabled
346                     if (DBG) Log.d(TAG, "disabling cell broadcast CMAS extreme and severe");
347                     manager.disableCellBroadcastRange(cmasExtremeStart, cmasExtremeEnd,
348                             SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
349                     manager.disableCellBroadcast(
350                             SmsEnvelope.SERVICE_CATEGORY_CMAS_EXTREME_THREAT,
351                             SmsManager.CELL_BROADCAST_RAN_TYPE_CDMA);
352                 }
353 
354                 if (!enableCmasSevereAlerts) {
355                     if (DBG) Log.d(TAG, "disabling cell broadcast CMAS severe");
356                     manager.disableCellBroadcastRange(cmasSevereStart, cmasSevereEnd,
357                             SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
358                     manager.disableCellBroadcast(SmsEnvelope.SERVICE_CATEGORY_CMAS_SEVERE_THREAT,
359                             SmsManager.CELL_BROADCAST_RAN_TYPE_CDMA);
360                 }
361                 if (!enableCmasAmberAlerts) {
362                     if (DBG) Log.d(TAG, "disabling cell broadcast CMAS amber");
363                     manager.disableCellBroadcast(cmasAmber, SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
364                     manager.disableCellBroadcast(
365                             SmsEnvelope.SERVICE_CATEGORY_CMAS_CHILD_ABDUCTION_EMERGENCY,
366                             SmsManager.CELL_BROADCAST_RAN_TYPE_CDMA);
367                 }
368                 if (!enableCmasTestAlerts) {
369                     if (DBG) Log.d(TAG, "disabling cell broadcast CMAS test messages");
370                     manager.disableCellBroadcastRange(cmasTestStart, cmasTestEnd,
371                             SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
372                     manager.disableCellBroadcast(SmsEnvelope.SERVICE_CATEGORY_CMAS_TEST_MESSAGE,
373                             SmsManager.CELL_BROADCAST_RAN_TYPE_CDMA);
374                 }
375             } catch (Exception ex) {
376                 Log.e(TAG, "exception enabling cell broadcast channels", ex);
377             }
378         }
379     }
380 
log(String msg)381     private static void log(String msg) {
382         Log.d(TAG, msg);
383     }
384 }
385