| /* |
| * Copyright (C) 2011 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.cellbroadcastreceiver; |
| |
| import android.app.IntentService; |
| import android.content.Context; |
| import android.content.Intent; |
| import android.content.SharedPreferences; |
| import android.content.res.Resources; |
| import android.preference.PreferenceManager; |
| import android.telephony.SmsManager; |
| import android.telephony.SubscriptionManager; |
| import android.telephony.TelephonyManager; |
| import android.util.Log; |
| |
| import com.android.cellbroadcastreceiver.CellBroadcastOtherChannelsManager.CellBroadcastChannelRange; |
| import com.android.internal.telephony.cdma.sms.SmsEnvelope; |
| import com.android.internal.telephony.gsm.SmsCbConstants; |
| |
| import java.util.ArrayList; |
| |
| import static com.android.cellbroadcastreceiver.CellBroadcastReceiver.DBG; |
| |
| /** |
| * This service manages enabling and disabling ranges of message identifiers |
| * that the radio should listen for. It operates independently of the other |
| * services and runs at boot time and after exiting airplane mode. |
| * |
| * Note that the entire range of emergency channels is enabled. Test messages |
| * and lower priority broadcasts are filtered out in CellBroadcastAlertService |
| * if the user has not enabled them in settings. |
| * |
| * TODO: add notification to re-enable channels after a radio reset. |
| */ |
| public class CellBroadcastConfigService extends IntentService { |
| private static final String TAG = "CellBroadcastConfigService"; |
| |
| static final String ACTION_ENABLE_CHANNELS = "ACTION_ENABLE_CHANNELS"; |
| |
| private static final String COUNTRY_TAIWAN = "tw"; |
| private static final String COUNTRY_ISRAEL = "ir"; |
| private static final String COUNTRY_BRAZIL = "br"; |
| |
| public CellBroadcastConfigService() { |
| super(TAG); // use class name for worker thread name |
| } |
| |
| @Override |
| protected void onHandleIntent(Intent intent) { |
| if (ACTION_ENABLE_CHANNELS.equals(intent.getAction())) { |
| try { |
| |
| SubscriptionManager subManager = SubscriptionManager.from(getApplicationContext()); |
| int subId = SubscriptionManager.getDefaultSmsSubscriptionId(); |
| if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { |
| subId = SubscriptionManager.getDefaultSubscriptionId(); |
| if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID && |
| subManager != null) { |
| int [] subIds = subManager.getActiveSubscriptionIdList(); |
| if (subIds.length != 0) { |
| subId = subIds[0]; |
| } |
| } |
| } |
| |
| if (subManager != null) { |
| // Retrieve all the active sub ids. We only want to enable |
| // cell broadcast on the sub we are interested in and we'll disable |
| // it on other subs so the users will not receive duplicate messages from |
| // multiple carriers (e.g. for multi-sim users). |
| int [] subIds = subManager.getActiveSubscriptionIdList(); |
| if (subIds.length != 0) |
| { |
| for (int id : subIds) { |
| SmsManager manager = SmsManager.getSmsManagerForSubscriptionId(id); |
| if (manager != null) { |
| if (id == subId) { |
| // Enable cell broadcast messages on this sub. |
| log("Enable CellBroadcast on sub " + id); |
| setCellBroadcastOnSub(manager, id, true); |
| } |
| else { |
| // Disable all cell broadcast message on this sub. |
| // This is only for multi-sim scenario. For single SIM device |
| // we should not reach here. |
| log("Disable CellBroadcast on sub " + id); |
| setCellBroadcastOnSub(manager, id, false); |
| } |
| } |
| } |
| } |
| else { |
| // For no sim scenario. |
| SmsManager manager = SmsManager.getDefault(); |
| if (manager != null) { |
| setCellBroadcastOnSub(manager, |
| SubscriptionManager.INVALID_SUBSCRIPTION_ID, true); |
| } |
| } |
| } |
| } catch (Exception ex) { |
| Log.e(TAG, "exception enabling cell broadcast channels", ex); |
| } |
| } |
| } |
| |
| /** |
| * Enable/disable cell broadcast messages id on one subscription |
| * This includes all ETWS and CMAS alerts. |
| * @param manager SMS manager |
| * @param subId Subscription id |
| * @param enableForSub True if want to enable messages on this sub (e.g default SMS). False |
| * will disable all messages |
| */ |
| private void setCellBroadcastOnSub(SmsManager manager, int subId, boolean enableForSub) { |
| |
| SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); |
| Resources res = getResources(); |
| |
| // boolean for each user preference checkbox, true for checked, false for unchecked |
| // Note: If enableEmergencyAlerts is false, it disables ALL emergency broadcasts |
| // except for CMAS presidential. i.e. to receive CMAS severe alerts, both |
| // enableEmergencyAlerts AND enableCmasSevereAlerts must be true. |
| boolean enableEmergencyAlerts = enableForSub && prefs.getBoolean( |
| CellBroadcastSettings.KEY_ENABLE_EMERGENCY_ALERTS, true); |
| |
| boolean enableEtwsAlerts = enableEmergencyAlerts; |
| |
| // CMAS Presidential must be always on (See 3GPP TS 22.268 Section 6.2) regardless |
| // user's preference |
| boolean enablePresidential = enableForSub; |
| |
| boolean enableCmasExtremeAlerts = enableEmergencyAlerts && prefs.getBoolean( |
| CellBroadcastSettings.KEY_ENABLE_CMAS_EXTREME_THREAT_ALERTS, true); |
| |
| boolean enableCmasSevereAlerts = enableEmergencyAlerts && prefs.getBoolean( |
| CellBroadcastSettings.KEY_ENABLE_CMAS_SEVERE_THREAT_ALERTS, true); |
| |
| boolean enableCmasAmberAlerts = enableEmergencyAlerts && prefs.getBoolean( |
| CellBroadcastSettings.KEY_ENABLE_CMAS_AMBER_ALERTS, true); |
| |
| // Check if ETWS/CMAS test message is forced disabled on the device. |
| boolean forceDisableEtwsCmasTest = |
| CellBroadcastSettings.isEtwsCmasTestMessageForcedDisabled(this); |
| |
| boolean enableEtwsTestAlerts = !forceDisableEtwsCmasTest && |
| enableEmergencyAlerts && |
| prefs.getBoolean(CellBroadcastSettings.KEY_ENABLE_ETWS_TEST_ALERTS, false); |
| |
| boolean enableCmasTestAlerts = !forceDisableEtwsCmasTest && |
| enableEmergencyAlerts && |
| prefs.getBoolean(CellBroadcastSettings.KEY_ENABLE_CMAS_TEST_ALERTS, false); |
| |
| TelephonyManager tm = (TelephonyManager) getSystemService( |
| Context.TELEPHONY_SERVICE); |
| |
| boolean enableChannel50Support = res.getBoolean(R.bool.show_brazil_settings) || |
| COUNTRY_BRAZIL.equals(tm.getSimCountryIso(subId)); |
| |
| boolean enableChannel50Alerts = enableChannel50Support && |
| prefs.getBoolean(CellBroadcastSettings.KEY_ENABLE_CHANNEL_50_ALERTS, true); |
| |
| // Current Israel requires enable certain CMAS messages ids. |
| boolean supportIsraelPwsAlerts = (COUNTRY_ISRAEL.equals(tm.getSimCountryIso(subId)) |
| || COUNTRY_ISRAEL.equals(tm.getNetworkCountryIso(subId))); |
| |
| boolean supportTaiwanPwsAlerts = (COUNTRY_TAIWAN.equals(tm.getSimCountryIso(subId)) |
| || COUNTRY_TAIWAN.equals(tm.getNetworkCountryIso(subId))); |
| |
| if (DBG) { |
| log("enableEmergencyAlerts = " + enableEmergencyAlerts); |
| log("enableEtwsAlerts = " + enableEtwsAlerts); |
| log("enablePresidential = " + enablePresidential); |
| log("enableCmasExtremeAlerts = " + enableCmasExtremeAlerts); |
| log("enableCmasSevereAlerts = " + enableCmasExtremeAlerts); |
| log("enableCmasAmberAlerts = " + enableCmasAmberAlerts); |
| log("forceDisableEtwsCmasTest = " + forceDisableEtwsCmasTest); |
| log("enableEtwsTestAlerts = " + enableEtwsTestAlerts); |
| log("enableCmasTestAlerts = " + enableCmasTestAlerts); |
| log("enableChannel50Alerts = " + enableChannel50Alerts); |
| log("supportIsraelPwsAlerts = " + supportIsraelPwsAlerts); |
| log("supportTaiwanPwsAlerts = " + supportTaiwanPwsAlerts); |
| } |
| |
| /** Enable CDMA CMAS series messages. */ |
| |
| // Enable/Disable CDMA Presidential messages. |
| setCellBroadcastRange(manager, enablePresidential, |
| SmsManager.CELL_BROADCAST_RAN_TYPE_CDMA, |
| SmsEnvelope.SERVICE_CATEGORY_CMAS_PRESIDENTIAL_LEVEL_ALERT, |
| SmsEnvelope.SERVICE_CATEGORY_CMAS_PRESIDENTIAL_LEVEL_ALERT); |
| |
| // Enable/Disable CDMA CMAS extreme messages. |
| setCellBroadcastRange(manager, enableCmasExtremeAlerts, |
| SmsManager.CELL_BROADCAST_RAN_TYPE_CDMA, |
| SmsEnvelope.SERVICE_CATEGORY_CMAS_EXTREME_THREAT, |
| SmsEnvelope.SERVICE_CATEGORY_CMAS_EXTREME_THREAT); |
| |
| // Enable/Disable CDMA CMAS severe messages. |
| setCellBroadcastRange(manager, enableCmasSevereAlerts, |
| SmsManager.CELL_BROADCAST_RAN_TYPE_CDMA, |
| SmsEnvelope.SERVICE_CATEGORY_CMAS_SEVERE_THREAT, |
| SmsEnvelope.SERVICE_CATEGORY_CMAS_SEVERE_THREAT); |
| |
| // Enable/Disable CDMA CMAS amber alert messages. |
| setCellBroadcastRange(manager, enableCmasAmberAlerts, |
| SmsManager.CELL_BROADCAST_RAN_TYPE_CDMA, |
| SmsEnvelope.SERVICE_CATEGORY_CMAS_CHILD_ABDUCTION_EMERGENCY, |
| SmsEnvelope.SERVICE_CATEGORY_CMAS_CHILD_ABDUCTION_EMERGENCY); |
| |
| // Enable/Disable CDMA CMAS test messages. |
| setCellBroadcastRange(manager, enableCmasTestAlerts, |
| SmsManager.CELL_BROADCAST_RAN_TYPE_CDMA, |
| SmsEnvelope.SERVICE_CATEGORY_CMAS_TEST_MESSAGE, |
| SmsEnvelope.SERVICE_CATEGORY_CMAS_TEST_MESSAGE); |
| |
| /** Enable GSM ETWS series messages. */ |
| |
| // Enable/Disable GSM ETWS messages (4352~4354). |
| setCellBroadcastRange(manager, enableEtwsAlerts, |
| SmsManager.CELL_BROADCAST_RAN_TYPE_GSM, |
| SmsCbConstants.MESSAGE_ID_ETWS_EARTHQUAKE_WARNING, |
| SmsCbConstants.MESSAGE_ID_ETWS_EARTHQUAKE_AND_TSUNAMI_WARNING); |
| |
| // Enable/Disable GSM ETWS messages (4356) |
| setCellBroadcastRange(manager, enableEtwsAlerts, |
| SmsManager.CELL_BROADCAST_RAN_TYPE_GSM, |
| SmsCbConstants.MESSAGE_ID_ETWS_OTHER_EMERGENCY_TYPE, |
| SmsCbConstants.MESSAGE_ID_ETWS_OTHER_EMERGENCY_TYPE); |
| |
| // Enable/Disable GSM ETWS test messages (4355). |
| setCellBroadcastRange(manager, enableEtwsTestAlerts, |
| SmsManager.CELL_BROADCAST_RAN_TYPE_GSM, |
| SmsCbConstants.MESSAGE_ID_ETWS_TEST_MESSAGE, |
| SmsCbConstants.MESSAGE_ID_ETWS_TEST_MESSAGE); |
| |
| /** Enable GSM CMAS series messages. */ |
| |
| // Enable/Disable GSM CMAS presidential message (4370). |
| setCellBroadcastRange(manager, enablePresidential, |
| SmsManager.CELL_BROADCAST_RAN_TYPE_GSM, |
| SmsCbConstants.MESSAGE_ID_CMAS_ALERT_PRESIDENTIAL_LEVEL, |
| SmsCbConstants.MESSAGE_ID_CMAS_ALERT_PRESIDENTIAL_LEVEL); |
| |
| // Enable/Disable GSM CMAS extreme messages (4371~4372). |
| setCellBroadcastRange(manager, enableCmasExtremeAlerts, |
| SmsManager.CELL_BROADCAST_RAN_TYPE_GSM, |
| SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_OBSERVED, |
| SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_LIKELY); |
| |
| // Enable/Disable GSM CMAS severe messages (4373~4378). |
| setCellBroadcastRange(manager, enableCmasSevereAlerts, |
| SmsManager.CELL_BROADCAST_RAN_TYPE_GSM, |
| SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_EXPECTED_OBSERVED, |
| SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_EXPECTED_LIKELY); |
| |
| // Enable/Disable GSM CMAS amber alert messages (4379). |
| setCellBroadcastRange(manager, enableCmasAmberAlerts, |
| SmsManager.CELL_BROADCAST_RAN_TYPE_GSM, |
| SmsCbConstants.MESSAGE_ID_CMAS_ALERT_CHILD_ABDUCTION_EMERGENCY, |
| SmsCbConstants.MESSAGE_ID_CMAS_ALERT_CHILD_ABDUCTION_EMERGENCY); |
| |
| // Enable/Disable GSM CMAS test messages (4380~4382). |
| setCellBroadcastRange(manager, enableCmasTestAlerts, |
| SmsManager.CELL_BROADCAST_RAN_TYPE_GSM, |
| SmsCbConstants.MESSAGE_ID_CMAS_ALERT_REQUIRED_MONTHLY_TEST, |
| SmsCbConstants.MESSAGE_ID_CMAS_ALERT_OPERATOR_DEFINED_USE); |
| |
| |
| /** Enable GSM CMAS series messages for additional languages. */ |
| |
| // Enable/Disable GSM CMAS presidential messages for additional languages (4383). |
| setCellBroadcastRange(manager, enablePresidential, |
| SmsManager.CELL_BROADCAST_RAN_TYPE_GSM, |
| SmsCbConstants.MESSAGE_ID_CMAS_ALERT_PRESIDENTIAL_LEVEL_LANGUAGE, |
| SmsCbConstants.MESSAGE_ID_CMAS_ALERT_PRESIDENTIAL_LEVEL_LANGUAGE); |
| |
| // Enable/Disable GSM CMAS extreme messages for additional languages (4384~4385). |
| setCellBroadcastRange(manager, enableCmasExtremeAlerts, |
| SmsManager.CELL_BROADCAST_RAN_TYPE_GSM, |
| SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_OBSERVED_LANGUAGE, |
| SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_LIKELY_LANGUAGE); |
| |
| // Enable/Disable GSM CMAS severe messages for additional languages (4386~4391). |
| setCellBroadcastRange(manager, enableCmasSevereAlerts, |
| SmsManager.CELL_BROADCAST_RAN_TYPE_GSM, |
| SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_EXPECTED_OBSERVED_LANGUAGE, |
| SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_EXPECTED_LIKELY_LANGUAGE); |
| |
| // Enable/Disable GSM CMAS amber alert messages for additional languages (4392). |
| setCellBroadcastRange(manager, enableCmasAmberAlerts, |
| SmsManager.CELL_BROADCAST_RAN_TYPE_GSM, |
| SmsCbConstants.MESSAGE_ID_CMAS_ALERT_CHILD_ABDUCTION_EMERGENCY_LANGUAGE, |
| SmsCbConstants.MESSAGE_ID_CMAS_ALERT_CHILD_ABDUCTION_EMERGENCY_LANGUAGE); |
| |
| // Enable/Disable GSM CMAS test messages for additional languages (4393~4395). |
| setCellBroadcastRange(manager, enableCmasTestAlerts, |
| SmsManager.CELL_BROADCAST_RAN_TYPE_GSM, |
| SmsCbConstants.MESSAGE_ID_CMAS_ALERT_REQUIRED_MONTHLY_TEST_LANGUAGE, |
| SmsCbConstants.MESSAGE_ID_CMAS_ALERT_OPERATOR_DEFINED_USE_LANGUAGE); |
| |
| // Enable/Disable channel 50 messages for Brazil (50). |
| setCellBroadcastRange(manager, enableChannel50Alerts, |
| SmsManager.CELL_BROADCAST_RAN_TYPE_GSM, |
| SmsCbConstants.MESSAGE_ID_GSMA_ALLOCATED_CHANNEL_50, |
| SmsCbConstants.MESSAGE_ID_GSMA_ALLOCATED_CHANNEL_50); |
| |
| // Enable/Disable additional channels based on carrier specific requirement. |
| ArrayList<CellBroadcastChannelRange> ranges = CellBroadcastOtherChannelsManager. |
| getInstance().getCellBroadcastChannelRanges(getApplicationContext(), subId); |
| |
| if (ranges != null) { |
| for (CellBroadcastChannelRange range: ranges) { |
| setCellBroadcastRange(manager, enableEmergencyAlerts, |
| SmsManager.CELL_BROADCAST_RAN_TYPE_GSM, |
| range.mStartId, range.mEndId); |
| } |
| } |
| |
| // Enable/Disable additional channels based on country specific requirement. |
| if (supportIsraelPwsAlerts) { |
| // Enable/Disable Israel PWS channels (919~928). |
| setCellBroadcastRange(manager, enableEmergencyAlerts, |
| SmsManager.CELL_BROADCAST_RAN_TYPE_GSM, |
| SmsCbConstants.MESSAGE_ID_GSMA_ALLOCATED_CHANNEL_919, |
| SmsCbConstants.MESSAGE_ID_GSMA_ALLOCATED_CHANNEL_928); |
| } else if (supportTaiwanPwsAlerts) { |
| // Enable/Disable Taiwan PWS Chinese channel (911). |
| setCellBroadcastRange(manager, enableEmergencyAlerts, |
| SmsManager.CELL_BROADCAST_RAN_TYPE_GSM, |
| SmsCbConstants.MESSAGE_ID_GSMA_ALLOCATED_CHANNEL_911, |
| SmsCbConstants.MESSAGE_ID_GSMA_ALLOCATED_CHANNEL_911); |
| |
| // Enable/Disable Taiwan PWS English channel (919). |
| setCellBroadcastRange(manager, enableEmergencyAlerts, |
| SmsManager.CELL_BROADCAST_RAN_TYPE_GSM, |
| SmsCbConstants.MESSAGE_ID_GSMA_ALLOCATED_CHANNEL_919, |
| SmsCbConstants.MESSAGE_ID_GSMA_ALLOCATED_CHANNEL_919); |
| } |
| } |
| /** |
| * Enable/disable cell broadcast with messages id range |
| * @param manager SMS manager |
| * @param enable True for enabling cell broadcast with id range, otherwise for disabling. |
| * @param type GSM or CDMA |
| * @param start Cell broadcast id range start |
| * @param end Cell broadcast id range end |
| */ |
| private boolean setCellBroadcastRange( |
| SmsManager manager, boolean enable, int type, int start, int end) { |
| if (enable) { |
| return manager.enableCellBroadcastRange(start, end, type); |
| } else { |
| return manager.disableCellBroadcastRange(start, end, type); |
| } |
| } |
| |
| private static void log(String msg) { |
| Log.d(TAG, msg); |
| } |
| } |