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 CellBroadcastConfigService()53 public CellBroadcastConfigService() { 54 super(TAG); // use class name for worker thread name 55 } 56 57 @Override onHandleIntent(Intent intent)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 setCellBroadcastOnSub(SmsManager manager, boolean enableForSub)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 boolean enablePublicSafetyMessagesChannelAlerts = enableAlertsMasterToggle 158 && prefs.getBoolean(CellBroadcastSettings.KEY_ENABLE_PUBLIC_SAFETY_MESSAGES, 159 true); 160 boolean enableStateLocalTestAlerts = enableAlertsMasterToggle 161 && prefs.getBoolean(CellBroadcastSettings.KEY_ENABLE_STATE_LOCAL_TEST_ALERTS, 162 false); 163 164 boolean enableEmergencyAlerts = enableAlertsMasterToggle && prefs.getBoolean( 165 CellBroadcastSettings.KEY_ENABLE_EMERGENCY_ALERTS, true); 166 167 if (VDBG) { 168 log("enableAlertsMasterToggle = " + enableAlertsMasterToggle); 169 log("enableEtwsAlerts = " + enableEtwsAlerts); 170 log("enablePresidential = " + enablePresidential); 171 log("enableCmasExtremeAlerts = " + enableCmasExtremeAlerts); 172 log("enableCmasSevereAlerts = " + enableCmasExtremeAlerts); 173 log("enableCmasAmberAlerts = " + enableCmasAmberAlerts); 174 log("enableTestAlerts = " + enableTestAlerts); 175 log("enableAreaUpdateInfoAlerts = " + enableAreaUpdateInfoAlerts); 176 log("enablePublicSafetyMessagesChannelAlerts = " 177 + enablePublicSafetyMessagesChannelAlerts); 178 log("enableStateLocalTestAlerts = " + enableStateLocalTestAlerts); 179 log("enableEmergencyAlerts = " + enableEmergencyAlerts); 180 } 181 182 /** Enable CMAS series messages. */ 183 184 // Enable/Disable Presidential messages. 185 setCellBroadcastRange(manager, enablePresidential, 186 CellBroadcastChannelManager.getInstance().getCellBroadcastChannelRanges(this, 187 R.array.cmas_presidential_alerts_channels_range_strings)); 188 189 // Enable/Disable CMAS extreme messages. 190 setCellBroadcastRange(manager, enableCmasExtremeAlerts, 191 CellBroadcastChannelManager.getInstance().getCellBroadcastChannelRanges(this, 192 R.array.cmas_alert_extreme_channels_range_strings)); 193 194 // Enable/Disable CMAS severe messages. 195 setCellBroadcastRange(manager, enableCmasSevereAlerts, 196 CellBroadcastChannelManager.getInstance().getCellBroadcastChannelRanges(this, 197 R.array.cmas_alerts_severe_range_strings)); 198 199 // Enable/Disable CMAS amber alert messages. 200 setCellBroadcastRange(manager, enableCmasAmberAlerts, 201 CellBroadcastChannelManager.getInstance().getCellBroadcastChannelRanges(this, 202 R.array.cmas_amber_alerts_channels_range_strings)); 203 204 // Enable/Disable test messages. 205 setCellBroadcastRange(manager, enableTestAlerts, 206 CellBroadcastChannelManager.getInstance().getCellBroadcastChannelRanges(this, 207 R.array.required_monthly_test_range_strings)); 208 setCellBroadcastRange(manager, enableTestAlerts, 209 CellBroadcastChannelManager.getInstance().getCellBroadcastChannelRanges(this, 210 R.array.exercise_alert_range_strings)); 211 setCellBroadcastRange(manager, enableTestAlerts, 212 CellBroadcastChannelManager.getInstance().getCellBroadcastChannelRanges(this, 213 R.array.operator_defined_alert_range_strings)); 214 215 // Enable/Disable GSM ETWS messages. 216 setCellBroadcastRange(manager, enableEtwsAlerts, 217 CellBroadcastChannelManager.getInstance().getCellBroadcastChannelRanges(this, 218 R.array.etws_alerts_range_strings)); 219 220 // Enable/Disable GSM ETWS test messages. 221 setCellBroadcastRange(manager, enableTestAlerts, 222 CellBroadcastChannelManager.getInstance().getCellBroadcastChannelRanges(this, 223 R.array.etws_test_alerts_range_strings)); 224 225 // Enable/Disable GSM public safety messages. 226 setCellBroadcastRange(manager, enablePublicSafetyMessagesChannelAlerts, 227 CellBroadcastChannelManager.getInstance().getCellBroadcastChannelRanges(this, 228 R.array.public_safety_messages_channels_range_strings)); 229 230 // Enable/Disable GSM state/local test alerts. 231 setCellBroadcastRange(manager, enableStateLocalTestAlerts, 232 CellBroadcastChannelManager.getInstance().getCellBroadcastChannelRanges(this, 233 R.array.state_local_test_alert_range_strings)); 234 235 /** Enable non-CMAS series messages. */ 236 237 setCellBroadcastRange(manager, enableEmergencyAlerts, 238 CellBroadcastChannelManager.getInstance().getCellBroadcastChannelRanges(this, 239 R.array.emergency_alerts_channels_range_strings)); 240 241 // Enable/Disable additional channels based on carrier specific requirement. 242 ArrayList<CellBroadcastChannelRange> ranges = CellBroadcastChannelManager 243 .getInstance().getCellBroadcastChannelRanges(this, 244 R.array.additional_cbs_channels_strings); 245 if (ranges != null) { 246 for (CellBroadcastChannelRange range: ranges) { 247 boolean enableAlerts; 248 switch (range.mAlertType) { 249 case AREA: 250 enableAlerts = enableAreaUpdateInfoAlerts; 251 break; 252 case TEST: 253 enableAlerts = enableTestAlerts; 254 break; 255 default: 256 enableAlerts = enableAlertsMasterToggle; 257 } 258 setCellBroadcastRange(manager, enableAlerts, new ArrayList<>(Arrays.asList(range))); 259 } 260 } 261 } 262 /** 263 * Enable/disable cell broadcast with messages id range 264 * @param manager SMS manager 265 * @param enable True for enabling cell broadcast with id range, otherwise for disabling. 266 * @param ranges Cell broadcast id ranges 267 */ setCellBroadcastRange( SmsManager manager, boolean enable, List<CellBroadcastChannelRange> ranges)268 private void setCellBroadcastRange( 269 SmsManager manager, boolean enable, List<CellBroadcastChannelRange> ranges) { 270 if (ranges != null) { 271 for (CellBroadcastChannelRange range: ranges) { 272 if (enable) { 273 manager.enableCellBroadcastRange(range.mStartId, range.mEndId, range.mRat); 274 } else { 275 manager.disableCellBroadcastRange(range.mStartId, range.mEndId, range.mRat); 276 } 277 } 278 } 279 } 280 log(String msg)281 private static void log(String msg) { 282 Log.d(TAG, msg); 283 } 284 } 285