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