1 /* 2 * Copyright (C) 2013 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.internal.telephony.gsm; 18 19 import android.app.Activity; 20 import android.content.Context; 21 import android.os.Message; 22 import android.provider.Telephony.Sms.Intents; 23 24 import com.android.internal.telephony.CommandsInterface; 25 import com.android.internal.telephony.InboundSmsHandler; 26 import com.android.internal.telephony.PhoneBase; 27 import com.android.internal.telephony.SmsConstants; 28 import com.android.internal.telephony.SmsMessageBase; 29 import com.android.internal.telephony.SmsStorageMonitor; 30 import com.android.internal.telephony.uicc.UsimServiceTable; 31 32 /** 33 * This class broadcasts incoming SMS messages to interested apps after storing them in 34 * the SmsProvider "raw" table and ACKing them to the SMSC. After each message has been 35 */ 36 public class GsmInboundSmsHandler extends InboundSmsHandler { 37 38 /** Handler for SMS-PP data download messages to UICC. */ 39 private final UsimDataDownloadHandler mDataDownloadHandler; 40 41 /** 42 * Create a new GSM inbound SMS handler. 43 */ 44 private GsmInboundSmsHandler(Context context, SmsStorageMonitor storageMonitor, 45 PhoneBase phone) { 46 super("GsmInboundSmsHandler", context, storageMonitor, phone, 47 GsmCellBroadcastHandler.makeGsmCellBroadcastHandler(context, phone)); 48 phone.mCi.setOnNewGsmSms(getHandler(), EVENT_NEW_SMS, null); 49 mDataDownloadHandler = new UsimDataDownloadHandler(phone.mCi); 50 } 51 52 /** 53 * Unregister for GSM SMS. 54 */ 55 @Override 56 protected void onQuitting() { 57 mPhone.mCi.unSetOnNewGsmSms(getHandler()); 58 mCellBroadcastHandler.dispose(); 59 60 if (DBG) log("unregistered for 3GPP SMS"); 61 super.onQuitting(); // release wakelock 62 } 63 64 /** 65 * Wait for state machine to enter startup state. We can't send any messages until then. 66 */ 67 public static GsmInboundSmsHandler makeInboundSmsHandler(Context context, 68 SmsStorageMonitor storageMonitor, PhoneBase phone) { 69 GsmInboundSmsHandler handler = new GsmInboundSmsHandler(context, storageMonitor, phone); 70 handler.start(); 71 return handler; 72 } 73 74 /** 75 * Return true if this handler is for 3GPP2 messages; false for 3GPP format. 76 * @return false (3GPP) 77 */ 78 @Override 79 protected boolean is3gpp2() { 80 return false; 81 } 82 83 /** 84 * Handle type zero, SMS-PP data download, and 3GPP/CPHS MWI type SMS. Normal SMS messages 85 * are handled by {@link #dispatchNormalMessage} in parent class. 86 * 87 * @param smsb the SmsMessageBase object from the RIL 88 * @return a result code from {@link android.provider.Telephony.Sms.Intents}, 89 * or {@link Activity#RESULT_OK} for delayed acknowledgment to SMSC 90 */ 91 @Override 92 protected int dispatchMessageRadioSpecific(SmsMessageBase smsb) { 93 SmsMessage sms = (SmsMessage) smsb; 94 95 if (sms.isTypeZero()) { 96 // As per 3GPP TS 23.040 9.2.3.9, Type Zero messages should not be 97 // Displayed/Stored/Notified. They should only be acknowledged. 98 log("Received short message type 0, Don't display or store it. Send Ack"); 99 return Intents.RESULT_SMS_HANDLED; 100 } 101 102 // Send SMS-PP data download messages to UICC. See 3GPP TS 31.111 section 7.1.1. 103 if (sms.isUsimDataDownload()) { 104 UsimServiceTable ust = mPhone.getUsimServiceTable(); 105 return mDataDownloadHandler.handleUsimDataDownload(ust, sms); 106 } 107 108 boolean handled = false; 109 if (sms.isMWISetMessage()) { 110 mPhone.setVoiceMessageWaiting(1, -1); // line 1: unknown number of msgs waiting 111 handled = sms.isMwiDontStore(); 112 if (DBG) log("Received voice mail indicator set SMS shouldStore=" + !handled); 113 } else if (sms.isMWIClearMessage()) { 114 mPhone.setVoiceMessageWaiting(1, 0); // line 1: no msgs waiting 115 handled = sms.isMwiDontStore(); 116 if (DBG) log("Received voice mail indicator clear SMS shouldStore=" + !handled); 117 } 118 if (handled) { 119 return Intents.RESULT_SMS_HANDLED; 120 } 121 122 if (!mStorageMonitor.isStorageAvailable() && 123 sms.getMessageClass() != SmsConstants.MessageClass.CLASS_0) { 124 // It's a storable message and there's no storage available. Bail. 125 // (See TS 23.038 for a description of class 0 messages.) 126 return Intents.RESULT_SMS_OUT_OF_MEMORY; 127 } 128 129 return dispatchNormalMessage(smsb); 130 } 131 132 /** 133 * Send an acknowledge message. 134 * @param success indicates that last message was successfully received. 135 * @param result result code indicating any error 136 * @param response callback message sent when operation completes. 137 */ 138 @Override 139 protected void acknowledgeLastIncomingSms(boolean success, int result, Message response) { 140 mPhone.mCi.acknowledgeLastIncomingGsmSms(success, resultToCause(result), response); 141 } 142 143 /** 144 * Called when the phone changes the default method updates mPhone 145 * mStorageMonitor and mCellBroadcastHandler.updatePhoneObject. 146 * Override if different or other behavior is desired. 147 * 148 * @param phone 149 */ 150 @Override 151 protected void onUpdatePhoneObject(PhoneBase phone) { 152 super.onUpdatePhoneObject(phone); 153 log("onUpdatePhoneObject: dispose of old CellBroadcastHandler and make a new one"); 154 mCellBroadcastHandler.dispose(); 155 mCellBroadcastHandler = GsmCellBroadcastHandler 156 .makeGsmCellBroadcastHandler(mContext, phone); 157 } 158 159 /** 160 * Convert Android result code to 3GPP SMS failure cause. 161 * @param rc the Android SMS intent result value 162 * @return 0 for success, or a 3GPP SMS failure cause value 163 */ 164 private static int resultToCause(int rc) { 165 switch (rc) { 166 case Activity.RESULT_OK: 167 case Intents.RESULT_SMS_HANDLED: 168 // Cause code is ignored on success. 169 return 0; 170 case Intents.RESULT_SMS_OUT_OF_MEMORY: 171 return CommandsInterface.GSM_SMS_FAIL_CAUSE_MEMORY_CAPACITY_EXCEEDED; 172 case Intents.RESULT_SMS_GENERIC_ERROR: 173 default: 174 return CommandsInterface.GSM_SMS_FAIL_CAUSE_UNSPECIFIED_ERROR; 175 } 176 } 177 } 178