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.content.BroadcastReceiver; 2050a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hambyimport android.content.Context; 2150a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hambyimport android.content.Intent; 2200b87064abfb9d254fbbf72110643d2e626365e6Jake Hambyimport android.content.SharedPreferences; 2350a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hambyimport android.os.RemoteException; 2450a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hambyimport android.os.ServiceManager; 2500b87064abfb9d254fbbf72110643d2e626365e6Jake Hambyimport android.preference.PreferenceManager; 2650a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hambyimport android.provider.Telephony; 2750a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hambyimport android.telephony.TelephonyManager; 2800b87064abfb9d254fbbf72110643d2e626365e6Jake Hambyimport android.telephony.cdma.CdmaSmsCbProgramData; 2950a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hambyimport android.util.Log; 3050a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby 3150a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hambyimport com.android.internal.telephony.ITelephony; 3200b87064abfb9d254fbbf72110643d2e626365e6Jake Hambyimport com.android.internal.telephony.cdma.sms.SmsEnvelope; 3350a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby 3450a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hambypublic class CellBroadcastReceiver extends BroadcastReceiver { 3550a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby private static final String TAG = "CellBroadcastReceiver"; 3600b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby static final boolean DBG = true; // STOPSHIP: change to false before ship 3750a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby 3850a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby @Override 3950a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby public void onReceive(Context context, Intent intent) { 4050a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby onReceiveWithPrivilege(context, intent, false); 4150a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby } 4250a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby 4350a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby protected void onReceiveWithPrivilege(Context context, Intent intent, boolean privileged) { 44da5c415f6d0999131e93384b5fb90422ada8e4daJake Hamby if (DBG) log("onReceive " + intent); 4550a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby 4650a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby String action = intent.getAction(); 4750a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby 4850a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby if (Intent.ACTION_BOOT_COMPLETED.equals(action)) { 4950a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby startConfigService(context); 5050a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby } else if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(action)) { 5150a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby boolean airplaneModeOn = intent.getBooleanExtra("state", false); 5250a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby if (!airplaneModeOn) { 5350a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby startConfigService(context); 5450a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby } 5550a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby } else if (Telephony.Sms.Intents.SMS_EMERGENCY_CB_RECEIVED_ACTION.equals(action) || 5650a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby Telephony.Sms.Intents.SMS_CB_RECEIVED_ACTION.equals(action)) { 5750a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby // If 'privileged' is false, it means that the intent was delivered to the base 5850a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby // no-permissions receiver class. If we get an SMS_CB_RECEIVED message that way, it 5950a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby // means someone has tried to spoof the message by delivering it outside the normal 6050a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby // permission-checked route, so we just ignore it. 6150a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby if (privileged) { 6250a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby intent.setClass(context, CellBroadcastAlertService.class); 6350a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby context.startService(intent); 6450a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby } else { 6550a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby Log.e(TAG, "ignoring unprivileged action received " + action); 6650a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby } 6700b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby } else if (Telephony.Sms.Intents.SMS_SERVICE_CATEGORY_PROGRAM_DATA_RECEIVED_ACTION 6800b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby .equals(action)) { 6900b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby if (privileged) { 70e707fd18bd5170f8f8f0320921899f1683747c6bEd Heyl CdmaSmsCbProgramData[] programDataList = (CdmaSmsCbProgramData[]) 71e707fd18bd5170f8f8f0320921899f1683747c6bEd Heyl intent.getParcelableArrayExtra("program_data_list"); 72e707fd18bd5170f8f8f0320921899f1683747c6bEd Heyl if (programDataList != null) { 73e707fd18bd5170f8f8f0320921899f1683747c6bEd Heyl handleCdmaSmsCbProgramData(context, programDataList); 74e707fd18bd5170f8f8f0320921899f1683747c6bEd Heyl } else { 75e707fd18bd5170f8f8f0320921899f1683747c6bEd Heyl Log.e(TAG, "SCPD intent received with no program_data_list"); 7600b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby } 7700b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby } else { 7800b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby Log.e(TAG, "ignoring unprivileged action received " + action); 7900b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby } 8050a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby } else { 8150a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby Log.w(TAG, "onReceive() unexpected action " + action); 8250a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby } 8350a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby } 8450a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby 8550a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby /** 86e707fd18bd5170f8f8f0320921899f1683747c6bEd Heyl * Handle Service Category Program Data message. 87e707fd18bd5170f8f8f0320921899f1683747c6bEd Heyl * TODO: Send Service Category Program Results response message to sender 8800b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby * 89e707fd18bd5170f8f8f0320921899f1683747c6bEd Heyl * @param context 90e707fd18bd5170f8f8f0320921899f1683747c6bEd Heyl * @param programDataList 9100b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby */ 92e707fd18bd5170f8f8f0320921899f1683747c6bEd Heyl private void handleCdmaSmsCbProgramData(Context context, 93e707fd18bd5170f8f8f0320921899f1683747c6bEd Heyl CdmaSmsCbProgramData[] programDataList) { 9400b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby for (CdmaSmsCbProgramData programData : programDataList) { 9500b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby switch (programData.getOperation()) { 9600b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby case CdmaSmsCbProgramData.OPERATION_ADD_CATEGORY: 97e707fd18bd5170f8f8f0320921899f1683747c6bEd Heyl tryCdmaSetCategory(context, programData.getCategory(), true); 9800b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby break; 9900b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby 10000b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby case CdmaSmsCbProgramData.OPERATION_DELETE_CATEGORY: 101e707fd18bd5170f8f8f0320921899f1683747c6bEd Heyl tryCdmaSetCategory(context, programData.getCategory(), false); 10200b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby break; 10300b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby 10400b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby case CdmaSmsCbProgramData.OPERATION_CLEAR_CATEGORIES: 10500b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby tryCdmaSetCategory(context, 10600b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby SmsEnvelope.SERVICE_CATEGORY_CMAS_EXTREME_THREAT, false); 10700b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby tryCdmaSetCategory(context, 10800b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby SmsEnvelope.SERVICE_CATEGORY_CMAS_SEVERE_THREAT, false); 10900b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby tryCdmaSetCategory(context, 11000b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby SmsEnvelope.SERVICE_CATEGORY_CMAS_CHILD_ABDUCTION_EMERGENCY, false); 11100b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby tryCdmaSetCategory(context, 11200b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby SmsEnvelope.SERVICE_CATEGORY_CMAS_TEST_MESSAGE, false); 11300b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby break; 11400b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby 11500b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby default: 11600b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby Log.e(TAG, "Ignoring unknown SCPD operation " + programData.getOperation()); 11700b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby } 11800b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby } 11921f2b9ac08ca93cee099292ba597b9a45e846030Jake Hamby } 12000b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby 121e707fd18bd5170f8f8f0320921899f1683747c6bEd Heyl private void tryCdmaSetCategory(Context context, int category, boolean enable) { 122e707fd18bd5170f8f8f0320921899f1683747c6bEd Heyl SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context); 123e707fd18bd5170f8f8f0320921899f1683747c6bEd Heyl 12400b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby switch (category) { 12500b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby case SmsEnvelope.SERVICE_CATEGORY_CMAS_EXTREME_THREAT: 126e707fd18bd5170f8f8f0320921899f1683747c6bEd Heyl sharedPrefs.edit().putBoolean( 127e707fd18bd5170f8f8f0320921899f1683747c6bEd Heyl CellBroadcastSettings.KEY_ENABLE_CMAS_EXTREME_THREAT_ALERTS, enable) 128e707fd18bd5170f8f8f0320921899f1683747c6bEd Heyl .apply(); 12900b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby break; 13000b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby 13100b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby case SmsEnvelope.SERVICE_CATEGORY_CMAS_SEVERE_THREAT: 132e707fd18bd5170f8f8f0320921899f1683747c6bEd Heyl sharedPrefs.edit().putBoolean( 133e707fd18bd5170f8f8f0320921899f1683747c6bEd Heyl CellBroadcastSettings.KEY_ENABLE_CMAS_SEVERE_THREAT_ALERTS, enable) 134e707fd18bd5170f8f8f0320921899f1683747c6bEd Heyl .apply(); 13500b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby break; 13600b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby 13700b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby case SmsEnvelope.SERVICE_CATEGORY_CMAS_CHILD_ABDUCTION_EMERGENCY: 138e707fd18bd5170f8f8f0320921899f1683747c6bEd Heyl sharedPrefs.edit().putBoolean( 139e707fd18bd5170f8f8f0320921899f1683747c6bEd Heyl CellBroadcastSettings.KEY_ENABLE_CMAS_AMBER_ALERTS, enable).apply(); 14000b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby break; 14100b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby 14200b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby case SmsEnvelope.SERVICE_CATEGORY_CMAS_TEST_MESSAGE: 143e707fd18bd5170f8f8f0320921899f1683747c6bEd Heyl sharedPrefs.edit().putBoolean( 144e707fd18bd5170f8f8f0320921899f1683747c6bEd Heyl CellBroadcastSettings.KEY_ENABLE_CMAS_TEST_ALERTS, enable).apply(); 14500b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby break; 14600b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby 14700b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby default: 148e707fd18bd5170f8f8f0320921899f1683747c6bEd Heyl Log.w(TAG, "Ignoring SCPD command to " + (enable ? "enable" : "disable") 149e707fd18bd5170f8f8f0320921899f1683747c6bEd Heyl + " alerts in category " + category); 15000b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby } 15100b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby } 15200b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby 15300b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby /** 15450a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby * Tell {@link CellBroadcastConfigService} to enable the CB channels. 15550a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby * @param context the broadcast receiver context 15650a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby */ 15750a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby static void startConfigService(Context context) { 15850a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby if (phoneIsCdma()) { 159da5c415f6d0999131e93384b5fb90422ada8e4daJake Hamby if (DBG) log("CDMA phone detected; doing nothing"); 16050a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby } else { 16150a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby Intent serviceIntent = new Intent(CellBroadcastConfigService.ACTION_ENABLE_CHANNELS, 16250a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby null, context, CellBroadcastConfigService.class); 16350a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby context.startService(serviceIntent); 16450a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby } 16550a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby } 16650a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby 16750a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby /** 16850a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby * @return true if the phone is a CDMA phone type 16950a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby */ 17050a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby private static boolean phoneIsCdma() { 17150a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby boolean isCdma = false; 17250a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby try { 17350a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby ITelephony phone = ITelephony.Stub.asInterface(ServiceManager.checkService("phone")); 17450a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby if (phone != null) { 17550a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby isCdma = (phone.getActivePhoneType() == TelephonyManager.PHONE_TYPE_CDMA); 17650a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby } 17750a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby } catch (RemoteException e) { 17850a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby Log.w(TAG, "phone.getActivePhoneType() failed", e); 17950a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby } 18050a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby return isCdma; 18150a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby } 182da5c415f6d0999131e93384b5fb90422ada8e4daJake Hamby 183da5c415f6d0999131e93384b5fb90422ada8e4daJake Hamby private static void log(String msg) { 184da5c415f6d0999131e93384b5fb90422ada8e4daJake Hamby Log.d(TAG, msg); 185da5c415f6d0999131e93384b5fb90422ada8e4daJake Hamby } 18650a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby} 187