CellBroadcastReceiver.java revision 00b87064abfb9d254fbbf72110643d2e626365e6
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) {
4450a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby        if (DBG) Log.d(TAG, "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) {
7000b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby                CdmaSmsCbProgramData[] programDataList = (CdmaSmsCbProgramData[])
7100b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby                        intent.getParcelableArrayExtra("program_data_list");
7200b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby                if (programDataList != null) {
7300b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby                    handleCdmaSmsCbProgramData(context, programDataList);
7400b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby                } else {
7500b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby                    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    /**
8600b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby     * Handle Service Category Program Data message.
8700b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby     * TODO: Send Service Category Program Results response message to sender
8800b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby     *
8900b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby     * @param context
9000b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby     * @param programDataList
9100b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby     */
9200b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby    private void handleCdmaSmsCbProgramData(Context context,
9300b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby            CdmaSmsCbProgramData[] programDataList) {
9400b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby        for (CdmaSmsCbProgramData programData : programDataList) {
9500b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby            switch (programData.getOperation()) {
9600b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby                case CdmaSmsCbProgramData.OPERATION_ADD_CATEGORY:
9700b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby                    tryCdmaSetCategory(context, programData.getCategory(), true);
9800b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby                    break;
9900b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby
10000b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby                case CdmaSmsCbProgramData.OPERATION_DELETE_CATEGORY:
10100b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby                    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        }
11900b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby    }
12000b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby
12100b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby    private void tryCdmaSetCategory(Context context, int category, boolean enable) {
12200b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby        SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
12300b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby
12400b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby        switch (category) {
12500b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby            case SmsEnvelope.SERVICE_CATEGORY_CMAS_EXTREME_THREAT:
12600b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby                sharedPrefs.edit().putBoolean(
12700b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby                        CellBroadcastSettings.KEY_ENABLE_CMAS_EXTREME_THREAT_ALERTS, enable)
12800b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby                        .apply();
12900b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby                break;
13000b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby
13100b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby            case SmsEnvelope.SERVICE_CATEGORY_CMAS_SEVERE_THREAT:
13200b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby                sharedPrefs.edit().putBoolean(
13300b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby                        CellBroadcastSettings.KEY_ENABLE_CMAS_SEVERE_THREAT_ALERTS, enable)
13400b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby                        .apply();
13500b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby                break;
13600b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby
13700b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby            case SmsEnvelope.SERVICE_CATEGORY_CMAS_CHILD_ABDUCTION_EMERGENCY:
13800b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby                sharedPrefs.edit().putBoolean(
13900b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby                        CellBroadcastSettings.KEY_ENABLE_CMAS_AMBER_ALERTS, enable).apply();
14000b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby                break;
14100b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby
14200b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby            case SmsEnvelope.SERVICE_CATEGORY_CMAS_TEST_MESSAGE:
14300b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby                sharedPrefs.edit().putBoolean(
14400b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby                        CellBroadcastSettings.KEY_ENABLE_CMAS_TEST_ALERTS, enable).apply();
14500b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby                break;
14600b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby
14700b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby            default:
14800b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby                Log.w(TAG, "Ignoring SCPD command to " + (enable ? "enable" : "disable")
14900b87064abfb9d254fbbf72110643d2e626365e6Jake Hamby                        + " 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()) {
15950a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby            Log.d(TAG, "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    }
18250a624a47ce645a7992e346e40a4e7ec5e0df9b7Jake Hamby}
183