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