CellBroadcastConfigService.java revision 5c99d6fe60b213790fbdaa9d05c5d11fc8a3652c
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
17package com.android.cellbroadcastreceiver;
18
19import android.app.IntentService;
20import android.content.Context;
21import android.content.Intent;
22import android.content.SharedPreferences;
23import android.content.res.Resources;
24import android.os.SystemProperties;
25import android.preference.PreferenceManager;
26import android.telephony.CellBroadcastMessage;
27import android.telephony.SmsManager;
28import android.telephony.SubscriptionManager;
29import android.telephony.TelephonyManager;
30import android.text.TextUtils;
31import android.util.Log;
32import com.android.internal.telephony.PhoneConstants;
33import com.android.internal.telephony.cdma.sms.SmsEnvelope;
34import com.android.internal.telephony.gsm.SmsCbConstants;
35
36import static com.android.cellbroadcastreceiver.CellBroadcastReceiver.DBG;
37
38/**
39 * This service manages enabling and disabling ranges of message identifiers
40 * that the radio should listen for. It operates independently of the other
41 * services and runs at boot time and after exiting airplane mode.
42 *
43 * Note that the entire range of emergency channels is enabled. Test messages
44 * and lower priority broadcasts are filtered out in CellBroadcastAlertService
45 * if the user has not enabled them in settings.
46 *
47 * TODO: add notification to re-enable channels after a radio reset.
48 */
49public class CellBroadcastConfigService extends IntentService {
50    private static final String TAG = "CellBroadcastConfigService";
51
52    static final String ACTION_ENABLE_CHANNELS = "ACTION_ENABLE_CHANNELS";
53
54    static final String EMERGENCY_BROADCAST_RANGE_GSM =
55            "ro.cb.gsm.emergencyids";
56
57    public CellBroadcastConfigService() {
58        super(TAG);          // use class name for worker thread name
59    }
60
61    private static void setChannelRange(SmsManager manager, String ranges, boolean enable) {
62        if (DBG)log("setChannelRange: " + ranges);
63
64        try {
65            for (String channelRange : ranges.split(",")) {
66                int dashIndex = channelRange.indexOf('-');
67                if (dashIndex != -1) {
68                    int startId = Integer.decode(channelRange.substring(0, dashIndex).trim());
69                    int endId = Integer.decode(channelRange.substring(dashIndex + 1).trim());
70                    if (enable) {
71                        if (DBG) log("enabling emergency IDs " + startId + '-' + endId);
72                        manager.enableCellBroadcastRange(startId, endId,
73                                SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
74                    } else {
75                        if (DBG) log("disabling emergency IDs " + startId + '-' + endId);
76                        manager.disableCellBroadcastRange(startId, endId,
77                                SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
78                    }
79                } else {
80                    int messageId = Integer.decode(channelRange.trim());
81                    if (enable) {
82                        if (DBG) log("enabling emergency message ID " + messageId);
83                        manager.enableCellBroadcast(messageId,
84                                SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
85                    } else {
86                        if (DBG) log("disabling emergency message ID " + messageId);
87                        manager.disableCellBroadcast(messageId,
88                                SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
89                    }
90                }
91            }
92        } catch (NumberFormatException e) {
93            Log.e(TAG, "Number Format Exception parsing emergency channel range", e);
94        }
95
96        // Make sure CMAS Presidential is enabled (See 3GPP TS 22.268 Section 6.2).
97        if (DBG) log("setChannelRange: enabling CMAS Presidential");
98        manager.enableCellBroadcast(SmsCbConstants.MESSAGE_ID_CMAS_ALERT_PRESIDENTIAL_LEVEL,
99                SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
100        // register Taiwan PWS 4383 also, by default
101        manager.enableCellBroadcast(
102                SmsCbConstants.MESSAGE_ID_CMAS_ALERT_PRESIDENTIAL_LEVEL_LANGUAGE,
103                SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
104        manager.enableCellBroadcast(SmsEnvelope.SERVICE_CATEGORY_CMAS_PRESIDENTIAL_LEVEL_ALERT,
105                SmsManager.CELL_BROADCAST_RAN_TYPE_CDMA);
106    }
107
108    /**
109     * Returns true if this is a standard or operator-defined emergency alert message.
110     * This includes all ETWS and CMAS alerts, except for AMBER alerts.
111     * @param message the message to test
112     * @return true if the message is an emergency alert; false otherwise
113     */
114    static boolean isEmergencyAlertMessage(CellBroadcastMessage message) {
115        if (message.isEmergencyAlertMessage()) {
116            return true;
117        }
118
119        // Check for system property defining the emergency channel ranges to enable
120        String emergencyIdRange = (CellBroadcastReceiver.phoneIsCdma(message.getSubId())) ?
121                "" : SystemProperties.get(EMERGENCY_BROADCAST_RANGE_GSM);
122
123        if (TextUtils.isEmpty(emergencyIdRange)) {
124            return false;
125        }
126        try {
127            int messageId = message.getServiceCategory();
128            for (String channelRange : emergencyIdRange.split(",")) {
129                int dashIndex = channelRange.indexOf('-');
130                if (dashIndex != -1) {
131                    int startId = Integer.decode(channelRange.substring(0, dashIndex).trim());
132                    int endId = Integer.decode(channelRange.substring(dashIndex + 1).trim());
133                    if (messageId >= startId && messageId <= endId) {
134                        return true;
135                    }
136                } else {
137                    int emergencyMessageId = Integer.decode(channelRange.trim());
138                    if (emergencyMessageId == messageId) {
139                        return true;
140                    }
141                }
142            }
143        } catch (NumberFormatException e) {
144            Log.e(TAG, "Number Format Exception parsing emergency channel range", e);
145        }
146        return false;
147    }
148
149    @Override
150    protected void onHandleIntent(Intent intent) {
151        if (ACTION_ENABLE_CHANNELS.equals(intent.getAction())) {
152            int subId = intent.getExtras().getInt(PhoneConstants.SUBSCRIPTION_KEY);
153
154            try {
155                SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
156                Resources res = getResources();
157
158
159                // boolean for each user preference checkbox, true for checked, false for
160                // unchecked
161                // Note: If enableEmergencyAlerts is false, it disables ALL emergency broadcasts
162                // except for cmas presidential. i.e. to receive cmas severe alerts, both
163                // enableEmergencyAlerts AND enableCmasSevereAlerts must be true.
164
165                boolean enableEmergencyAlerts = SubscriptionManager.getBooleanSubscriptionProperty(
166                        subId, SubscriptionManager.CB_EMERGENCY_ALERT, true, this);
167
168                TelephonyManager tm = (TelephonyManager) getSystemService(
169                        Context.TELEPHONY_SERVICE);
170
171                boolean enableChannel50Support = res.getBoolean(R.bool.show_brazil_settings) ||
172                        "br".equals(tm.getSimCountryIso());
173
174                boolean enableChannel50Alerts = enableChannel50Support &&
175                        SubscriptionManager.getBooleanSubscriptionProperty(subId,
176                                SubscriptionManager.CB_CHANNEL_50_ALERT, true, this);
177
178                // Note:  ETWS is for 3GPP only
179
180                // Check if ETWS/CMAS test message is forced disabled on the device.
181                boolean forceDisableEtwsCmasTest =
182                        CellBroadcastSettings.isEtwsCmasTestMessageForcedDisabled(this, subId);
183
184                boolean enableEtwsTestAlerts = !forceDisableEtwsCmasTest &&
185                        SubscriptionManager.getBooleanSubscriptionProperty(
186                        subId, SubscriptionManager.CB_ETWS_TEST_ALERT, false, this);
187
188                boolean enableCmasExtremeAlerts = SubscriptionManager
189                        .getBooleanSubscriptionProperty(subId,
190                                SubscriptionManager.CB_EXTREME_THREAT_ALERT, true, this);
191
192                boolean enableCmasSevereAlerts = SubscriptionManager.getBooleanSubscriptionProperty(
193                        subId, SubscriptionManager.CB_SEVERE_THREAT_ALERT, true, this);
194
195                boolean enableCmasAmberAlerts = SubscriptionManager.getBooleanSubscriptionProperty(
196                        subId, SubscriptionManager.CB_AMBER_ALERT, true, this);
197
198                boolean enableCmasTestAlerts = !forceDisableEtwsCmasTest &&
199                        SubscriptionManager.getBooleanSubscriptionProperty(
200                        subId, SubscriptionManager.CB_CMAS_TEST_ALERT, false, this);
201
202                // set up broadcast ID ranges to be used for each category
203                int cmasExtremeStart =
204                        SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_OBSERVED;
205                int cmasExtremeEnd = SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_LIKELY;
206                int cmasSevereStart =
207                        SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_EXPECTED_OBSERVED;
208                int cmasSevereEnd = SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_EXPECTED_LIKELY;
209                int cmasAmber = SmsCbConstants.MESSAGE_ID_CMAS_ALERT_CHILD_ABDUCTION_EMERGENCY;
210                int cmasTestStart = SmsCbConstants.MESSAGE_ID_CMAS_ALERT_REQUIRED_MONTHLY_TEST;
211                int cmasTestEnd = SmsCbConstants.MESSAGE_ID_CMAS_ALERT_OPERATOR_DEFINED_USE;
212                int cmasTestLanguageStart =
213                        SmsCbConstants.MESSAGE_ID_CMAS_ALERT_REQUIRED_MONTHLY_TEST_LANGUAGE;
214                int cmasTestLanguageEnd =
215                        SmsCbConstants.MESSAGE_ID_CMAS_ALERT_OPERATOR_DEFINED_USE_LANGUAGE;
216                int cmasPresident = SmsCbConstants.MESSAGE_ID_CMAS_ALERT_PRESIDENTIAL_LEVEL;
217                int cmasPresidentLanguage =
218                        SmsCbConstants.MESSAGE_ID_CMAS_ALERT_PRESIDENTIAL_LEVEL_LANGUAGE;
219
220                // set to CDMA broadcast ID rage if phone is in CDMA mode.
221                boolean isCdma = CellBroadcastReceiver.phoneIsCdma(subId);
222
223                SmsManager manager = SmsManager.getSmsManagerForSubscriptionId(subId);
224                // Check for system property defining the emergency channel ranges to enable
225                String emergencyIdRange = isCdma ?
226                        "" : SystemProperties.get(EMERGENCY_BROADCAST_RANGE_GSM);
227                if (enableEmergencyAlerts) {
228                    if (DBG) log("enabling emergency cell broadcast channels");
229                    if (!TextUtils.isEmpty(emergencyIdRange)) {
230                        setChannelRange(manager, emergencyIdRange, true);
231                    } else {
232                        // No emergency channel system property, enable all emergency channels
233                        // that have checkbox checked
234                        manager.enableCellBroadcastRange(
235                                SmsCbConstants.MESSAGE_ID_ETWS_EARTHQUAKE_WARNING,
236                                SmsCbConstants.MESSAGE_ID_ETWS_EARTHQUAKE_AND_TSUNAMI_WARNING,
237                                SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
238
239                        if (enableEtwsTestAlerts) {
240                            manager.enableCellBroadcast(
241                                    SmsCbConstants.MESSAGE_ID_ETWS_TEST_MESSAGE,
242                                    SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
243                        }
244
245                        manager.enableCellBroadcast(
246                                SmsCbConstants.MESSAGE_ID_ETWS_OTHER_EMERGENCY_TYPE,
247                                SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
248
249                        if (enableCmasExtremeAlerts) {
250                            manager.enableCellBroadcastRange(cmasExtremeStart, cmasExtremeEnd,
251                                    SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
252                            manager.enableCellBroadcast(
253                                    SmsEnvelope.SERVICE_CATEGORY_CMAS_EXTREME_THREAT,
254                                    SmsManager.CELL_BROADCAST_RAN_TYPE_CDMA);
255                        }
256                        if (enableCmasSevereAlerts) {
257                            manager.enableCellBroadcastRange(cmasSevereStart, cmasSevereEnd,
258                                    SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
259                            manager.enableCellBroadcast(
260                                    SmsEnvelope.SERVICE_CATEGORY_CMAS_SEVERE_THREAT,
261                                    SmsManager.CELL_BROADCAST_RAN_TYPE_CDMA);
262                        }
263                        if (enableCmasAmberAlerts) {
264                            manager.enableCellBroadcast(cmasAmber,
265                                    SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
266                            manager.enableCellBroadcast(
267                                    SmsEnvelope.SERVICE_CATEGORY_CMAS_CHILD_ABDUCTION_EMERGENCY,
268                                    SmsManager.CELL_BROADCAST_RAN_TYPE_CDMA);
269                        }
270                        if (enableCmasTestAlerts) {
271                            manager.enableCellBroadcastRange(cmasTestStart, cmasTestEnd,
272                                    SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
273                            manager.enableCellBroadcast(
274                                    SmsEnvelope.SERVICE_CATEGORY_CMAS_TEST_MESSAGE,
275                                    SmsManager.CELL_BROADCAST_RAN_TYPE_CDMA);
276                            manager.enableCellBroadcastRange(
277                                    cmasTestLanguageStart, cmasTestLanguageEnd,
278                                    SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
279                        }
280                    }
281                    if (DBG) log("enabled emergency cell broadcast channels");
282                } else {
283                    // we may have enabled these channels previously, so try to disable them
284                    if (DBG) log("disabling emergency cell broadcast channels");
285                    if (!TextUtils.isEmpty(emergencyIdRange)) {
286                        setChannelRange(manager, emergencyIdRange, false);
287                    } else {
288                        // No emergency channel system property, disable all emergency channels
289                        // except for CMAS Presidential (See 3GPP TS 22.268 Section 6.2)
290                        manager.disableCellBroadcastRange(
291                                SmsCbConstants.MESSAGE_ID_ETWS_EARTHQUAKE_WARNING,
292                                SmsCbConstants.MESSAGE_ID_ETWS_EARTHQUAKE_AND_TSUNAMI_WARNING,
293                                SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
294                        manager.disableCellBroadcast(
295                                SmsCbConstants.MESSAGE_ID_ETWS_TEST_MESSAGE,
296                                SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
297                        manager.disableCellBroadcast(
298                                SmsCbConstants.MESSAGE_ID_ETWS_OTHER_EMERGENCY_TYPE,
299                                SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
300
301                        manager.disableCellBroadcastRange(cmasExtremeStart, cmasExtremeEnd,
302                                SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
303                        manager.disableCellBroadcastRange(cmasSevereStart, cmasSevereEnd,
304                                SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
305                        manager.disableCellBroadcast(cmasAmber,
306                                SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
307                        manager.disableCellBroadcastRange(cmasTestStart, cmasTestEnd,
308                                SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
309
310                        manager.disableCellBroadcast(
311                                SmsEnvelope.SERVICE_CATEGORY_CMAS_EXTREME_THREAT,
312                                SmsManager.CELL_BROADCAST_RAN_TYPE_CDMA);
313                        manager.disableCellBroadcast(
314                                SmsEnvelope.SERVICE_CATEGORY_CMAS_SEVERE_THREAT,
315                                SmsManager.CELL_BROADCAST_RAN_TYPE_CDMA);
316                        manager.disableCellBroadcast(
317                                SmsEnvelope.SERVICE_CATEGORY_CMAS_CHILD_ABDUCTION_EMERGENCY,
318                                SmsManager.CELL_BROADCAST_RAN_TYPE_CDMA);
319                        manager.disableCellBroadcast(
320                                SmsEnvelope.SERVICE_CATEGORY_CMAS_TEST_MESSAGE,
321                                SmsManager.CELL_BROADCAST_RAN_TYPE_CDMA);
322
323                    }
324                    if (DBG) log("disabled emergency cell broadcast channels");
325                }
326
327                // CMAS Presidential must be on (See 3GPP TS 22.268 Section 6.2).
328                manager.enableCellBroadcast(cmasPresident,
329                        SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
330                manager.enableCellBroadcast(
331                        SmsEnvelope.SERVICE_CATEGORY_CMAS_PRESIDENTIAL_LEVEL_ALERT,
332                        SmsManager.CELL_BROADCAST_RAN_TYPE_CDMA);
333
334                // CMAS Presidential additional language must be on per Taiwan regulation.
335                // Technical Specifications of the Telecommunications Land Mobile 10 (PLMN10)
336                // 5.14.2.3 Channel 4383 shows public warning messages in English and shall not
337                // be turned off.
338                manager.enableCellBroadcast(cmasPresidentLanguage,
339                        SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
340
341                if (enableChannel50Alerts) {
342                    if (DBG) log("enabling cell broadcast channel 50");
343                    manager.enableCellBroadcast(50, SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
344                } else {
345                    if (DBG) log("disabling cell broadcast channel 50");
346                    manager.disableCellBroadcast(50, SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
347                }
348
349                if ("il".equals(tm.getSimCountryIso()) || "il".equals(tm.getNetworkCountryIso())) {
350                    if (DBG) log("enabling channels 919-928 for Israel");
351                    manager.enableCellBroadcastRange(919, 928,
352                            SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
353                } else {
354                    if (DBG) log("disabling channels 919-928");
355                    manager.disableCellBroadcastRange(919, 928,
356                            SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
357                }
358
359                // Disable per user preference/checkbox.
360                // This takes care of the case where enableEmergencyAlerts is true,
361                // but check box is unchecked to receive such as cmas severe alerts.
362                if (!enableEtwsTestAlerts) {
363                    if (DBG) Log.d(TAG, "disabling cell broadcast ETWS test messages");
364                    manager.disableCellBroadcast(
365                            SmsCbConstants.MESSAGE_ID_ETWS_TEST_MESSAGE,
366                            SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
367                }
368                if (!enableCmasExtremeAlerts) {
369                    // Unregister Severe alerts also, if Extreme alerts are disabled
370                    if (DBG) Log.d(TAG, "disabling cell broadcast CMAS extreme and severe");
371                    manager.disableCellBroadcastRange(cmasExtremeStart, cmasExtremeEnd,
372                            SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
373                    manager.disableCellBroadcast(
374                            SmsEnvelope.SERVICE_CATEGORY_CMAS_EXTREME_THREAT,
375                            SmsManager.CELL_BROADCAST_RAN_TYPE_CDMA);
376                }
377
378                if (!enableCmasSevereAlerts) {
379                    if (DBG) Log.d(TAG, "disabling cell broadcast CMAS severe");
380                    manager.disableCellBroadcastRange(cmasSevereStart, cmasSevereEnd,
381                            SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
382                    manager.disableCellBroadcast(SmsEnvelope.SERVICE_CATEGORY_CMAS_SEVERE_THREAT,
383                            SmsManager.CELL_BROADCAST_RAN_TYPE_CDMA);
384                }
385                if (!enableCmasAmberAlerts) {
386                    if (DBG) Log.d(TAG, "disabling cell broadcast CMAS amber");
387                    manager.disableCellBroadcast(cmasAmber, SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
388                    manager.disableCellBroadcast(
389                            SmsEnvelope.SERVICE_CATEGORY_CMAS_CHILD_ABDUCTION_EMERGENCY,
390                            SmsManager.CELL_BROADCAST_RAN_TYPE_CDMA);
391                }
392                if (!enableCmasTestAlerts) {
393                    if (DBG) Log.d(TAG, "disabling cell broadcast CMAS test messages");
394                    manager.disableCellBroadcastRange(cmasTestStart, cmasTestEnd,
395                            SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
396                    manager.disableCellBroadcast(SmsEnvelope.SERVICE_CATEGORY_CMAS_TEST_MESSAGE,
397                            SmsManager.CELL_BROADCAST_RAN_TYPE_CDMA);
398                    manager.disableCellBroadcastRange(
399                            cmasTestLanguageStart, cmasTestLanguageEnd,
400                            SmsManager.CELL_BROADCAST_RAN_TYPE_GSM);
401                }
402            } catch (Exception ex) {
403                Log.e(TAG, "exception enabling cell broadcast channels", ex);
404            }
405        }
406    }
407
408    private static void log(String msg) {
409        Log.d(TAG, msg);
410    }
411}
412