CellBroadcastReceiver.java revision a028d57ae657c29873abd1ba6969f6e4ce835eba
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.content.BroadcastReceiver; 20import android.content.Context; 21import android.content.Intent; 22import android.content.SharedPreferences; 23import android.os.RemoteException; 24import android.os.ServiceManager; 25import android.preference.PreferenceManager; 26import android.provider.Telephony; 27import android.telephony.TelephonyManager; 28import android.telephony.cdma.CdmaSmsCbProgramData; 29import android.util.Log; 30 31import com.android.internal.telephony.ITelephony; 32import com.android.internal.telephony.cdma.sms.SmsEnvelope; 33 34public class CellBroadcastReceiver extends BroadcastReceiver { 35 private static final String TAG = "CellBroadcastReceiver"; 36 static final boolean DBG = true; // STOPSHIP: change to false before ship 37 38 @Override 39 public void onReceive(Context context, Intent intent) { 40 onReceiveWithPrivilege(context, intent, false); 41 } 42 43 protected void onReceiveWithPrivilege(Context context, Intent intent, boolean privileged) { 44 if (DBG) log("onReceive " + intent); 45 46 String action = intent.getAction(); 47 48 if (Intent.ACTION_BOOT_COMPLETED.equals(action)) { 49 startConfigService(context); 50 } else if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(action)) { 51 boolean airplaneModeOn = intent.getBooleanExtra("state", false); 52 if (DBG) log("airplaneModeOn: " + airplaneModeOn); 53 if (!airplaneModeOn) { 54 startConfigService(context); 55 } 56 } else if (Telephony.Sms.Intents.SMS_EMERGENCY_CB_RECEIVED_ACTION.equals(action) || 57 Telephony.Sms.Intents.SMS_CB_RECEIVED_ACTION.equals(action)) { 58 // If 'privileged' is false, it means that the intent was delivered to the base 59 // no-permissions receiver class. If we get an SMS_CB_RECEIVED message that way, it 60 // means someone has tried to spoof the message by delivering it outside the normal 61 // permission-checked route, so we just ignore it. 62 if (privileged) { 63 intent.setClass(context, CellBroadcastAlertService.class); 64 context.startService(intent); 65 } else { 66 loge("ignoring unprivileged action received " + action); 67 } 68 } else if (Telephony.Sms.Intents.SMS_SERVICE_CATEGORY_PROGRAM_DATA_RECEIVED_ACTION 69 .equals(action)) { 70 if (privileged) { 71 CdmaSmsCbProgramData[] programDataList = (CdmaSmsCbProgramData[]) 72 intent.getParcelableArrayExtra("program_data_list"); 73 if (programDataList != null) { 74 handleCdmaSmsCbProgramData(context, programDataList); 75 } else { 76 loge("SCPD intent received with no program_data_list"); 77 } 78 } else { 79 loge("ignoring unprivileged action received " + action); 80 } 81 } else { 82 Log.w(TAG, "onReceive() unexpected action " + action); 83 } 84 } 85 86 /** 87 * Handle Service Category Program Data message. 88 * TODO: Send Service Category Program Results response message to sender 89 * 90 * @param context 91 * @param programDataList 92 */ 93 private void handleCdmaSmsCbProgramData(Context context, 94 CdmaSmsCbProgramData[] programDataList) { 95 for (CdmaSmsCbProgramData programData : programDataList) { 96 switch (programData.getOperation()) { 97 case CdmaSmsCbProgramData.OPERATION_ADD_CATEGORY: 98 tryCdmaSetCategory(context, programData.getCategory(), true); 99 break; 100 101 case CdmaSmsCbProgramData.OPERATION_DELETE_CATEGORY: 102 tryCdmaSetCategory(context, programData.getCategory(), false); 103 break; 104 105 case CdmaSmsCbProgramData.OPERATION_CLEAR_CATEGORIES: 106 tryCdmaSetCategory(context, 107 SmsEnvelope.SERVICE_CATEGORY_CMAS_EXTREME_THREAT, false); 108 tryCdmaSetCategory(context, 109 SmsEnvelope.SERVICE_CATEGORY_CMAS_SEVERE_THREAT, false); 110 tryCdmaSetCategory(context, 111 SmsEnvelope.SERVICE_CATEGORY_CMAS_CHILD_ABDUCTION_EMERGENCY, false); 112 tryCdmaSetCategory(context, 113 SmsEnvelope.SERVICE_CATEGORY_CMAS_TEST_MESSAGE, false); 114 break; 115 116 default: 117 loge("Ignoring unknown SCPD operation " + programData.getOperation()); 118 } 119 } 120 } 121 122 private void tryCdmaSetCategory(Context context, int category, boolean enable) { 123 SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context); 124 125 switch (category) { 126 case SmsEnvelope.SERVICE_CATEGORY_CMAS_EXTREME_THREAT: 127 sharedPrefs.edit().putBoolean( 128 CellBroadcastSettings.KEY_ENABLE_CMAS_EXTREME_THREAT_ALERTS, enable) 129 .apply(); 130 break; 131 132 case SmsEnvelope.SERVICE_CATEGORY_CMAS_SEVERE_THREAT: 133 sharedPrefs.edit().putBoolean( 134 CellBroadcastSettings.KEY_ENABLE_CMAS_SEVERE_THREAT_ALERTS, enable) 135 .apply(); 136 break; 137 138 case SmsEnvelope.SERVICE_CATEGORY_CMAS_CHILD_ABDUCTION_EMERGENCY: 139 sharedPrefs.edit().putBoolean( 140 CellBroadcastSettings.KEY_ENABLE_CMAS_AMBER_ALERTS, enable).apply(); 141 break; 142 143 case SmsEnvelope.SERVICE_CATEGORY_CMAS_TEST_MESSAGE: 144 sharedPrefs.edit().putBoolean( 145 CellBroadcastSettings.KEY_ENABLE_CMAS_TEST_ALERTS, enable).apply(); 146 break; 147 148 default: 149 Log.w(TAG, "Ignoring SCPD command to " + (enable ? "enable" : "disable") 150 + " alerts in category " + category); 151 } 152 } 153 154 /** 155 * Tell {@link CellBroadcastConfigService} to enable the CB channels. 156 * @param context the broadcast receiver context 157 */ 158 static void startConfigService(Context context) { 159 Intent serviceIntent = new Intent(CellBroadcastConfigService.ACTION_ENABLE_CHANNELS, 160 null, context, CellBroadcastConfigService.class); 161 context.startService(serviceIntent); 162 } 163 164 /** 165 * @return true if the phone is a CDMA phone type 166 */ 167 static boolean phoneIsCdma() { 168 boolean isCdma = false; 169 try { 170 ITelephony phone = ITelephony.Stub.asInterface(ServiceManager.checkService("phone")); 171 if (phone != null) { 172 isCdma = (phone.getActivePhoneType() == TelephonyManager.PHONE_TYPE_CDMA); 173 } 174 } catch (RemoteException e) { 175 Log.w(TAG, "phone.getActivePhoneType() failed", e); 176 } 177 return isCdma; 178 } 179 180 private static void log(String msg) { 181 Log.d(TAG, msg); 182 } 183 184 private static void loge(String msg) { 185 Log.e(TAG, msg); 186 } 187} 188