Home | History | Annotate | Download | only in cellbroadcastreceiver
      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 
     56     public CellBroadcastConfigService() {
     57         super(TAG);          // use class name for worker thread name
     58     }
     59 
     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      */
    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
    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 
    381     private static void log(String msg) {
    382         Log.d(TAG, msg);
    383     }
    384 }
    385