GsmInboundSmsHandler.java revision d2feaf918ab0c1173d4ada182532e48d0c0d3f77
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    /**
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