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