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