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; 29a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.telephony.SubscriptionManager; 300d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport android.telephony.cdma.CdmaSmsCbProgramData; 310d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport android.telephony.cdma.CdmaSmsCbProgramResults; 320d4bcdf379842af4b6304809156971e926f374f0Jake Hamby 330d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport com.android.internal.telephony.CommandsInterface; 34a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.PhoneConstants; 350d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport com.android.internal.telephony.WakeLockStateMachine; 360d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport com.android.internal.telephony.cdma.sms.BearerData; 370d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport com.android.internal.telephony.cdma.sms.CdmaSmsAddress; 380d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport com.android.internal.telephony.cdma.sms.SmsEnvelope; 390d4bcdf379842af4b6304809156971e926f374f0Jake Hamby 400d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport java.io.ByteArrayOutputStream; 410d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport java.io.DataOutputStream; 420d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport java.io.IOException; 430d4bcdf379842af4b6304809156971e926f374f0Jake Hambyimport java.util.ArrayList; 440d4bcdf379842af4b6304809156971e926f374f0Jake Hamby 450d4bcdf379842af4b6304809156971e926f374f0Jake Hamby/** 460d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * Handle CDMA Service Category Program Data requests and responses. 470d4bcdf379842af4b6304809156971e926f374f0Jake Hamby */ 480d4bcdf379842af4b6304809156971e926f374f0Jake Hambypublic final class CdmaServiceCategoryProgramHandler extends WakeLockStateMachine { 490d4bcdf379842af4b6304809156971e926f374f0Jake Hamby 500d4bcdf379842af4b6304809156971e926f374f0Jake Hamby final CommandsInterface mCi; 510d4bcdf379842af4b6304809156971e926f374f0Jake Hamby 520d4bcdf379842af4b6304809156971e926f374f0Jake Hamby /** 530d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * Create a new CDMA inbound SMS handler. 540d4bcdf379842af4b6304809156971e926f374f0Jake Hamby */ 550d4bcdf379842af4b6304809156971e926f374f0Jake Hamby CdmaServiceCategoryProgramHandler(Context context, CommandsInterface commandsInterface) { 56d2feaf918ab0c1173d4ada182532e48d0c0d3f77Wink Saville super("CdmaServiceCategoryProgramHandler", context, null); 570d4bcdf379842af4b6304809156971e926f374f0Jake Hamby mContext = context; 580d4bcdf379842af4b6304809156971e926f374f0Jake Hamby mCi = commandsInterface; 590d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } 600d4bcdf379842af4b6304809156971e926f374f0Jake Hamby 610d4bcdf379842af4b6304809156971e926f374f0Jake Hamby /** 620d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * Create a new State machine for SCPD requests. 630d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * @param context the context to use 640d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * @param commandsInterface the radio commands interface 650d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * @return the new SCPD handler 660d4bcdf379842af4b6304809156971e926f374f0Jake Hamby */ 670d4bcdf379842af4b6304809156971e926f374f0Jake Hamby static CdmaServiceCategoryProgramHandler makeScpHandler(Context context, 680d4bcdf379842af4b6304809156971e926f374f0Jake Hamby CommandsInterface commandsInterface) { 690d4bcdf379842af4b6304809156971e926f374f0Jake Hamby CdmaServiceCategoryProgramHandler handler = new CdmaServiceCategoryProgramHandler( 700d4bcdf379842af4b6304809156971e926f374f0Jake Hamby context, commandsInterface); 710d4bcdf379842af4b6304809156971e926f374f0Jake Hamby handler.start(); 720d4bcdf379842af4b6304809156971e926f374f0Jake Hamby return handler; 730d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } 740d4bcdf379842af4b6304809156971e926f374f0Jake Hamby 750d4bcdf379842af4b6304809156971e926f374f0Jake Hamby /** 760d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * Handle Cell Broadcast messages from {@code CdmaInboundSmsHandler}. 770d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * 3GPP-format Cell Broadcast messages sent from radio are handled in the subclass. 780d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * 790d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * @param message the message to process 800d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * @return true if an ordered broadcast was sent; false on failure 810d4bcdf379842af4b6304809156971e926f374f0Jake Hamby */ 820d4bcdf379842af4b6304809156971e926f374f0Jake Hamby @Override 830d4bcdf379842af4b6304809156971e926f374f0Jake Hamby protected boolean handleSmsMessage(Message message) { 840d4bcdf379842af4b6304809156971e926f374f0Jake Hamby if (message.obj instanceof SmsMessage) { 850d4bcdf379842af4b6304809156971e926f374f0Jake Hamby return handleServiceCategoryProgramData((SmsMessage) message.obj); 860d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } else { 870d4bcdf379842af4b6304809156971e926f374f0Jake Hamby loge("handleMessage got object of type: " + message.obj.getClass().getName()); 880d4bcdf379842af4b6304809156971e926f374f0Jake Hamby return false; 890d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } 900d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } 910d4bcdf379842af4b6304809156971e926f374f0Jake Hamby 920d4bcdf379842af4b6304809156971e926f374f0Jake Hamby 930d4bcdf379842af4b6304809156971e926f374f0Jake Hamby /** 940d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * Send SCPD request to CellBroadcastReceiver as an ordered broadcast. 950d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * @param sms the CDMA SmsMessage containing the SCPD request 960d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * @return true if an ordered broadcast was sent; false on failure 970d4bcdf379842af4b6304809156971e926f374f0Jake Hamby */ 980d4bcdf379842af4b6304809156971e926f374f0Jake Hamby private boolean handleServiceCategoryProgramData(SmsMessage sms) { 990d4bcdf379842af4b6304809156971e926f374f0Jake Hamby ArrayList<CdmaSmsCbProgramData> programDataList = sms.getSmsCbProgramData(); 1000d4bcdf379842af4b6304809156971e926f374f0Jake Hamby if (programDataList == null) { 1010d4bcdf379842af4b6304809156971e926f374f0Jake Hamby loge("handleServiceCategoryProgramData: program data list is null!"); 1020d4bcdf379842af4b6304809156971e926f374f0Jake Hamby return false; 1030d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } 1040d4bcdf379842af4b6304809156971e926f374f0Jake Hamby 1050d4bcdf379842af4b6304809156971e926f374f0Jake Hamby Intent intent = new Intent(Intents.SMS_SERVICE_CATEGORY_PROGRAM_DATA_RECEIVED_ACTION); 1060d4bcdf379842af4b6304809156971e926f374f0Jake Hamby intent.putExtra("sender", sms.getOriginatingAddress()); 1070d4bcdf379842af4b6304809156971e926f374f0Jake Hamby intent.putParcelableArrayListExtra("program_data", programDataList); 108a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville SubscriptionManager.putPhoneIdAndSubIdExtra(intent, mPhone.getPhoneId()); 1090d4bcdf379842af4b6304809156971e926f374f0Jake Hamby mContext.sendOrderedBroadcast(intent, Manifest.permission.RECEIVE_SMS, 1100d4bcdf379842af4b6304809156971e926f374f0Jake Hamby AppOpsManager.OP_RECEIVE_SMS, mScpResultsReceiver, 1110d4bcdf379842af4b6304809156971e926f374f0Jake Hamby getHandler(), Activity.RESULT_OK, null, null); 1120d4bcdf379842af4b6304809156971e926f374f0Jake Hamby return true; 1130d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } 1140d4bcdf379842af4b6304809156971e926f374f0Jake Hamby 1150d4bcdf379842af4b6304809156971e926f374f0Jake Hamby /** 1160d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * Broadcast receiver to handle results of ordered broadcast. Sends the SCPD results 1170d4bcdf379842af4b6304809156971e926f374f0Jake Hamby * as a reply SMS, then sends a message to state machine to transition to idle. 1180d4bcdf379842af4b6304809156971e926f374f0Jake Hamby */ 1190d4bcdf379842af4b6304809156971e926f374f0Jake Hamby private final BroadcastReceiver mScpResultsReceiver = new BroadcastReceiver() { 1200d4bcdf379842af4b6304809156971e926f374f0Jake Hamby @Override 1210d4bcdf379842af4b6304809156971e926f374f0Jake Hamby public void onReceive(Context context, Intent intent) { 1220d4bcdf379842af4b6304809156971e926f374f0Jake Hamby sendScpResults(); 1230d4bcdf379842af4b6304809156971e926f374f0Jake Hamby if (DBG) log("mScpResultsReceiver finished"); 1240d4bcdf379842af4b6304809156971e926f374f0Jake Hamby sendMessage(EVENT_BROADCAST_COMPLETE); 1250d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } 1260d4bcdf379842af4b6304809156971e926f374f0Jake Hamby 1270d4bcdf379842af4b6304809156971e926f374f0Jake Hamby private void sendScpResults() { 1280d4bcdf379842af4b6304809156971e926f374f0Jake Hamby int resultCode = getResultCode(); 1290d4bcdf379842af4b6304809156971e926f374f0Jake Hamby if ((resultCode != Activity.RESULT_OK) && (resultCode != Intents.RESULT_SMS_HANDLED)) { 1300d4bcdf379842af4b6304809156971e926f374f0Jake Hamby loge("SCP results error: result code = " + resultCode); 1310d4bcdf379842af4b6304809156971e926f374f0Jake Hamby return; 1320d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } 1330d4bcdf379842af4b6304809156971e926f374f0Jake Hamby Bundle extras = getResultExtras(false); 1340d4bcdf379842af4b6304809156971e926f374f0Jake Hamby if (extras == null) { 1350d4bcdf379842af4b6304809156971e926f374f0Jake Hamby loge("SCP results error: missing extras"); 1360d4bcdf379842af4b6304809156971e926f374f0Jake Hamby return; 1370d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } 1380d4bcdf379842af4b6304809156971e926f374f0Jake Hamby String sender = extras.getString("sender"); 1390d4bcdf379842af4b6304809156971e926f374f0Jake Hamby if (sender == null) { 1400d4bcdf379842af4b6304809156971e926f374f0Jake Hamby loge("SCP results error: missing sender extra."); 1410d4bcdf379842af4b6304809156971e926f374f0Jake Hamby return; 1420d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } 1430d4bcdf379842af4b6304809156971e926f374f0Jake Hamby ArrayList<CdmaSmsCbProgramResults> results 1440d4bcdf379842af4b6304809156971e926f374f0Jake Hamby = extras.getParcelableArrayList("results"); 1450d4bcdf379842af4b6304809156971e926f374f0Jake Hamby if (results == null) { 1460d4bcdf379842af4b6304809156971e926f374f0Jake Hamby loge("SCP results error: missing results extra."); 1470d4bcdf379842af4b6304809156971e926f374f0Jake Hamby return; 1480d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } 1490d4bcdf379842af4b6304809156971e926f374f0Jake Hamby 1500d4bcdf379842af4b6304809156971e926f374f0Jake Hamby BearerData bData = new BearerData(); 1510d4bcdf379842af4b6304809156971e926f374f0Jake Hamby bData.messageType = BearerData.MESSAGE_TYPE_SUBMIT; 1520d4bcdf379842af4b6304809156971e926f374f0Jake Hamby bData.messageId = SmsMessage.getNextMessageId(); 1530d4bcdf379842af4b6304809156971e926f374f0Jake Hamby bData.serviceCategoryProgramResults = results; 1540d4bcdf379842af4b6304809156971e926f374f0Jake Hamby byte[] encodedBearerData = BearerData.encode(bData); 1550d4bcdf379842af4b6304809156971e926f374f0Jake Hamby 1560d4bcdf379842af4b6304809156971e926f374f0Jake Hamby ByteArrayOutputStream baos = new ByteArrayOutputStream(100); 1570d4bcdf379842af4b6304809156971e926f374f0Jake Hamby DataOutputStream dos = new DataOutputStream(baos); 1580d4bcdf379842af4b6304809156971e926f374f0Jake Hamby try { 1590d4bcdf379842af4b6304809156971e926f374f0Jake Hamby dos.writeInt(SmsEnvelope.TELESERVICE_SCPT); 1600d4bcdf379842af4b6304809156971e926f374f0Jake Hamby dos.writeInt(0); //servicePresent 1610d4bcdf379842af4b6304809156971e926f374f0Jake Hamby dos.writeInt(0); //serviceCategory 1620d4bcdf379842af4b6304809156971e926f374f0Jake Hamby CdmaSmsAddress destAddr = CdmaSmsAddress.parse( 1638409d93cf9f3ed23db12f24b4f49063ea416b30bJake Hamby PhoneNumberUtils.cdmaCheckAndProcessPlusCodeForSms(sender)); 1640d4bcdf379842af4b6304809156971e926f374f0Jake Hamby dos.write(destAddr.digitMode); 1650d4bcdf379842af4b6304809156971e926f374f0Jake Hamby dos.write(destAddr.numberMode); 1660d4bcdf379842af4b6304809156971e926f374f0Jake Hamby dos.write(destAddr.ton); // number_type 1670d4bcdf379842af4b6304809156971e926f374f0Jake Hamby dos.write(destAddr.numberPlan); 1680d4bcdf379842af4b6304809156971e926f374f0Jake Hamby dos.write(destAddr.numberOfDigits); 1690d4bcdf379842af4b6304809156971e926f374f0Jake Hamby dos.write(destAddr.origBytes, 0, destAddr.origBytes.length); // digits 1700d4bcdf379842af4b6304809156971e926f374f0Jake Hamby // Subaddress is not supported. 1710d4bcdf379842af4b6304809156971e926f374f0Jake Hamby dos.write(0); //subaddressType 1720d4bcdf379842af4b6304809156971e926f374f0Jake Hamby dos.write(0); //subaddr_odd 1730d4bcdf379842af4b6304809156971e926f374f0Jake Hamby dos.write(0); //subaddr_nbr_of_digits 1740d4bcdf379842af4b6304809156971e926f374f0Jake Hamby dos.write(encodedBearerData.length); 1750d4bcdf379842af4b6304809156971e926f374f0Jake Hamby dos.write(encodedBearerData, 0, encodedBearerData.length); 1760d4bcdf379842af4b6304809156971e926f374f0Jake Hamby // Ignore the RIL response. TODO: implement retry if SMS send fails. 1770d4bcdf379842af4b6304809156971e926f374f0Jake Hamby mCi.sendCdmaSms(baos.toByteArray(), null); 1780d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } catch (IOException e) { 1790d4bcdf379842af4b6304809156971e926f374f0Jake Hamby loge("exception creating SCP results PDU", e); 1800d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } finally { 1810d4bcdf379842af4b6304809156971e926f374f0Jake Hamby try { 1820d4bcdf379842af4b6304809156971e926f374f0Jake Hamby dos.close(); 1830d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } catch (IOException ignored) { 1840d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } 1850d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } 1860d4bcdf379842af4b6304809156971e926f374f0Jake Hamby } 1870d4bcdf379842af4b6304809156971e926f374f0Jake Hamby }; 1880d4bcdf379842af4b6304809156971e926f374f0Jake Hamby} 189