CdmaServiceCategoryProgramHandler.java revision d2feaf918ab0c1173d4ada182532e48d0c0d3f77
10d4bcdf379842af4b6304809156971e926f374f0Jake Hamby/*
20d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * Copyright (C) 2013 The Android Open Source Project
30d4bcdf379842af4b6304809156971e926f374f0Jake Hamby *
40d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * Licensed under the Apache License, Version 2.0 (the "License");
50d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * you may not use this file except in compliance with the License.
60d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * You may obtain a copy of the License at
70d4bcdf379842af4b6304809156971e926f374f0Jake Hamby *
80d4bcdf379842af4b6304809156971e926f374f0Jake Hamby *      http://www.apache.org/licenses/LICENSE-2.0
90d4bcdf379842af4b6304809156971e926f374f0Jake Hamby *
100d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * Unless required by applicable law or agreed to in writing, software
110d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * distributed under the License is distributed on an "AS IS" BASIS,
120d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * See the License for the specific language governing permissions and
140d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * limitations under the License.
150d4bcdf379842af4b6304809156971e926f374f0Jake Hamby */
160d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
170d4bcdf379842af4b6304809156971e926f374f0Jake Hambypackage com.android.internal.telephony.cdma;
180d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
190d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport android.Manifest;
200d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport android.app.Activity;
210d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport android.app.AppOpsManager;
220d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport android.content.BroadcastReceiver;
230d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport android.content.Context;
240d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport android.content.Intent;
250d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport android.os.Bundle;
260d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport android.os.Message;
270d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport android.provider.Telephony.Sms.Intents;
280d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport android.telephony.PhoneNumberUtils;
290d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport android.telephony.cdma.CdmaSmsCbProgramData;
300d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport android.telephony.cdma.CdmaSmsCbProgramResults;
310d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
320d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport com.android.internal.telephony.CommandsInterface;
330d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport com.android.internal.telephony.WakeLockStateMachine;
340d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport com.android.internal.telephony.cdma.sms.BearerData;
350d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport com.android.internal.telephony.cdma.sms.CdmaSmsAddress;
360d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport com.android.internal.telephony.cdma.sms.SmsEnvelope;
370d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
380d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport java.io.ByteArrayOutputStream;
390d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport java.io.DataOutputStream;
400d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport java.io.IOException;
410d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport java.util.ArrayList;
420d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
430d4bcdf379842af4b6304809156971e926f374f0Jake Hamby/**
440d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * Handle CDMA Service Category Program Data requests and responses.
450d4bcdf379842af4b6304809156971e926f374f0Jake Hamby */
460d4bcdf379842af4b6304809156971e926f374f0Jake Hambypublic final class CdmaServiceCategoryProgramHandler extends WakeLockStateMachine {
470d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
480d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    final CommandsInterface mCi;
490d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
500d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    /**
510d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * Create a new CDMA inbound SMS handler.
520d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     */
530d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    CdmaServiceCategoryProgramHandler(Context context, CommandsInterface commandsInterface) {
54d2feaf918ab0c1173d4ada182532e48d0c0d3f77Wink Saville        super("CdmaServiceCategoryProgramHandler", context, null);
550d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        mContext = context;
560d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        mCi = commandsInterface;
570d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    }
580d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
590d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    /**
600d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * Create a new State machine for SCPD requests.
610d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * @param context the context to use
620d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * @param commandsInterface the radio commands interface
630d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * @return the new SCPD handler
640d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     */
650d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    static CdmaServiceCategoryProgramHandler makeScpHandler(Context context,
660d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            CommandsInterface commandsInterface) {
670d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        CdmaServiceCategoryProgramHandler handler = new CdmaServiceCategoryProgramHandler(
680d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                context, commandsInterface);
690d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        handler.start();
700d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        return handler;
710d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    }
720d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
730d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    /**
740d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * Handle Cell Broadcast messages from {@code CdmaInboundSmsHandler}.
750d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * 3GPP-format Cell Broadcast messages sent from radio are handled in the subclass.
760d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     *
770d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * @param message the message to process
780d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * @return true if an ordered broadcast was sent; false on failure
790d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     */
800d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    @Override
810d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    protected boolean handleSmsMessage(Message message) {
820d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        if (message.obj instanceof SmsMessage) {
830d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            return handleServiceCategoryProgramData((SmsMessage) message.obj);
840d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        } else {
850d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            loge("handleMessage got object of type: " + message.obj.getClass().getName());
860d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            return false;
870d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        }
880d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    }
890d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
900d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
910d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    /**
920d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * Send SCPD request to CellBroadcastReceiver as an ordered broadcast.
930d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * @param sms the CDMA SmsMessage containing the SCPD request
940d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * @return true if an ordered broadcast was sent; false on failure
950d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     */
960d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    private boolean handleServiceCategoryProgramData(SmsMessage sms) {
970d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        ArrayList<CdmaSmsCbProgramData> programDataList = sms.getSmsCbProgramData();
980d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        if (programDataList == null) {
990d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            loge("handleServiceCategoryProgramData: program data list is null!");
1000d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            return false;
1010d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        }
1020d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
1030d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        Intent intent = new Intent(Intents.SMS_SERVICE_CATEGORY_PROGRAM_DATA_RECEIVED_ACTION);
1040d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        intent.putExtra("sender", sms.getOriginatingAddress());
1050d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        intent.putParcelableArrayListExtra("program_data", programDataList);
1060d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
1070d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        mContext.sendOrderedBroadcast(intent, Manifest.permission.RECEIVE_SMS,
1080d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                AppOpsManager.OP_RECEIVE_SMS, mScpResultsReceiver,
1090d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                getHandler(), Activity.RESULT_OK, null, null);
1100d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        return true;
1110d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    }
1120d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
1130d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    /**
1140d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * Broadcast receiver to handle results of ordered broadcast. Sends the SCPD results
1150d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     * as a reply SMS, then sends a message to state machine to transition to idle.
1160d4bcdf379842af4b6304809156971e926f374f0Jake Hamby     */
1170d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    private final BroadcastReceiver mScpResultsReceiver = new BroadcastReceiver() {
1180d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        @Override
1190d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        public void onReceive(Context context, Intent intent) {
1200d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            sendScpResults();
1210d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            if (DBG) log("mScpResultsReceiver finished");
1220d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            sendMessage(EVENT_BROADCAST_COMPLETE);
1230d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        }
1240d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
1250d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        private void sendScpResults() {
1260d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            int resultCode = getResultCode();
1270d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            if ((resultCode != Activity.RESULT_OK) && (resultCode != Intents.RESULT_SMS_HANDLED)) {
1280d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                loge("SCP results error: result code = " + resultCode);
1290d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                return;
1300d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            }
1310d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            Bundle extras = getResultExtras(false);
1320d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            if (extras == null) {
1330d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                loge("SCP results error: missing extras");
1340d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                return;
1350d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            }
1360d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            String sender = extras.getString("sender");
1370d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            if (sender == null) {
1380d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                loge("SCP results error: missing sender extra.");
1390d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                return;
1400d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            }
1410d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            ArrayList<CdmaSmsCbProgramResults> results
1420d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                    = extras.getParcelableArrayList("results");
1430d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            if (results == null) {
1440d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                loge("SCP results error: missing results extra.");
1450d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                return;
1460d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            }
1470d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
1480d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            BearerData bData = new BearerData();
1490d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            bData.messageType = BearerData.MESSAGE_TYPE_SUBMIT;
1500d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            bData.messageId = SmsMessage.getNextMessageId();
1510d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            bData.serviceCategoryProgramResults = results;
1520d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            byte[] encodedBearerData = BearerData.encode(bData);
1530d4bcdf379842af4b6304809156971e926f374f0Jake Hamby
1540d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            ByteArrayOutputStream baos = new ByteArrayOutputStream(100);
1550d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            DataOutputStream dos = new DataOutputStream(baos);
1560d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            try {
1570d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                dos.writeInt(SmsEnvelope.TELESERVICE_SCPT);
1580d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                dos.writeInt(0); //servicePresent
1590d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                dos.writeInt(0); //serviceCategory
1600d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                CdmaSmsAddress destAddr = CdmaSmsAddress.parse(
1610d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                        PhoneNumberUtils.cdmaCheckAndProcessPlusCode(sender));
1620d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                dos.write(destAddr.digitMode);
1630d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                dos.write(destAddr.numberMode);
1640d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                dos.write(destAddr.ton); // number_type
1650d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                dos.write(destAddr.numberPlan);
1660d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                dos.write(destAddr.numberOfDigits);
1670d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                dos.write(destAddr.origBytes, 0, destAddr.origBytes.length); // digits
1680d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                // Subaddress is not supported.
1690d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                dos.write(0); //subaddressType
1700d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                dos.write(0); //subaddr_odd
1710d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                dos.write(0); //subaddr_nbr_of_digits
1720d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                dos.write(encodedBearerData.length);
1730d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                dos.write(encodedBearerData, 0, encodedBearerData.length);
1740d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                // Ignore the RIL response. TODO: implement retry if SMS send fails.
1750d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                mCi.sendCdmaSms(baos.toByteArray(), null);
1760d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            } catch (IOException e) {
1770d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                loge("exception creating SCP results PDU", e);
1780d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            } finally {
1790d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                try {
1800d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                    dos.close();
1810d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                } catch (IOException ignored) {
1820d4bcdf379842af4b6304809156971e926f374f0Jake Hamby                }
1830d4bcdf379842af4b6304809156971e926f374f0Jake Hamby            }
1840d4bcdf379842af4b6304809156971e926f374f0Jake Hamby        }
1850d4bcdf379842af4b6304809156971e926f374f0Jake Hamby    };
1860d4bcdf379842af4b6304809156971e926f374f0Jake Hamby}
187