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 static com.android.cellbroadcastreceiver.CellBroadcastReceiver.VDBG;
     20 
     21 import android.app.IntentService;
     22 import android.content.Intent;
     23 import android.content.SharedPreferences;
     24 import android.content.res.Resources;
     25 import android.preference.PreferenceManager;
     26 import android.telephony.SmsManager;
     27 import android.telephony.SubscriptionManager;
     28 import android.util.Log;
     29 
     30 import com.android.cellbroadcastreceiver.CellBroadcastChannelManager.CellBroadcastChannelRange;
     31 import com.android.internal.annotations.VisibleForTesting;
     32 
     33 import java.util.ArrayList;
     34 import java.util.Arrays;
     35 import java.util.List;
     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     public CellBroadcastConfigService() {
     54         super(TAG);          // use class name for worker thread name
     55     }
     56 
     57     @Override
     58     protected void onHandleIntent(Intent intent) {
     59         if (ACTION_ENABLE_CHANNELS.equals(intent.getAction())) {
     60             try {
     61 
     62                 SubscriptionManager subManager = SubscriptionManager.from(getApplicationContext());
     63                 int subId = SubscriptionManager.getDefaultSmsSubscriptionId();
     64                 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
     65                     subId = SubscriptionManager.getDefaultSubscriptionId();
     66                     if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID &&
     67                             subManager != null) {
     68                         int [] subIds = subManager.getActiveSubscriptionIdList();
     69                         if (subIds.length != 0) {
     70                             subId = subIds[0];
     71                         }
     72                     }
     73                 }
     74 
     75                 if (subManager != null) {
     76                     // Retrieve all the active sub ids. We only want to enable
     77                     // cell broadcast on the sub we are interested in and we'll disable
     78                     // it on other subs so the users will not receive duplicate messages from
     79                     // multiple carriers (e.g. for multi-sim users).
     80                     int [] subIds = subManager.getActiveSubscriptionIdList();
     81                     if (subIds.length != 0)
     82                     {
     83                         for (int id : subIds) {
     84                             SmsManager manager = SmsManager.getSmsManagerForSubscriptionId(id);
     85                             if (manager != null) {
     86                                 if (id == subId) {
     87                                     // Enable cell broadcast messages on this sub.
     88                                     log("Enable CellBroadcast on sub " + id);
     89                                     setCellBroadcastOnSub(manager, true);
     90                                 }
     91                                 else {
     92                                     // Disable all cell broadcast message on this sub.
     93                                     // This is only for multi-sim scenario. For single SIM device
     94                                     // we should not reach here.
     95                                     log("Disable CellBroadcast on sub " + id);
     96                                     setCellBroadcastOnSub(manager, false);
     97                                 }
     98                             }
     99                         }
    100                     }
    101                     else {
    102                         // For no sim scenario.
    103                         SmsManager manager = SmsManager.getDefault();
    104                         if (manager != null) {
    105                             setCellBroadcastOnSub(manager, true);
    106                         }
    107                     }
    108                 }
    109             } catch (Exception ex) {
    110                 Log.e(TAG, "exception enabling cell broadcast channels", ex);
    111             }
    112         }
    113     }
    114 
    115     /**
    116      * Enable/disable cell broadcast messages id on one subscription
    117      * This includes all ETWS and CMAS alerts.
    118      * @param manager SMS manager
    119      * @param enableForSub True if want to enable messages on this sub (e.g default SMS). False
    120      *                     will disable all messages
    121      */
    122     @VisibleForTesting
    123     public void setCellBroadcastOnSub(SmsManager manager, boolean enableForSub) {
    124 
    125         SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
    126 
    127         // boolean for each user preference checkbox, true for checked, false for unchecked
    128         // Note: If enableAlertsMasterToggle is false, it disables ALL emergency broadcasts
    129         // except for CMAS presidential. i.e. to receive CMAS severe alerts, both
    130         // enableAlertsMasterToggle AND enableCmasSevereAlerts must be true.
    131         boolean enableAlertsMasterToggle = enableForSub && prefs.getBoolean(
    132                 CellBroadcastSettings.KEY_ENABLE_ALERTS_MASTER_TOGGLE, true);
    133 
    134         boolean enableEtwsAlerts = enableAlertsMasterToggle;
    135 
    136         // CMAS Presidential must be always on (See 3GPP TS 22.268 Section 6.2) regardless
    137         // user's preference
    138         boolean enablePresidential = enableForSub;
    139 
    140         boolean enableCmasExtremeAlerts = enableAlertsMasterToggle && prefs.getBoolean(
    141                 CellBroadcastSettings.KEY_ENABLE_CMAS_EXTREME_THREAT_ALERTS, true);
    142 
    143         boolean enableCmasSevereAlerts = enableAlertsMasterToggle && prefs.getBoolean(
    144                 CellBroadcastSettings.KEY_ENABLE_CMAS_SEVERE_THREAT_ALERTS, true);
    145 
    146         boolean enableCmasAmberAlerts = enableAlertsMasterToggle && prefs.getBoolean(
    147                 CellBroadcastSettings.KEY_ENABLE_CMAS_AMBER_ALERTS, true);
    148 
    149         boolean enableTestAlerts = enableAlertsMasterToggle
    150                 && prefs.getBoolean(CellBroadcastSettings.KEY_ENABLE_TEST_ALERTS, false);
    151 
    152         boolean enableAreaUpdateInfoAlerts = Resources.getSystem().getBoolean(
    153                 com.android.internal.R.bool.config_showAreaUpdateInfoSettings)
    154                 && prefs.getBoolean(CellBroadcastSettings.KEY_ENABLE_AREA_UPDATE_INFO_ALERTS,
    155                 false);
    156 
    157         // Non-CMAS channels
    158         boolean enablePublicSafetyMessagesChannelAlerts = enableAlertsMasterToggle
    159                 && prefs.getBoolean(CellBroadcastSettings.KEY_ENABLE_PUBLIC_SAFETY_MESSAGES,
    160                 true);
    161 
    162         boolean enableEmergencyAlerts = enableAlertsMasterToggle && prefs.getBoolean(
    163                 CellBroadcastSettings.KEY_ENABLE_EMERGENCY_ALERTS, true);
    164 
    165         if (VDBG) {
    166             log("enableAlertsMasterToggle = " + enableAlertsMasterToggle);
    167             log("enableEtwsAlerts = " + enableEtwsAlerts);
    168             log("enablePresidential = " + enablePresidential);
    169             log("enableCmasExtremeAlerts = " + enableCmasExtremeAlerts);
    170             log("enableCmasSevereAlerts = " + enableCmasExtremeAlerts);
    171             log("enableCmasAmberAlerts = " + enableCmasAmberAlerts);
    172             log("enableTestAlerts = " + enableTestAlerts);
    173             log("enableAreaUpdateInfoAlerts = " + enableAreaUpdateInfoAlerts);
    174             log("enablePublicSafetyMessagesChannelAlerts = "
    175                     + enablePublicSafetyMessagesChannelAlerts);
    176             log("enableEmergencyAlerts = " + enableEmergencyAlerts);
    177         }
    178 
    179         /** Enable CMAS series messages. */
    180 
    181         // Enable/Disable Presidential messages.
    182         setCellBroadcastRange(manager, enablePresidential,
    183                 CellBroadcastChannelManager.getInstance().getCellBroadcastChannelRanges(this,
    184                 R.array.cmas_presidential_alerts_channels_range_strings));
    185 
    186         // Enable/Disable CMAS extreme messages.
    187         setCellBroadcastRange(manager, enableCmasExtremeAlerts,
    188                 CellBroadcastChannelManager.getInstance().getCellBroadcastChannelRanges(this,
    189                 R.array.cmas_alert_extreme_channels_range_strings));
    190 
    191         // Enable/Disable CMAS severe messages.
    192         setCellBroadcastRange(manager, enableCmasSevereAlerts,
    193                 CellBroadcastChannelManager.getInstance().getCellBroadcastChannelRanges(this,
    194                 R.array.cmas_alerts_severe_range_strings));
    195 
    196         // Enable/Disable CMAS amber alert messages.
    197         setCellBroadcastRange(manager, enableCmasAmberAlerts,
    198                 CellBroadcastChannelManager.getInstance().getCellBroadcastChannelRanges(this,
    199                 R.array.cmas_amber_alerts_channels_range_strings));
    200 
    201         // Enable/Disable test messages.
    202         setCellBroadcastRange(manager, enableTestAlerts,
    203                 CellBroadcastChannelManager.getInstance().getCellBroadcastChannelRanges(this,
    204                 R.array.required_monthly_test_range_strings));
    205         setCellBroadcastRange(manager, enableTestAlerts,
    206                 CellBroadcastChannelManager.getInstance().getCellBroadcastChannelRanges(this,
    207                         R.array.exercise_alert_range_strings));
    208         setCellBroadcastRange(manager, enableTestAlerts,
    209                 CellBroadcastChannelManager.getInstance().getCellBroadcastChannelRanges(this,
    210                         R.array.operator_defined_alert_range_strings));
    211 
    212         // Enable/Disable GSM ETWS messages.
    213         setCellBroadcastRange(manager, enableEtwsAlerts,
    214                 CellBroadcastChannelManager.getInstance().getCellBroadcastChannelRanges(this,
    215                 R.array.etws_alerts_range_strings));
    216 
    217         // Enable/Disable GSM ETWS test messages.
    218         setCellBroadcastRange(manager, enableTestAlerts,
    219                 CellBroadcastChannelManager.getInstance().getCellBroadcastChannelRanges(this,
    220                 R.array.etws_test_alerts_range_strings));
    221 
    222         // Enable/Disable GSM public safety messages.
    223         setCellBroadcastRange(manager, enablePublicSafetyMessagesChannelAlerts,
    224                 CellBroadcastChannelManager.getInstance().getCellBroadcastChannelRanges(this,
    225                         R.array.public_safety_messages_channels_range_strings));
    226 
    227         /** Enable non-CMAS series messages. */
    228 
    229         setCellBroadcastRange(manager, enableEmergencyAlerts,
    230                 CellBroadcastChannelManager.getInstance().getCellBroadcastChannelRanges(this,
    231                 R.array.emergency_alerts_channels_range_strings));
    232 
    233         // Enable/Disable additional channels based on carrier specific requirement.
    234         ArrayList<CellBroadcastChannelRange> ranges = CellBroadcastChannelManager
    235                 .getInstance().getCellBroadcastChannelRanges(this,
    236                 R.array.additional_cbs_channels_strings);
    237         if (ranges != null) {
    238             for (CellBroadcastChannelRange range: ranges) {
    239                 boolean enableAlerts;
    240                 switch (range.mAlertType) {
    241                     case AREA:
    242                         enableAlerts = enableAreaUpdateInfoAlerts;
    243                         break;
    244                     case TEST:
    245                         enableAlerts = enableTestAlerts;
    246                         break;
    247                     default:
    248                         enableAlerts = enableAlertsMasterToggle;
    249                 }
    250                 setCellBroadcastRange(manager, enableAlerts, new ArrayList<>(Arrays.asList(range)));
    251             }
    252         }
    253     }
    254     /**
    255      * Enable/disable cell broadcast with messages id range
    256      * @param manager SMS manager
    257      * @param enable True for enabling cell broadcast with id range, otherwise for disabling.
    258      * @param ranges Cell broadcast id ranges
    259      */
    260     private void setCellBroadcastRange(
    261             SmsManager manager, boolean enable, List<CellBroadcastChannelRange> ranges) {
    262         if (ranges != null) {
    263             for (CellBroadcastChannelRange range: ranges) {
    264                 if (enable) {
    265                     manager.enableCellBroadcastRange(range.mStartId, range.mEndId, range.mRat);
    266                 } else {
    267                     manager.disableCellBroadcastRange(range.mStartId, range.mEndId, range.mRat);
    268                 }
    269             }
    270         }
    271     }
    272 
    273     private static void log(String msg) {
    274         Log.d(TAG, msg);
    275     }
    276 }
    277