1767a662ecde33c3979bf02b793d392aca0403162Wink Saville/*
2767a662ecde33c3979bf02b793d392aca0403162Wink Saville * Copyright (C) 2008 The Android Open Source Project
3767a662ecde33c3979bf02b793d392aca0403162Wink Saville *
4767a662ecde33c3979bf02b793d392aca0403162Wink Saville * Licensed under the Apache License, Version 2.0 (the "License");
5767a662ecde33c3979bf02b793d392aca0403162Wink Saville * you may not use this file except in compliance with the License.
6767a662ecde33c3979bf02b793d392aca0403162Wink Saville * You may obtain a copy of the License at
7767a662ecde33c3979bf02b793d392aca0403162Wink Saville *
8767a662ecde33c3979bf02b793d392aca0403162Wink Saville *      http://www.apache.org/licenses/LICENSE-2.0
9767a662ecde33c3979bf02b793d392aca0403162Wink Saville *
10767a662ecde33c3979bf02b793d392aca0403162Wink Saville * Unless required by applicable law or agreed to in writing, software
11767a662ecde33c3979bf02b793d392aca0403162Wink Saville * distributed under the License is distributed on an "AS IS" BASIS,
12767a662ecde33c3979bf02b793d392aca0403162Wink Saville * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13767a662ecde33c3979bf02b793d392aca0403162Wink Saville * See the License for the specific language governing permissions and
14767a662ecde33c3979bf02b793d392aca0403162Wink Saville * limitations under the License.
15767a662ecde33c3979bf02b793d392aca0403162Wink Saville */
16767a662ecde33c3979bf02b793d392aca0403162Wink Saville
17767a662ecde33c3979bf02b793d392aca0403162Wink Savillepackage android.telephony;
18767a662ecde33c3979bf02b793d392aca0403162Wink Saville
19767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport android.app.PendingIntent;
20767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport android.os.RemoteException;
21767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport android.os.ServiceManager;
22767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport android.text.TextUtils;
23767a662ecde33c3979bf02b793d392aca0403162Wink Saville
24767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport com.android.internal.telephony.EncodeException;
25767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport com.android.internal.telephony.ISms;
26767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport com.android.internal.telephony.IccConstants;
27767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport com.android.internal.telephony.SmsRawData;
28767a662ecde33c3979bf02b793d392aca0403162Wink Saville
29767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport java.util.ArrayList;
30767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport java.util.Arrays;
31767a662ecde33c3979bf02b793d392aca0403162Wink Savilleimport java.util.List;
32767a662ecde33c3979bf02b793d392aca0403162Wink Saville
33fc78f358cb1d1cee99758bcd6ef998a122ef27c9Tammo Spalink/*
34fc78f358cb1d1cee99758bcd6ef998a122ef27c9Tammo Spalink * TODO(code review): Curious question... Why are a lot of these
35fc78f358cb1d1cee99758bcd6ef998a122ef27c9Tammo Spalink * methods not declared as static, since they do not seem to require
36fc78f358cb1d1cee99758bcd6ef998a122ef27c9Tammo Spalink * any local object state?  Assumedly this cannot be changed without
37fc78f358cb1d1cee99758bcd6ef998a122ef27c9Tammo Spalink * interfering with the API...
38fc78f358cb1d1cee99758bcd6ef998a122ef27c9Tammo Spalink */
39767a662ecde33c3979bf02b793d392aca0403162Wink Saville
40767a662ecde33c3979bf02b793d392aca0403162Wink Saville/**
41767a662ecde33c3979bf02b793d392aca0403162Wink Saville * Manages SMS operations such as sending data, text, and pdu SMS messages.
42767a662ecde33c3979bf02b793d392aca0403162Wink Saville * Get this object by calling the static method SmsManager.getDefault().
43767a662ecde33c3979bf02b793d392aca0403162Wink Saville */
44767a662ecde33c3979bf02b793d392aca0403162Wink Savillepublic final class SmsManager {
45767a662ecde33c3979bf02b793d392aca0403162Wink Saville    private static SmsManager sInstance;
46767a662ecde33c3979bf02b793d392aca0403162Wink Saville
47767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /**
48767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * Send a text based SMS.
49767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *
50767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * @param destinationAddress the address to send the message to
51767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * @param scAddress is the service center address or null to use
52767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *  the current default SMSC
53767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * @param text the body of the message to send
54767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * @param sentIntent if not NULL this <code>PendingIntent</code> is
55767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *  broadcast when the message is sucessfully sent, or failed.
56767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *  The result code will be <code>Activity.RESULT_OK<code> for success,
57d1cb1d22af0775a7c030822e04db1c9ecad9beabjsh     *  or one of these errors:<br>
58d1cb1d22af0775a7c030822e04db1c9ecad9beabjsh     *  <code>RESULT_ERROR_GENERIC_FAILURE</code><br>
59d1cb1d22af0775a7c030822e04db1c9ecad9beabjsh     *  <code>RESULT_ERROR_RADIO_OFF</code><br>
60d1cb1d22af0775a7c030822e04db1c9ecad9beabjsh     *  <code>RESULT_ERROR_NULL_PDU</code><br>
61d1cb1d22af0775a7c030822e04db1c9ecad9beabjsh     *  For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include
62d1cb1d22af0775a7c030822e04db1c9ecad9beabjsh     *  the extra "errorCode" containing a radio technology specific value,
63d1cb1d22af0775a7c030822e04db1c9ecad9beabjsh     *  generally only useful for troubleshooting.<br>
64767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *  The per-application based SMS control checks sentIntent. If sentIntent
65767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *  is NULL the caller will be checked against all unknown applications,
66767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *  which cause smaller number of SMS to be sent in checking period.
67767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * @param deliveryIntent if not NULL this <code>PendingIntent</code> is
68767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *  broadcast when the message is delivered to the recipient.  The
69767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *  raw pdu of the status report is in the extended data ("pdu").
70767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *
71767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * @throws IllegalArgumentException if destinationAddress or text are empty
72767a662ecde33c3979bf02b793d392aca0403162Wink Saville     */
73767a662ecde33c3979bf02b793d392aca0403162Wink Saville    public void sendTextMessage(
74767a662ecde33c3979bf02b793d392aca0403162Wink Saville            String destinationAddress, String scAddress, String text,
75767a662ecde33c3979bf02b793d392aca0403162Wink Saville            PendingIntent sentIntent, PendingIntent deliveryIntent) {
76767a662ecde33c3979bf02b793d392aca0403162Wink Saville        if (TextUtils.isEmpty(destinationAddress)) {
77767a662ecde33c3979bf02b793d392aca0403162Wink Saville            throw new IllegalArgumentException("Invalid destinationAddress");
78767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
79767a662ecde33c3979bf02b793d392aca0403162Wink Saville
80767a662ecde33c3979bf02b793d392aca0403162Wink Saville        if (TextUtils.isEmpty(text)) {
81767a662ecde33c3979bf02b793d392aca0403162Wink Saville            throw new IllegalArgumentException("Invalid message body");
82767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
83767a662ecde33c3979bf02b793d392aca0403162Wink Saville
841f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink        try {
851f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink            ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
861f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink            if (iccISms != null) {
871f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink                iccISms.sendText(destinationAddress, scAddress, text, sentIntent, deliveryIntent);
881f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink            }
891f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink        } catch (RemoteException ex) {
901f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink            // ignore it
911f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink        }
92767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
93767a662ecde33c3979bf02b793d392aca0403162Wink Saville
94767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /**
95fc78f358cb1d1cee99758bcd6ef998a122ef27c9Tammo Spalink     * Divide a message text into several fragments, none bigger than
96767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * the maximum SMS message size.
97767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *
98767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * @param text the original message.  Must not be null.
99767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * @return an <code>ArrayList</code> of strings that, in order,
100767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *   comprise the original message
101767a662ecde33c3979bf02b793d392aca0403162Wink Saville     */
102767a662ecde33c3979bf02b793d392aca0403162Wink Saville    public ArrayList<String> divideMessage(String text) {
103fc78f358cb1d1cee99758bcd6ef998a122ef27c9Tammo Spalink        return SmsMessage.fragmentText(text);
104767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
105767a662ecde33c3979bf02b793d392aca0403162Wink Saville
106767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /**
107767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * Send a multi-part text based SMS.  The callee should have already
108767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * divided the message into correctly sized parts by calling
109767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * <code>divideMessage</code>.
110767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *
111767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * @param destinationAddress the address to send the message to
112767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * @param scAddress is the service center address or null to use
113767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *   the current default SMSC
114767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * @param parts an <code>ArrayList</code> of strings that, in order,
115767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *   comprise the original message
116767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * @param sentIntents if not null, an <code>ArrayList</code> of
117767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *   <code>PendingIntent</code>s (one for each message part) that is
118767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *   broadcast when the corresponding message part has been sent.
119767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *   The result code will be <code>Activity.RESULT_OK<code> for success,
120d1cb1d22af0775a7c030822e04db1c9ecad9beabjsh     *   or one of these errors:<br>
121d1cb1d22af0775a7c030822e04db1c9ecad9beabjsh     *   <code>RESULT_ERROR_GENERIC_FAILURE</code><br>
122d1cb1d22af0775a7c030822e04db1c9ecad9beabjsh     *   <code>RESULT_ERROR_RADIO_OFF</code><br>
123d1cb1d22af0775a7c030822e04db1c9ecad9beabjsh     *   <code>RESULT_ERROR_NULL_PDU</code><br>
124d1cb1d22af0775a7c030822e04db1c9ecad9beabjsh     *   For <code>RESULT_ERROR_GENERIC_FAILURE</code> each sentIntent may include
125d1cb1d22af0775a7c030822e04db1c9ecad9beabjsh     *   the extra "errorCode" containing a radio technology specific value,
126d1cb1d22af0775a7c030822e04db1c9ecad9beabjsh     *   generally only useful for troubleshooting.<br>
127767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *   The per-application based SMS control checks sentIntent. If sentIntent
128767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *   is NULL the caller will be checked against all unknown applicaitons,
129767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *   which cause smaller number of SMS to be sent in checking period.
130767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * @param deliveryIntents if not null, an <code>ArrayList</code> of
131767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *   <code>PendingIntent</code>s (one for each message part) that is
132767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *   broadcast when the corresponding message part has been delivered
133767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *   to the recipient.  The raw pdu of the status report is in the
134767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *   extended data ("pdu").
135767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *
136767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * @throws IllegalArgumentException if destinationAddress or data are empty
137767a662ecde33c3979bf02b793d392aca0403162Wink Saville     */
138767a662ecde33c3979bf02b793d392aca0403162Wink Saville    public void sendMultipartTextMessage(
139767a662ecde33c3979bf02b793d392aca0403162Wink Saville            String destinationAddress, String scAddress, ArrayList<String> parts,
140767a662ecde33c3979bf02b793d392aca0403162Wink Saville            ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents) {
141767a662ecde33c3979bf02b793d392aca0403162Wink Saville        if (TextUtils.isEmpty(destinationAddress)) {
142767a662ecde33c3979bf02b793d392aca0403162Wink Saville            throw new IllegalArgumentException("Invalid destinationAddress");
143767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
144767a662ecde33c3979bf02b793d392aca0403162Wink Saville        if (parts == null || parts.size() < 1) {
145767a662ecde33c3979bf02b793d392aca0403162Wink Saville            throw new IllegalArgumentException("Invalid message body");
146767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
147767a662ecde33c3979bf02b793d392aca0403162Wink Saville
148767a662ecde33c3979bf02b793d392aca0403162Wink Saville        if (parts.size() > 1) {
149767a662ecde33c3979bf02b793d392aca0403162Wink Saville            try {
150767a662ecde33c3979bf02b793d392aca0403162Wink Saville                ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
151767a662ecde33c3979bf02b793d392aca0403162Wink Saville                if (iccISms != null) {
152767a662ecde33c3979bf02b793d392aca0403162Wink Saville                    iccISms.sendMultipartText(destinationAddress, scAddress, parts,
153767a662ecde33c3979bf02b793d392aca0403162Wink Saville                            sentIntents, deliveryIntents);
154767a662ecde33c3979bf02b793d392aca0403162Wink Saville                }
155767a662ecde33c3979bf02b793d392aca0403162Wink Saville            } catch (RemoteException ex) {
156767a662ecde33c3979bf02b793d392aca0403162Wink Saville                // ignore it
157767a662ecde33c3979bf02b793d392aca0403162Wink Saville            }
158767a662ecde33c3979bf02b793d392aca0403162Wink Saville        } else {
159767a662ecde33c3979bf02b793d392aca0403162Wink Saville            PendingIntent sentIntent = null;
160767a662ecde33c3979bf02b793d392aca0403162Wink Saville            PendingIntent deliveryIntent = null;
161767a662ecde33c3979bf02b793d392aca0403162Wink Saville            if (sentIntents != null && sentIntents.size() > 0) {
162767a662ecde33c3979bf02b793d392aca0403162Wink Saville                sentIntent = sentIntents.get(0);
163767a662ecde33c3979bf02b793d392aca0403162Wink Saville            }
164767a662ecde33c3979bf02b793d392aca0403162Wink Saville            if (deliveryIntents != null && deliveryIntents.size() > 0) {
165767a662ecde33c3979bf02b793d392aca0403162Wink Saville                deliveryIntent = deliveryIntents.get(0);
166767a662ecde33c3979bf02b793d392aca0403162Wink Saville            }
167767a662ecde33c3979bf02b793d392aca0403162Wink Saville            sendTextMessage(destinationAddress, scAddress, parts.get(0),
168767a662ecde33c3979bf02b793d392aca0403162Wink Saville                    sentIntent, deliveryIntent);
169767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
170767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
171767a662ecde33c3979bf02b793d392aca0403162Wink Saville
172767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /**
173767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * Send a data based SMS to a specific application port.
174767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *
175767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * @param destinationAddress the address to send the message to
176767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * @param scAddress is the service center address or null to use
177767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *  the current default SMSC
178767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * @param destinationPort the port to deliver the message to
179767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * @param data the body of the message to send
180767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * @param sentIntent if not NULL this <code>PendingIntent</code> is
181767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *  broadcast when the message is sucessfully sent, or failed.
182767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *  The result code will be <code>Activity.RESULT_OK<code> for success,
183d1cb1d22af0775a7c030822e04db1c9ecad9beabjsh     *  or one of these errors:<br>
184d1cb1d22af0775a7c030822e04db1c9ecad9beabjsh     *  <code>RESULT_ERROR_GENERIC_FAILURE</code><br>
185d1cb1d22af0775a7c030822e04db1c9ecad9beabjsh     *  <code>RESULT_ERROR_RADIO_OFF</code><br>
186d1cb1d22af0775a7c030822e04db1c9ecad9beabjsh     *  <code>RESULT_ERROR_NULL_PDU</code><br>
187d1cb1d22af0775a7c030822e04db1c9ecad9beabjsh     *  For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include
188d1cb1d22af0775a7c030822e04db1c9ecad9beabjsh     *  the extra "errorCode" containing a radio technology specific value,
189d1cb1d22af0775a7c030822e04db1c9ecad9beabjsh     *  generally only useful for troubleshooting.<br>
190767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *  The per-application based SMS control checks sentIntent. If sentIntent
191767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *  is NULL the caller will be checked against all unknown applicaitons,
192767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *  which cause smaller number of SMS to be sent in checking period.
193767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * @param deliveryIntent if not NULL this <code>PendingIntent</code> is
194767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *  broadcast when the message is delivered to the recipient.  The
195767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *  raw pdu of the status report is in the extended data ("pdu").
196767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *
197767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * @throws IllegalArgumentException if destinationAddress or data are empty
198767a662ecde33c3979bf02b793d392aca0403162Wink Saville     */
199767a662ecde33c3979bf02b793d392aca0403162Wink Saville    public void sendDataMessage(
200767a662ecde33c3979bf02b793d392aca0403162Wink Saville            String destinationAddress, String scAddress, short destinationPort,
201767a662ecde33c3979bf02b793d392aca0403162Wink Saville            byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) {
202767a662ecde33c3979bf02b793d392aca0403162Wink Saville        if (TextUtils.isEmpty(destinationAddress)) {
203767a662ecde33c3979bf02b793d392aca0403162Wink Saville            throw new IllegalArgumentException("Invalid destinationAddress");
204767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
205767a662ecde33c3979bf02b793d392aca0403162Wink Saville
206767a662ecde33c3979bf02b793d392aca0403162Wink Saville        if (data == null || data.length == 0) {
207767a662ecde33c3979bf02b793d392aca0403162Wink Saville            throw new IllegalArgumentException("Invalid message data");
208767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
209767a662ecde33c3979bf02b793d392aca0403162Wink Saville
210767a662ecde33c3979bf02b793d392aca0403162Wink Saville        try {
211767a662ecde33c3979bf02b793d392aca0403162Wink Saville            ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
212767a662ecde33c3979bf02b793d392aca0403162Wink Saville            if (iccISms != null) {
2131f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink                iccISms.sendData(destinationAddress, scAddress, destinationPort & 0xFFFF,
2141f952a178db86559ff4bab79c4a9b5fae18096bfTammo Spalink                        data, sentIntent, deliveryIntent);
215767a662ecde33c3979bf02b793d392aca0403162Wink Saville            }
216767a662ecde33c3979bf02b793d392aca0403162Wink Saville        } catch (RemoteException ex) {
217767a662ecde33c3979bf02b793d392aca0403162Wink Saville            // ignore it
218767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
219767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
220767a662ecde33c3979bf02b793d392aca0403162Wink Saville
221767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /**
222767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * Get the default instance of the SmsManager
223767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *
224767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * @return the default instance of the SmsManager
225767a662ecde33c3979bf02b793d392aca0403162Wink Saville     */
226767a662ecde33c3979bf02b793d392aca0403162Wink Saville    public static SmsManager getDefault() {
227767a662ecde33c3979bf02b793d392aca0403162Wink Saville        if (sInstance == null) {
228767a662ecde33c3979bf02b793d392aca0403162Wink Saville            sInstance = new SmsManager();
229767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
230767a662ecde33c3979bf02b793d392aca0403162Wink Saville        return sInstance;
231767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
232767a662ecde33c3979bf02b793d392aca0403162Wink Saville
233767a662ecde33c3979bf02b793d392aca0403162Wink Saville    private SmsManager() {
234767a662ecde33c3979bf02b793d392aca0403162Wink Saville        //nothing
235767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
236767a662ecde33c3979bf02b793d392aca0403162Wink Saville
237767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /**
238767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * Copy a raw SMS PDU to the ICC.
2390da3bdb476086db02a1076780676b21e239c79d6Jaikumar Ganesh     * ICC (Integrated Circuit Card) is the card of the device.
2400da3bdb476086db02a1076780676b21e239c79d6Jaikumar Ganesh     * For example, this can be the SIM or USIM for GSM.
241767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *
242767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * @param smsc the SMSC for this message, or NULL for the default SMSC
243767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * @param pdu the raw PDU to store
244767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * @param status message status (STATUS_ON_ICC_READ, STATUS_ON_ICC_UNREAD,
245767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *               STATUS_ON_ICC_SENT, STATUS_ON_ICC_UNSENT)
246767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * @return true for success
247767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *
248767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * {@hide}
249767a662ecde33c3979bf02b793d392aca0403162Wink Saville     */
250767a662ecde33c3979bf02b793d392aca0403162Wink Saville    public boolean copyMessageToIcc(byte[] smsc, byte[] pdu, int status) {
251767a662ecde33c3979bf02b793d392aca0403162Wink Saville        boolean success = false;
252767a662ecde33c3979bf02b793d392aca0403162Wink Saville
253767a662ecde33c3979bf02b793d392aca0403162Wink Saville        try {
254767a662ecde33c3979bf02b793d392aca0403162Wink Saville            ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
255767a662ecde33c3979bf02b793d392aca0403162Wink Saville            if (iccISms != null) {
256767a662ecde33c3979bf02b793d392aca0403162Wink Saville                success = iccISms.copyMessageToIccEf(status, pdu, smsc);
257767a662ecde33c3979bf02b793d392aca0403162Wink Saville            }
258767a662ecde33c3979bf02b793d392aca0403162Wink Saville        } catch (RemoteException ex) {
259767a662ecde33c3979bf02b793d392aca0403162Wink Saville            // ignore it
260767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
261767a662ecde33c3979bf02b793d392aca0403162Wink Saville
262767a662ecde33c3979bf02b793d392aca0403162Wink Saville        return success;
263767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
264767a662ecde33c3979bf02b793d392aca0403162Wink Saville
265767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /**
266767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * Delete the specified message from the ICC.
2670da3bdb476086db02a1076780676b21e239c79d6Jaikumar Ganesh     * ICC (Integrated Circuit Card) is the card of the device.
2680da3bdb476086db02a1076780676b21e239c79d6Jaikumar Ganesh     * For example, this can be the SIM or USIM for GSM.
269767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *
270767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * @param messageIndex is the record index of the message on ICC
271767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * @return true for success
272767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *
273767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * {@hide}
274767a662ecde33c3979bf02b793d392aca0403162Wink Saville     */
275767a662ecde33c3979bf02b793d392aca0403162Wink Saville    public boolean
276767a662ecde33c3979bf02b793d392aca0403162Wink Saville    deleteMessageFromIcc(int messageIndex) {
277767a662ecde33c3979bf02b793d392aca0403162Wink Saville        boolean success = false;
278767a662ecde33c3979bf02b793d392aca0403162Wink Saville        byte[] pdu = new byte[IccConstants.SMS_RECORD_LENGTH-1];
279767a662ecde33c3979bf02b793d392aca0403162Wink Saville        Arrays.fill(pdu, (byte)0xff);
280767a662ecde33c3979bf02b793d392aca0403162Wink Saville
281767a662ecde33c3979bf02b793d392aca0403162Wink Saville        try {
282767a662ecde33c3979bf02b793d392aca0403162Wink Saville            ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
283767a662ecde33c3979bf02b793d392aca0403162Wink Saville            if (iccISms != null) {
284767a662ecde33c3979bf02b793d392aca0403162Wink Saville                success = iccISms.updateMessageOnIccEf(messageIndex, STATUS_ON_ICC_FREE, pdu);
285767a662ecde33c3979bf02b793d392aca0403162Wink Saville            }
286767a662ecde33c3979bf02b793d392aca0403162Wink Saville        } catch (RemoteException ex) {
287767a662ecde33c3979bf02b793d392aca0403162Wink Saville            // ignore it
288767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
289767a662ecde33c3979bf02b793d392aca0403162Wink Saville
290767a662ecde33c3979bf02b793d392aca0403162Wink Saville        return success;
291767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
292767a662ecde33c3979bf02b793d392aca0403162Wink Saville
293767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /**
294767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * Update the specified message on the ICC.
2950da3bdb476086db02a1076780676b21e239c79d6Jaikumar Ganesh     * ICC (Integrated Circuit Card) is the card of the device.
2960da3bdb476086db02a1076780676b21e239c79d6Jaikumar Ganesh     * For example, this can be the SIM or USIM for GSM.
297767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *
298767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * @param messageIndex record index of message to update
299767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * @param newStatus new message status (STATUS_ON_ICC_READ,
300767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *                  STATUS_ON_ICC_UNREAD, STATUS_ON_ICC_SENT,
301767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *                  STATUS_ON_ICC_UNSENT, STATUS_ON_ICC_FREE)
302767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * @param pdu the raw PDU to store
303767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * @return true for success
304767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *
305767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * {@hide}
306767a662ecde33c3979bf02b793d392aca0403162Wink Saville     */
307767a662ecde33c3979bf02b793d392aca0403162Wink Saville    public boolean updateMessageOnIcc(int messageIndex, int newStatus, byte[] pdu) {
308767a662ecde33c3979bf02b793d392aca0403162Wink Saville        boolean success = false;
309767a662ecde33c3979bf02b793d392aca0403162Wink Saville
310767a662ecde33c3979bf02b793d392aca0403162Wink Saville        try {
311767a662ecde33c3979bf02b793d392aca0403162Wink Saville            ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
312767a662ecde33c3979bf02b793d392aca0403162Wink Saville            if (iccISms != null) {
313767a662ecde33c3979bf02b793d392aca0403162Wink Saville                success = iccISms.updateMessageOnIccEf(messageIndex, newStatus, pdu);
314767a662ecde33c3979bf02b793d392aca0403162Wink Saville            }
315767a662ecde33c3979bf02b793d392aca0403162Wink Saville        } catch (RemoteException ex) {
316767a662ecde33c3979bf02b793d392aca0403162Wink Saville            // ignore it
317767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
318767a662ecde33c3979bf02b793d392aca0403162Wink Saville
319767a662ecde33c3979bf02b793d392aca0403162Wink Saville        return success;
320767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
321767a662ecde33c3979bf02b793d392aca0403162Wink Saville
322767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /**
323767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * Retrieves all messages currently stored on ICC.
3240da3bdb476086db02a1076780676b21e239c79d6Jaikumar Ganesh     * ICC (Integrated Circuit Card) is the card of the device.
3250da3bdb476086db02a1076780676b21e239c79d6Jaikumar Ganesh     * For example, this can be the SIM or USIM for GSM.
326767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *
327767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * @return <code>ArrayList</code> of <code>SmsMessage</code> objects
328767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *
329767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * {@hide}
330767a662ecde33c3979bf02b793d392aca0403162Wink Saville     */
331767a662ecde33c3979bf02b793d392aca0403162Wink Saville    public ArrayList<SmsMessage> getAllMessagesFromIcc() {
332767a662ecde33c3979bf02b793d392aca0403162Wink Saville        List<SmsRawData> records = null;
333767a662ecde33c3979bf02b793d392aca0403162Wink Saville
334767a662ecde33c3979bf02b793d392aca0403162Wink Saville        try {
335767a662ecde33c3979bf02b793d392aca0403162Wink Saville            ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
336767a662ecde33c3979bf02b793d392aca0403162Wink Saville            if (iccISms != null) {
337767a662ecde33c3979bf02b793d392aca0403162Wink Saville                records = iccISms.getAllMessagesFromIccEf();
338767a662ecde33c3979bf02b793d392aca0403162Wink Saville            }
339767a662ecde33c3979bf02b793d392aca0403162Wink Saville        } catch (RemoteException ex) {
340767a662ecde33c3979bf02b793d392aca0403162Wink Saville            // ignore it
341767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
342767a662ecde33c3979bf02b793d392aca0403162Wink Saville
343767a662ecde33c3979bf02b793d392aca0403162Wink Saville        return createMessageListFromRawRecords(records);
344767a662ecde33c3979bf02b793d392aca0403162Wink Saville   }
345767a662ecde33c3979bf02b793d392aca0403162Wink Saville
346767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /**
347767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * Create a list of <code>SmsMessage</code>s from a list of RawSmsData
348767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * records returned by <code>getAllMessagesFromIcc()</code>
349767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *
350767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * @param records SMS EF records, returned by
351767a662ecde33c3979bf02b793d392aca0403162Wink Saville     *   <code>getAllMessagesFromIcc</code>
352767a662ecde33c3979bf02b793d392aca0403162Wink Saville     * @return <code>ArrayList</code> of <code>SmsMessage</code> objects.
353767a662ecde33c3979bf02b793d392aca0403162Wink Saville     */
3540da3bdb476086db02a1076780676b21e239c79d6Jaikumar Ganesh    private ArrayList<SmsMessage> createMessageListFromRawRecords(List<SmsRawData> records) {
355767a662ecde33c3979bf02b793d392aca0403162Wink Saville        ArrayList<SmsMessage> messages = new ArrayList<SmsMessage>();
356767a662ecde33c3979bf02b793d392aca0403162Wink Saville        if (records != null) {
357767a662ecde33c3979bf02b793d392aca0403162Wink Saville            int count = records.size();
358767a662ecde33c3979bf02b793d392aca0403162Wink Saville            for (int i = 0; i < count; i++) {
3590da3bdb476086db02a1076780676b21e239c79d6Jaikumar Ganesh                SmsRawData data = records.get(i);
360767a662ecde33c3979bf02b793d392aca0403162Wink Saville                // List contains all records, including "free" records (null)
361767a662ecde33c3979bf02b793d392aca0403162Wink Saville                if (data != null) {
362767a662ecde33c3979bf02b793d392aca0403162Wink Saville                    SmsMessage sms = SmsMessage.createFromEfRecord(i+1, data.getBytes());
36372fac6778119e42f39e00f5b7e36b7500893f45cTom Taylor                    if (sms != null) {
36472fac6778119e42f39e00f5b7e36b7500893f45cTom Taylor                        messages.add(sms);
36572fac6778119e42f39e00f5b7e36b7500893f45cTom Taylor                    }
366767a662ecde33c3979bf02b793d392aca0403162Wink Saville                }
367767a662ecde33c3979bf02b793d392aca0403162Wink Saville            }
368767a662ecde33c3979bf02b793d392aca0403162Wink Saville        }
369767a662ecde33c3979bf02b793d392aca0403162Wink Saville        return messages;
370767a662ecde33c3979bf02b793d392aca0403162Wink Saville    }
371767a662ecde33c3979bf02b793d392aca0403162Wink Saville
372767a662ecde33c3979bf02b793d392aca0403162Wink Saville    // see SmsMessage.getStatusOnIcc
373767a662ecde33c3979bf02b793d392aca0403162Wink Saville
374767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /** Free space (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */
375767a662ecde33c3979bf02b793d392aca0403162Wink Saville    static public final int STATUS_ON_ICC_FREE      = 0;
376767a662ecde33c3979bf02b793d392aca0403162Wink Saville
377767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /** Received and read (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */
378767a662ecde33c3979bf02b793d392aca0403162Wink Saville    static public final int STATUS_ON_ICC_READ      = 1;
379767a662ecde33c3979bf02b793d392aca0403162Wink Saville
380767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /** Received and unread (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */
381767a662ecde33c3979bf02b793d392aca0403162Wink Saville    static public final int STATUS_ON_ICC_UNREAD    = 3;
382767a662ecde33c3979bf02b793d392aca0403162Wink Saville
383767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /** Stored and sent (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */
384767a662ecde33c3979bf02b793d392aca0403162Wink Saville    static public final int STATUS_ON_ICC_SENT      = 5;
385767a662ecde33c3979bf02b793d392aca0403162Wink Saville
386767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /** Stored and unsent (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */
387767a662ecde33c3979bf02b793d392aca0403162Wink Saville    static public final int STATUS_ON_ICC_UNSENT    = 7;
388767a662ecde33c3979bf02b793d392aca0403162Wink Saville
389767a662ecde33c3979bf02b793d392aca0403162Wink Saville    // SMS send failure result codes
390767a662ecde33c3979bf02b793d392aca0403162Wink Saville
391767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /** Generic failure cause */
392767a662ecde33c3979bf02b793d392aca0403162Wink Saville    static public final int RESULT_ERROR_GENERIC_FAILURE    = 1;
393767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /** Failed because radio was explicitly turned off */
394767a662ecde33c3979bf02b793d392aca0403162Wink Saville    static public final int RESULT_ERROR_RADIO_OFF          = 2;
395767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /** Failed because no pdu provided */
396767a662ecde33c3979bf02b793d392aca0403162Wink Saville    static public final int RESULT_ERROR_NULL_PDU           = 3;
397767a662ecde33c3979bf02b793d392aca0403162Wink Saville    /** Failed because service is currently unavailable */
398767a662ecde33c3979bf02b793d392aca0403162Wink Saville    static public final int RESULT_ERROR_NO_SERVICE         = 4;
39951b2b33219a0e97ed1e5ea75dabe4113a38871b9Yong Liu    /** Failed because we reached the sending queue limit.  {@hide} */
40051b2b33219a0e97ed1e5ea75dabe4113a38871b9Yong Liu    static public final int RESULT_ERROR_LIMIT_EXCEEDED     = 5;
401767a662ecde33c3979bf02b793d392aca0403162Wink Saville}
402