150a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby/* 250a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby * Copyright (C) 2011 The Android Open Source Project 350a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby * 450a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby * Licensed under the Apache License, Version 2.0 (the "License"); 550a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby * you may not use this file except in compliance with the License. 650a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby * You may obtain a copy of the License at 750a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby * 850a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby * http://www.apache.org/licenses/LICENSE-2.0 950a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby * 1050a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby * Unless required by applicable law or agreed to in writing, software 1150a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby * distributed under the License is distributed on an "AS IS" BASIS, 1250a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1350a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby * See the License for the specific language governing permissions and 1450a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby * limitations under the License. 1550a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby */ 1650a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby 1750a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hambypackage com.android.cellbroadcastreceiver; 1850a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby 1950a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hambyimport android.app.IntentService; 2050a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hambyimport android.content.Intent; 2150a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hambyimport android.content.SharedPreferences; 2250a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hambyimport android.content.res.Resources; 2359610ad5074acb5305c353a53c01676eb8258887Jake Hambyimport android.os.SystemProperties; 2450a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hambyimport android.preference.PreferenceManager; 2550a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hambyimport android.telephony.SmsCbConstants; 2650a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hambyimport android.telephony.SmsManager; 2759610ad5074acb5305c353a53c01676eb8258887Jake Hambyimport android.text.TextUtils; 2850a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hambyimport android.util.Log; 2950a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby 3050a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hambyimport com.android.internal.telephony.gsm.SmsCbHeader; 3150a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby 3250a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hambyimport static com.android.cellbroadcastreceiver.CellBroadcastReceiver.DBG; 3350a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby 3450a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby/** 3550a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby * This service manages enabling and disabling ranges of message identifiers 3650a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby * that the radio should listen for. It operates independently of the other 3750a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby * services and runs at boot time and after exiting airplane mode. 3850a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby * 3950a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby * Note that the entire range of emergency channels is enabled. Test messages 4050a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby * and lower priority broadcasts are filtered out in CellBroadcastAlertService 4150a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby * if the user has not enabled them in settings. 4250a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby * 4350a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby * TODO: add notification to re-enable channels after a radio reset. 4450a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby */ 4550a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hambypublic class CellBroadcastConfigService extends IntentService { 4650a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby private static final String TAG = "CellBroadcastConfigService"; 4750a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby 4850a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby static final String ACTION_ENABLE_CHANNELS = "ACTION_ENABLE_CHANNELS"; 4950a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby 5050a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby public CellBroadcastConfigService() { 5150a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby super(TAG); // use class name for worker thread name 5250a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby } 5350a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby 5459610ad5074acb5305c353a53c01676eb8258887Jake Hamby private void setChannelRange(SmsManager manager, String ranges, boolean enable) { 5559610ad5074acb5305c353a53c01676eb8258887Jake Hamby try { 5659610ad5074acb5305c353a53c01676eb8258887Jake Hamby for (String channelRange : ranges.split(",")) { 5759610ad5074acb5305c353a53c01676eb8258887Jake Hamby int dashIndex = channelRange.indexOf('-'); 5859610ad5074acb5305c353a53c01676eb8258887Jake Hamby if (dashIndex != -1) { 5959610ad5074acb5305c353a53c01676eb8258887Jake Hamby int startId = Integer.decode(channelRange.substring(0, dashIndex)); 6059610ad5074acb5305c353a53c01676eb8258887Jake Hamby int endId = Integer.decode(channelRange.substring(dashIndex + 1)); 6159610ad5074acb5305c353a53c01676eb8258887Jake Hamby if (enable) { 6259610ad5074acb5305c353a53c01676eb8258887Jake Hamby if (DBG) Log.d(TAG, "enabling emergency IDs " + startId + '-' + endId); 6359610ad5074acb5305c353a53c01676eb8258887Jake Hamby manager.enableCellBroadcastRange(startId, endId); 6459610ad5074acb5305c353a53c01676eb8258887Jake Hamby } else { 6559610ad5074acb5305c353a53c01676eb8258887Jake Hamby if (DBG) Log.d(TAG, "disabling emergency IDs " + startId + '-' + endId); 6659610ad5074acb5305c353a53c01676eb8258887Jake Hamby manager.disableCellBroadcastRange(startId, endId); 6759610ad5074acb5305c353a53c01676eb8258887Jake Hamby } 6859610ad5074acb5305c353a53c01676eb8258887Jake Hamby } else { 6959610ad5074acb5305c353a53c01676eb8258887Jake Hamby int messageId = Integer.decode(channelRange); 7059610ad5074acb5305c353a53c01676eb8258887Jake Hamby if (enable) { 7159610ad5074acb5305c353a53c01676eb8258887Jake Hamby if (DBG) Log.d(TAG, "enabling emergency message ID " + messageId); 7259610ad5074acb5305c353a53c01676eb8258887Jake Hamby manager.enableCellBroadcast(messageId); 7359610ad5074acb5305c353a53c01676eb8258887Jake Hamby } else { 7459610ad5074acb5305c353a53c01676eb8258887Jake Hamby if (DBG) Log.d(TAG, "disabling emergency message ID " + messageId); 7559610ad5074acb5305c353a53c01676eb8258887Jake Hamby manager.disableCellBroadcast(messageId); 7659610ad5074acb5305c353a53c01676eb8258887Jake Hamby } 7759610ad5074acb5305c353a53c01676eb8258887Jake Hamby } 7859610ad5074acb5305c353a53c01676eb8258887Jake Hamby } 7959610ad5074acb5305c353a53c01676eb8258887Jake Hamby } catch (NumberFormatException e) { 8059610ad5074acb5305c353a53c01676eb8258887Jake Hamby Log.e(TAG, "Number Format Exception parsing emergency channel range", e); 8159610ad5074acb5305c353a53c01676eb8258887Jake Hamby } 8259610ad5074acb5305c353a53c01676eb8258887Jake Hamby } 8359610ad5074acb5305c353a53c01676eb8258887Jake Hamby 84f88de2b37383f138b3c7d876bdc3b6b6fae7b728Jake Hamby static boolean isOperatorDefinedEmergencyId(int messageId) { 85f88de2b37383f138b3c7d876bdc3b6b6fae7b728Jake Hamby // Check for system property defining the emergency channel ranges to enable 86f88de2b37383f138b3c7d876bdc3b6b6fae7b728Jake Hamby String emergencyIdRange = SystemProperties.get("ro.cellbroadcast.emergencyids"); 87f88de2b37383f138b3c7d876bdc3b6b6fae7b728Jake Hamby if (TextUtils.isEmpty(emergencyIdRange)) { 88f88de2b37383f138b3c7d876bdc3b6b6fae7b728Jake Hamby return false; 89f88de2b37383f138b3c7d876bdc3b6b6fae7b728Jake Hamby } 90f88de2b37383f138b3c7d876bdc3b6b6fae7b728Jake Hamby try { 91f88de2b37383f138b3c7d876bdc3b6b6fae7b728Jake Hamby for (String channelRange : emergencyIdRange.split(",")) { 92f88de2b37383f138b3c7d876bdc3b6b6fae7b728Jake Hamby int dashIndex = channelRange.indexOf('-'); 93f88de2b37383f138b3c7d876bdc3b6b6fae7b728Jake Hamby if (dashIndex != -1) { 94f88de2b37383f138b3c7d876bdc3b6b6fae7b728Jake Hamby int startId = Integer.decode(channelRange.substring(0, dashIndex)); 95f88de2b37383f138b3c7d876bdc3b6b6fae7b728Jake Hamby int endId = Integer.decode(channelRange.substring(dashIndex + 1)); 96f88de2b37383f138b3c7d876bdc3b6b6fae7b728Jake Hamby if (messageId >= startId && messageId <= endId) { 97f88de2b37383f138b3c7d876bdc3b6b6fae7b728Jake Hamby return true; 98f88de2b37383f138b3c7d876bdc3b6b6fae7b728Jake Hamby } 99f88de2b37383f138b3c7d876bdc3b6b6fae7b728Jake Hamby } else { 100f88de2b37383f138b3c7d876bdc3b6b6fae7b728Jake Hamby int emergencyMessageId = Integer.decode(channelRange); 101f88de2b37383f138b3c7d876bdc3b6b6fae7b728Jake Hamby if (emergencyMessageId == messageId) { 102f88de2b37383f138b3c7d876bdc3b6b6fae7b728Jake Hamby return true; 103f88de2b37383f138b3c7d876bdc3b6b6fae7b728Jake Hamby } 104f88de2b37383f138b3c7d876bdc3b6b6fae7b728Jake Hamby } 105f88de2b37383f138b3c7d876bdc3b6b6fae7b728Jake Hamby } 106f88de2b37383f138b3c7d876bdc3b6b6fae7b728Jake Hamby } catch (NumberFormatException e) { 107f88de2b37383f138b3c7d876bdc3b6b6fae7b728Jake Hamby Log.e(TAG, "Number Format Exception parsing emergency channel range", e); 108f88de2b37383f138b3c7d876bdc3b6b6fae7b728Jake Hamby } 109f88de2b37383f138b3c7d876bdc3b6b6fae7b728Jake Hamby return false; 110f88de2b37383f138b3c7d876bdc3b6b6fae7b728Jake Hamby } 111f88de2b37383f138b3c7d876bdc3b6b6fae7b728Jake Hamby 11250a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby @Override 11350a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby protected void onHandleIntent(Intent intent) { 11450a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby if (ACTION_ENABLE_CHANNELS.equals(intent.getAction())) { 11550a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby try { 11650a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); 11750a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby Resources res = getResources(); 11850a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby 11959610ad5074acb5305c353a53c01676eb8258887Jake Hamby // Check for system property defining the emergency channel ranges to enable 12059610ad5074acb5305c353a53c01676eb8258887Jake Hamby String emergencyIdRange = SystemProperties.get("ro.cellbroadcast.emergencyids"); 12159610ad5074acb5305c353a53c01676eb8258887Jake Hamby 12250a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby boolean enableEmergencyAlerts = prefs.getBoolean( 12350a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby CellBroadcastSettings.KEY_ENABLE_EMERGENCY_ALERTS, true); 12450a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby 12550a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby boolean enableChannel50Alerts = res.getBoolean(R.bool.show_brazil_settings) && 12650a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby prefs.getBoolean(CellBroadcastSettings.KEY_ENABLE_CHANNEL_50_ALERTS, true); 12750a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby 12850a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby SmsManager manager = SmsManager.getDefault(); 12950a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby if (enableEmergencyAlerts) { 13050a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby if (DBG) Log.d(TAG, "enabling emergency cell broadcast channels"); 13159610ad5074acb5305c353a53c01676eb8258887Jake Hamby if (!TextUtils.isEmpty(emergencyIdRange)) { 13259610ad5074acb5305c353a53c01676eb8258887Jake Hamby setChannelRange(manager, emergencyIdRange, true); 13359610ad5074acb5305c353a53c01676eb8258887Jake Hamby } else { 13459610ad5074acb5305c353a53c01676eb8258887Jake Hamby // No emergency channel system property, enable all emergency channels 13559610ad5074acb5305c353a53c01676eb8258887Jake Hamby manager.enableCellBroadcastRange( 13659610ad5074acb5305c353a53c01676eb8258887Jake Hamby SmsCbConstants.MESSAGE_ID_PWS_FIRST_IDENTIFIER, 13759610ad5074acb5305c353a53c01676eb8258887Jake Hamby SmsCbConstants.MESSAGE_ID_PWS_LAST_IDENTIFIER); 13859610ad5074acb5305c353a53c01676eb8258887Jake Hamby } 13950a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby if (DBG) Log.d(TAG, "enabled emergency cell broadcast channels"); 14050a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby } else { 14150a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby // we may have enabled these channels previously, so try to disable them 14250a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby if (DBG) Log.d(TAG, "disabling emergency cell broadcast channels"); 14359610ad5074acb5305c353a53c01676eb8258887Jake Hamby if (!TextUtils.isEmpty(emergencyIdRange)) { 14459610ad5074acb5305c353a53c01676eb8258887Jake Hamby setChannelRange(manager, emergencyIdRange, false); 14559610ad5074acb5305c353a53c01676eb8258887Jake Hamby } else { 14659610ad5074acb5305c353a53c01676eb8258887Jake Hamby // No emergency channel system property, disable all emergency channels 14759610ad5074acb5305c353a53c01676eb8258887Jake Hamby manager.disableCellBroadcastRange( 14859610ad5074acb5305c353a53c01676eb8258887Jake Hamby SmsCbConstants.MESSAGE_ID_PWS_FIRST_IDENTIFIER, 14959610ad5074acb5305c353a53c01676eb8258887Jake Hamby SmsCbConstants.MESSAGE_ID_PWS_LAST_IDENTIFIER); 15059610ad5074acb5305c353a53c01676eb8258887Jake Hamby } 15150a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby if (DBG) Log.d(TAG, "disabled emergency cell broadcast channels"); 15250a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby } 15350a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby 15450a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby if (enableChannel50Alerts) { 15550a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby if (DBG) Log.d(TAG, "enabling cell broadcast channel 50"); 15650a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby manager.enableCellBroadcast(50); 15750a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby if (DBG) Log.d(TAG, "enabled cell broadcast channel 50"); 15850a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby } else { 15950a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby if (DBG) Log.d(TAG, "disabling cell broadcast channel 50"); 16050a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby manager.disableCellBroadcast(50); 16150a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby if (DBG) Log.d(TAG, "disabled cell broadcast channel 50"); 16250a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby } 16350a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby } catch (Exception ex) { 16450a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby Log.e(TAG, "exception enabling cell broadcast channels", ex); 16550a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby } 16650a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby } 16750a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby } 16850a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby} 169