• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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         // 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      */
setCellBroadcastRange( SmsManager manager, boolean enable, List<CellBroadcastChannelRange> ranges)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 
log(String msg)273     private static void log(String msg) {
274         Log.d(TAG, msg);
275     }
276 }
277