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