IccSmsInterfaceManager.java revision 0825495a331bb44df395a0cdb79fab85e68db5d5
1/*
2 * Copyright (C) 2008 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;
18
19import android.app.PendingIntent;
20import android.content.Context;
21import android.util.Log;
22
23import com.android.internal.util.HexDump;
24
25import java.util.ArrayList;
26import java.util.List;
27
28import static android.telephony.SmsManager.STATUS_ON_ICC_FREE;
29
30/**
31 * IccSmsInterfaceManager to provide an inter-process communication to
32 * access Sms in Icc.
33 */
34public abstract class IccSmsInterfaceManager extends ISms.Stub {
35    protected PhoneBase mPhone;
36    protected Context mContext;
37    protected SMSDispatcher mDispatcher;
38
39    protected IccSmsInterfaceManager(PhoneBase phone){
40        mPhone = phone;
41        mContext = phone.getContext();
42    }
43
44    protected void enforceReceiveAndSend(String message) {
45        mContext.enforceCallingPermission(
46                "android.permission.RECEIVE_SMS", message);
47        mContext.enforceCallingPermission(
48                "android.permission.SEND_SMS", message);
49    }
50
51    /**
52     * Send a data based SMS to a specific application port.
53     *
54     * @param destAddr the address to send the message to
55     * @param scAddr is the service center address or null to use
56     *  the current default SMSC
57     * @param destPort the port to deliver the message to
58     * @param data the body of the message to send
59     * @param sentIntent if not NULL this <code>PendingIntent</code> is
60     *  broadcast when the message is successfully sent, or failed.
61     *  The result code will be <code>Activity.RESULT_OK<code> for success,
62     *  or one of these errors:<br>
63     *  <code>RESULT_ERROR_GENERIC_FAILURE</code><br>
64     *  <code>RESULT_ERROR_RADIO_OFF</code><br>
65     *  <code>RESULT_ERROR_NULL_PDU</code><br>
66     *  For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include
67     *  the extra "errorCode" containing a radio technology specific value,
68     *  generally only useful for troubleshooting.<br>
69     *  The per-application based SMS control checks sentIntent. If sentIntent
70     *  is NULL the caller will be checked against all unknown applications,
71     *  which cause smaller number of SMS to be sent in checking period.
72     * @param deliveryIntent if not NULL this <code>PendingIntent</code> is
73     *  broadcast when the message is delivered to the recipient.  The
74     *  raw pdu of the status report is in the extended data ("pdu").
75     */
76    public void sendData(String destAddr, String scAddr, int destPort,
77            byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) {
78        mPhone.getContext().enforceCallingPermission(
79                "android.permission.SEND_SMS",
80                "Sending SMS message");
81        if (Log.isLoggable("SMS", Log.VERBOSE)) {
82            log("sendData: destAddr=" + destAddr + " scAddr=" + scAddr + " destPort=" +
83                destPort + " data='"+ HexDump.toHexString(data)  + "' sentIntent=" +
84                sentIntent + " deliveryIntent=" + deliveryIntent);
85        }
86        mDispatcher.sendData(destAddr, scAddr, destPort, data, sentIntent, deliveryIntent);
87    }
88
89    /**
90     * Send a text based SMS.
91     *
92     * @param destAddr the address to send the message to
93     * @param scAddr is the service center address or null to use
94     *  the current default SMSC
95     * @param text the body of the message to send
96     * @param sentIntent if not NULL this <code>PendingIntent</code> is
97     *  broadcast when the message is successfully sent, or failed.
98     *  The result code will be <code>Activity.RESULT_OK<code> for success,
99     *  or one of these errors:<br>
100     *  <code>RESULT_ERROR_GENERIC_FAILURE</code><br>
101     *  <code>RESULT_ERROR_RADIO_OFF</code><br>
102     *  <code>RESULT_ERROR_NULL_PDU</code><br>
103     *  For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include
104     *  the extra "errorCode" containing a radio technology specific value,
105     *  generally only useful for troubleshooting.<br>
106     *  The per-application based SMS control checks sentIntent. If sentIntent
107     *  is NULL the caller will be checked against all unknown applications,
108     *  which cause smaller number of SMS to be sent in checking period.
109     * @param deliveryIntent if not NULL this <code>PendingIntent</code> is
110     *  broadcast when the message is delivered to the recipient.  The
111     *  raw pdu of the status report is in the extended data ("pdu").
112     */
113    public void sendText(String destAddr, String scAddr,
114            String text, PendingIntent sentIntent, PendingIntent deliveryIntent) {
115        mPhone.getContext().enforceCallingPermission(
116                "android.permission.SEND_SMS",
117                "Sending SMS message");
118        if (Log.isLoggable("SMS", Log.VERBOSE)) {
119            log("sendText: destAddr=" + destAddr + " scAddr=" + scAddr +
120                " text='"+ text + "' sentIntent=" +
121                sentIntent + " deliveryIntent=" + deliveryIntent);
122        }
123        mDispatcher.sendText(destAddr, scAddr, text, sentIntent, deliveryIntent);
124    }
125
126    /**
127     * Send a multi-part text based SMS.
128     *
129     * @param destAddr the address to send the message to
130     * @param scAddr is the service center address or null to use
131     *   the current default SMSC
132     * @param parts an <code>ArrayList</code> of strings that, in order,
133     *   comprise the original message
134     * @param sentIntents if not null, an <code>ArrayList</code> of
135     *   <code>PendingIntent</code>s (one for each message part) that is
136     *   broadcast when the corresponding message part has been sent.
137     *   The result code will be <code>Activity.RESULT_OK<code> for success,
138     *   or one of these errors:
139     *   <code>RESULT_ERROR_GENERIC_FAILURE</code>
140     *   <code>RESULT_ERROR_RADIO_OFF</code>
141     *   <code>RESULT_ERROR_NULL_PDU</code>.
142     *  The per-application based SMS control checks sentIntent. If sentIntent
143     *  is NULL the caller will be checked against all unknown applications,
144     *  which cause smaller number of SMS to be sent in checking period.
145     * @param deliveryIntents if not null, an <code>ArrayList</code> of
146     *   <code>PendingIntent</code>s (one for each message part) that is
147     *   broadcast when the corresponding message part has been delivered
148     *   to the recipient.  The raw pdu of the status report is in the
149     *   extended data ("pdu").
150     */
151    public void sendMultipartText(String destAddr, String scAddr, List<String> parts,
152            List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents) {
153        mPhone.getContext().enforceCallingPermission(
154                "android.permission.SEND_SMS",
155                "Sending SMS message");
156        if (Log.isLoggable("SMS", Log.VERBOSE)) {
157            int i = 0;
158            for (String part : parts) {
159                log("sendMultipartText: destAddr=" + destAddr + ", srAddr=" + scAddr +
160                        ", part[" + (i++) + "]=" + part);
161            }
162        }
163        mDispatcher.sendMultipartText(destAddr, scAddr, (ArrayList<String>) parts,
164                (ArrayList<PendingIntent>) sentIntents, (ArrayList<PendingIntent>) deliveryIntents);
165    }
166
167    /**
168     * create SmsRawData lists from all sms record byte[]
169     * Use null to indicate "free" record
170     *
171     * @param messages List of message records from EF_SMS.
172     * @return SmsRawData list of all in-used records
173     */
174    protected ArrayList<SmsRawData> buildValidRawData(ArrayList<byte[]> messages) {
175        int count = messages.size();
176        ArrayList<SmsRawData> ret;
177
178        ret = new ArrayList<SmsRawData>(count);
179
180        for (int i = 0; i < count; i++) {
181            byte[] ba = messages.get(i);
182            if (ba[0] == STATUS_ON_ICC_FREE) {
183                ret.add(null);
184            } else {
185                ret.add(new SmsRawData(messages.get(i)));
186            }
187        }
188
189        return ret;
190    }
191
192    /**
193     * Generates an EF_SMS record from status and raw PDU.
194     *
195     * @param status Message status.  See TS 51.011 10.5.3.
196     * @param pdu Raw message PDU.
197     * @return byte array for the record.
198     */
199    protected byte[] makeSmsRecordData(int status, byte[] pdu) {
200        byte[] data = new byte[IccConstants.SMS_RECORD_LENGTH];
201
202        // Status bits for this record.  See TS 51.011 10.5.3
203        data[0] = (byte)(status & 7);
204
205        System.arraycopy(pdu, 0, data, 1, pdu.length);
206
207        // Pad out with 0xFF's.
208        for (int j = pdu.length+1; j < IccConstants.SMS_RECORD_LENGTH; j++) {
209            data[j] = -1;
210        }
211
212        return data;
213    }
214
215    protected abstract void log(String msg);
216
217}
218