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