Home | History | Annotate | Download | only in gsm
      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