1c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville/*
2c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * Copyright (C) 2008 The Android Open Source Project
3c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville *
4c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * Licensed under the Apache License, Version 2.0 (the "License");
5c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * you may not use this file except in compliance with the License.
6c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * You may obtain a copy of the License at
7c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville *
8c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville *      http://www.apache.org/licenses/LICENSE-2.0
9c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville *
10c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * Unless required by applicable law or agreed to in writing, software
11c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * distributed under the License is distributed on an "AS IS" BASIS,
12c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * See the License for the specific language governing permissions and
14c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * limitations under the License.
15c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville */
16c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
17c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savillepackage android.telephony;
18c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
197fce994eb223105829becb6c26e3af7a9739752cDianne Hackbornimport android.app.ActivityThread;
20c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.app.PendingIntent;
21c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.os.RemoteException;
22c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.os.ServiceManager;
23c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport android.text.TextUtils;
24c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
25c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport com.android.internal.telephony.ISms;
26c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport com.android.internal.telephony.SmsRawData;
27d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenkaimport com.android.internal.telephony.uicc.IccConstants;
28c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
29c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport java.util.ArrayList;
30c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport java.util.Arrays;
31c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savilleimport java.util.List;
32c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
33c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville/*
34c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * TODO(code review): Curious question... Why are a lot of these
35c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * methods not declared as static, since they do not seem to require
36c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * any local object state?  Presumably this cannot be changed without
37c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * interfering with the API...
38c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville */
39c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
40c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville/**
41c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * Manages SMS operations such as sending data, text, and pdu SMS messages.
4229305a0d8e45e8b6731ab91e59fcba7a4d6ff766Scott Main * Get this object by calling the static method {@link #getDefault()}.
4329305a0d8e45e8b6731ab91e59fcba7a4d6ff766Scott Main *
4429305a0d8e45e8b6731ab91e59fcba7a4d6ff766Scott Main * <p>For information about how to behave as the default SMS app on Android 4.4 (API level 19)
4529305a0d8e45e8b6731ab91e59fcba7a4d6ff766Scott Main * and higher, see {@link android.provider.Telephony}.
46c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville */
47c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savillepublic final class SmsManager {
48c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** Singleton object constructed during class initialization. */
49c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static final SmsManager sInstance = new SmsManager();
50c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
51c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
52c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Send a text based SMS.
53c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
5429305a0d8e45e8b6731ab91e59fcba7a4d6ff766Scott Main     * <p class="note"><strong>Note:</strong> Using this method requires that your app has the
5529305a0d8e45e8b6731ab91e59fcba7a4d6ff766Scott Main     * {@link android.Manifest.permission#SEND_SMS} permission.</p>
5629305a0d8e45e8b6731ab91e59fcba7a4d6ff766Scott Main     *
5729305a0d8e45e8b6731ab91e59fcba7a4d6ff766Scott Main     * <p class="note"><strong>Note:</strong> Beginning with Android 4.4 (API level 19), if
5829305a0d8e45e8b6731ab91e59fcba7a4d6ff766Scott Main     * <em>and only if</em> an app is not selected as the default SMS app, the system automatically
5929305a0d8e45e8b6731ab91e59fcba7a4d6ff766Scott Main     * writes messages sent using this method to the SMS Provider (the default SMS app is always
6029305a0d8e45e8b6731ab91e59fcba7a4d6ff766Scott Main     * responsible for writing its sent messages to the SMS Provider). For information about
6129305a0d8e45e8b6731ab91e59fcba7a4d6ff766Scott Main     * how to behave as the default SMS app, see {@link android.provider.Telephony}.</p>
6229305a0d8e45e8b6731ab91e59fcba7a4d6ff766Scott Main     *
6329305a0d8e45e8b6731ab91e59fcba7a4d6ff766Scott Main     *
64c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @param destinationAddress the address to send the message to
65c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @param scAddress is the service center address or null to use
66c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *  the current default SMSC
67c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @param text the body of the message to send
68c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @param sentIntent if not NULL this <code>PendingIntent</code> is
69c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *  broadcast when the message is successfully sent, or failed.
70c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *  The result code will be <code>Activity.RESULT_OK</code> for success,
71c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *  or one of these errors:<br>
72c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *  <code>RESULT_ERROR_GENERIC_FAILURE</code><br>
73c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *  <code>RESULT_ERROR_RADIO_OFF</code><br>
74c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *  <code>RESULT_ERROR_NULL_PDU</code><br>
75c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *  For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include
76c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *  the extra "errorCode" containing a radio technology specific value,
77c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *  generally only useful for troubleshooting.<br>
78c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *  The per-application based SMS control checks sentIntent. If sentIntent
79c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *  is NULL the caller will be checked against all unknown applications,
80c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *  which cause smaller number of SMS to be sent in checking period.
81c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @param deliveryIntent if not NULL this <code>PendingIntent</code> is
82c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *  broadcast when the message is delivered to the recipient.  The
83c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *  raw pdu of the status report is in the extended data ("pdu").
84c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
85c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @throws IllegalArgumentException if destinationAddress or text are empty
86c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
87c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public void sendTextMessage(
88c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            String destinationAddress, String scAddress, String text,
89c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            PendingIntent sentIntent, PendingIntent deliveryIntent) {
90c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (TextUtils.isEmpty(destinationAddress)) {
91c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            throw new IllegalArgumentException("Invalid destinationAddress");
92c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
93c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
94c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (TextUtils.isEmpty(text)) {
95c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            throw new IllegalArgumentException("Invalid message body");
96c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
97c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
98c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        try {
99c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
100c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (iccISms != null) {
1017fce994eb223105829becb6c26e3af7a9739752cDianne Hackborn                iccISms.sendText(ActivityThread.currentPackageName(), destinationAddress,
1027fce994eb223105829becb6c26e3af7a9739752cDianne Hackborn                        scAddress, text, sentIntent, deliveryIntent);
103c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
104c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } catch (RemoteException ex) {
105c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // ignore it
106c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
107c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
108c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
109c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
110c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Divide a message text into several fragments, none bigger than
111c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * the maximum SMS message size.
112c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
113c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @param text the original message.  Must not be null.
114c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @return an <code>ArrayList</code> of strings that, in order,
115c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *   comprise the original message
116910825a2ed10bd5cc454b91380b7db0dac2e616eRika Brooks     *
117910825a2ed10bd5cc454b91380b7db0dac2e616eRika Brooks     * @throws IllegalArgumentException if text is null
118c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
119c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public ArrayList<String> divideMessage(String text) {
120910825a2ed10bd5cc454b91380b7db0dac2e616eRika Brooks        if (null == text) {
121910825a2ed10bd5cc454b91380b7db0dac2e616eRika Brooks            throw new IllegalArgumentException("text is null");
122910825a2ed10bd5cc454b91380b7db0dac2e616eRika Brooks        }
123c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return SmsMessage.fragmentText(text);
124c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
125c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
126c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
127c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Send a multi-part text based SMS.  The callee should have already
128c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * divided the message into correctly sized parts by calling
129c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * <code>divideMessage</code>.
130c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
13129305a0d8e45e8b6731ab91e59fcba7a4d6ff766Scott Main     * <p class="note"><strong>Note:</strong> Using this method requires that your app has the
13229305a0d8e45e8b6731ab91e59fcba7a4d6ff766Scott Main     * {@link android.Manifest.permission#SEND_SMS} permission.</p>
13329305a0d8e45e8b6731ab91e59fcba7a4d6ff766Scott Main     *
13429305a0d8e45e8b6731ab91e59fcba7a4d6ff766Scott Main     * <p class="note"><strong>Note:</strong> Beginning with Android 4.4 (API level 19), if
13529305a0d8e45e8b6731ab91e59fcba7a4d6ff766Scott Main     * <em>and only if</em> an app is not selected as the default SMS app, the system automatically
13629305a0d8e45e8b6731ab91e59fcba7a4d6ff766Scott Main     * writes messages sent using this method to the SMS Provider (the default SMS app is always
13729305a0d8e45e8b6731ab91e59fcba7a4d6ff766Scott Main     * responsible for writing its sent messages to the SMS Provider). For information about
13829305a0d8e45e8b6731ab91e59fcba7a4d6ff766Scott Main     * how to behave as the default SMS app, see {@link android.provider.Telephony}.</p>
13929305a0d8e45e8b6731ab91e59fcba7a4d6ff766Scott Main     *
140c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @param destinationAddress the address to send the message to
141c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @param scAddress is the service center address or null to use
142c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *   the current default SMSC
143c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @param parts an <code>ArrayList</code> of strings that, in order,
144c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *   comprise the original message
145c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @param sentIntents if not null, an <code>ArrayList</code> of
146c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *   <code>PendingIntent</code>s (one for each message part) that is
147c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *   broadcast when the corresponding message part has been sent.
148c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *   The result code will be <code>Activity.RESULT_OK</code> for success,
149c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *   or one of these errors:<br>
150c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *   <code>RESULT_ERROR_GENERIC_FAILURE</code><br>
151c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *   <code>RESULT_ERROR_RADIO_OFF</code><br>
152c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *   <code>RESULT_ERROR_NULL_PDU</code><br>
153c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *   For <code>RESULT_ERROR_GENERIC_FAILURE</code> each sentIntent may include
154c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *   the extra "errorCode" containing a radio technology specific value,
155c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *   generally only useful for troubleshooting.<br>
156c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *   The per-application based SMS control checks sentIntent. If sentIntent
157c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *   is NULL the caller will be checked against all unknown applications,
158c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *   which cause smaller number of SMS to be sent in checking period.
159c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @param deliveryIntents if not null, an <code>ArrayList</code> of
160c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *   <code>PendingIntent</code>s (one for each message part) that is
161c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *   broadcast when the corresponding message part has been delivered
162c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *   to the recipient.  The raw pdu of the status report is in the
163c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *   extended data ("pdu").
164c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
165c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @throws IllegalArgumentException if destinationAddress or data are empty
166c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
167c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public void sendMultipartTextMessage(
168c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            String destinationAddress, String scAddress, ArrayList<String> parts,
169c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents) {
170c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (TextUtils.isEmpty(destinationAddress)) {
171c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            throw new IllegalArgumentException("Invalid destinationAddress");
172c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
173c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (parts == null || parts.size() < 1) {
174c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            throw new IllegalArgumentException("Invalid message body");
175c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
176c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
177c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (parts.size() > 1) {
178c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            try {
179c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
180c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (iccISms != null) {
1817fce994eb223105829becb6c26e3af7a9739752cDianne Hackborn                    iccISms.sendMultipartText(ActivityThread.currentPackageName(),
1827fce994eb223105829becb6c26e3af7a9739752cDianne Hackborn                            destinationAddress, scAddress, parts,
183c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                            sentIntents, deliveryIntents);
184c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
185c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            } catch (RemoteException ex) {
186c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // ignore it
187c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
188c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } else {
189c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            PendingIntent sentIntent = null;
190c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            PendingIntent deliveryIntent = null;
191c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (sentIntents != null && sentIntents.size() > 0) {
192c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                sentIntent = sentIntents.get(0);
193c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
194c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (deliveryIntents != null && deliveryIntents.size() > 0) {
195c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                deliveryIntent = deliveryIntents.get(0);
196c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
197c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            sendTextMessage(destinationAddress, scAddress, parts.get(0),
198c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    sentIntent, deliveryIntent);
199c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
200c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
201c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
202c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
203c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Send a data based SMS to a specific application port.
204c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
20529305a0d8e45e8b6731ab91e59fcba7a4d6ff766Scott Main     * <p class="note"><strong>Note:</strong> Using this method requires that your app has the
20629305a0d8e45e8b6731ab91e59fcba7a4d6ff766Scott Main     * {@link android.Manifest.permission#SEND_SMS} permission.</p>
20729305a0d8e45e8b6731ab91e59fcba7a4d6ff766Scott Main     *
208c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @param destinationAddress the address to send the message to
209c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @param scAddress is the service center address or null to use
210c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *  the current default SMSC
211c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @param destinationPort the port to deliver the message to
212c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @param data the body of the message to send
213c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @param sentIntent if not NULL this <code>PendingIntent</code> is
214c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *  broadcast when the message is successfully sent, or failed.
215c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *  The result code will be <code>Activity.RESULT_OK</code> for success,
216c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *  or one of these errors:<br>
217c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *  <code>RESULT_ERROR_GENERIC_FAILURE</code><br>
218c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *  <code>RESULT_ERROR_RADIO_OFF</code><br>
219c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *  <code>RESULT_ERROR_NULL_PDU</code><br>
220c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *  For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include
221c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *  the extra "errorCode" containing a radio technology specific value,
222c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *  generally only useful for troubleshooting.<br>
223c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *  The per-application based SMS control checks sentIntent. If sentIntent
224c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *  is NULL the caller will be checked against all unknown applications,
225c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *  which cause smaller number of SMS to be sent in checking period.
226c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @param deliveryIntent if not NULL this <code>PendingIntent</code> is
227c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *  broadcast when the message is delivered to the recipient.  The
228c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *  raw pdu of the status report is in the extended data ("pdu").
229c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
230c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @throws IllegalArgumentException if destinationAddress or data are empty
231c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
232c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public void sendDataMessage(
233c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            String destinationAddress, String scAddress, short destinationPort,
234c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) {
235c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (TextUtils.isEmpty(destinationAddress)) {
236c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            throw new IllegalArgumentException("Invalid destinationAddress");
237c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
238c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
239c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (data == null || data.length == 0) {
240c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            throw new IllegalArgumentException("Invalid message data");
241c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
242c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
243c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        try {
244c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
245c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (iccISms != null) {
2467fce994eb223105829becb6c26e3af7a9739752cDianne Hackborn                iccISms.sendData(ActivityThread.currentPackageName(),
2477fce994eb223105829becb6c26e3af7a9739752cDianne Hackborn                        destinationAddress, scAddress, destinationPort & 0xFFFF,
248c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        data, sentIntent, deliveryIntent);
249c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
250c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } catch (RemoteException ex) {
251c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // ignore it
252c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
253c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
254c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
255c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
256c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Get the default instance of the SmsManager
257c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
258c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @return the default instance of the SmsManager
259c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
260c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public static SmsManager getDefault() {
261c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return sInstance;
262c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
263c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
264c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private SmsManager() {
265c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        //nothing
266c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
267c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
268c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
269c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Copy a raw SMS PDU to the ICC.
270c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * ICC (Integrated Circuit Card) is the card of the device.
271c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * For example, this can be the SIM or USIM for GSM.
272c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
273c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @param smsc the SMSC for this message, or NULL for the default SMSC
274c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @param pdu the raw PDU to store
275c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @param status message status (STATUS_ON_ICC_READ, STATUS_ON_ICC_UNREAD,
276c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *               STATUS_ON_ICC_SENT, STATUS_ON_ICC_UNSENT)
277c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @return true for success
278c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
279910825a2ed10bd5cc454b91380b7db0dac2e616eRika Brooks     * @throws IllegalArgumentException if pdu is NULL
280c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * {@hide}
281c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
282c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public boolean copyMessageToIcc(byte[] smsc, byte[] pdu, int status) {
283c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        boolean success = false;
284c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
285910825a2ed10bd5cc454b91380b7db0dac2e616eRika Brooks        if (null == pdu) {
286910825a2ed10bd5cc454b91380b7db0dac2e616eRika Brooks            throw new IllegalArgumentException("pdu is NULL");
287910825a2ed10bd5cc454b91380b7db0dac2e616eRika Brooks        }
288c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        try {
289c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
290c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (iccISms != null) {
2917fce994eb223105829becb6c26e3af7a9739752cDianne Hackborn                success = iccISms.copyMessageToIccEf(ActivityThread.currentPackageName(),
2927fce994eb223105829becb6c26e3af7a9739752cDianne Hackborn                        status, pdu, smsc);
293c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
294c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } catch (RemoteException ex) {
295c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // ignore it
296c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
297c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
298c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return success;
299c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
300c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
301c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
302c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Delete the specified message from the ICC.
303c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * ICC (Integrated Circuit Card) is the card of the device.
304c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * For example, this can be the SIM or USIM for GSM.
305c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
306c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @param messageIndex is the record index of the message on ICC
307c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @return true for success
308c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
309c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * {@hide}
310c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
311c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public boolean
312c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    deleteMessageFromIcc(int messageIndex) {
313c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        boolean success = false;
314c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        byte[] pdu = new byte[IccConstants.SMS_RECORD_LENGTH-1];
315c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        Arrays.fill(pdu, (byte)0xff);
316c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
317c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        try {
318c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
319c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (iccISms != null) {
3207fce994eb223105829becb6c26e3af7a9739752cDianne Hackborn                success = iccISms.updateMessageOnIccEf(ActivityThread.currentPackageName(),
3217fce994eb223105829becb6c26e3af7a9739752cDianne Hackborn                        messageIndex, STATUS_ON_ICC_FREE, pdu);
322c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
323c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } catch (RemoteException ex) {
324c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // ignore it
325c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
326c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
327c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return success;
328c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
329c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
330c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
331c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Update the specified message on the ICC.
332c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * ICC (Integrated Circuit Card) is the card of the device.
333c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * For example, this can be the SIM or USIM for GSM.
334c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
335c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @param messageIndex record index of message to update
336c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @param newStatus new message status (STATUS_ON_ICC_READ,
337c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *                  STATUS_ON_ICC_UNREAD, STATUS_ON_ICC_SENT,
338c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *                  STATUS_ON_ICC_UNSENT, STATUS_ON_ICC_FREE)
339c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @param pdu the raw PDU to store
340c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @return true for success
341c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
342c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * {@hide}
343c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
344c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public boolean updateMessageOnIcc(int messageIndex, int newStatus, byte[] pdu) {
345c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        boolean success = false;
346c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
347c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        try {
348c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
349c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (iccISms != null) {
3507fce994eb223105829becb6c26e3af7a9739752cDianne Hackborn                success = iccISms.updateMessageOnIccEf(ActivityThread.currentPackageName(),
3517fce994eb223105829becb6c26e3af7a9739752cDianne Hackborn                        messageIndex, newStatus, pdu);
352c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
353c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } catch (RemoteException ex) {
354c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // ignore it
355c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
356c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
357c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return success;
358c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
359c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
360c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
361c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Retrieves all messages currently stored on ICC.
362c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * ICC (Integrated Circuit Card) is the card of the device.
363c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * For example, this can be the SIM or USIM for GSM.
364c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
365c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @return <code>ArrayList</code> of <code>SmsMessage</code> objects
366c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
367c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * {@hide}
368c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
369c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public static ArrayList<SmsMessage> getAllMessagesFromIcc() {
370c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        List<SmsRawData> records = null;
371c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
372c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        try {
373c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
374c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (iccISms != null) {
3757fce994eb223105829becb6c26e3af7a9739752cDianne Hackborn                records = iccISms.getAllMessagesFromIccEf(ActivityThread.currentPackageName());
376c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
377c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } catch (RemoteException ex) {
378c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // ignore it
379c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
380c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
381c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return createMessageListFromRawRecords(records);
382c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
383c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
384c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
385c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Enable reception of cell broadcast (SMS-CB) messages with the given
386c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * message identifier. Note that if two different clients enable the same
387c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * message identifier, they must both disable it for the device to stop
388c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * receiving those messages. All received messages will be broadcast in an
389c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * intent with the action "android.provider.Telephony.SMS_CB_RECEIVED".
390c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Note: This call is blocking, callers may want to avoid calling it from
391c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * the main thread of an application.
392c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
393a63f55cf17629426d976830429a7612387532195Rika Brooks     * @param messageIdentifier Message identifier as specified in TS 23.041 (3GPP)
394a63f55cf17629426d976830429a7612387532195Rika Brooks     * or C.R1001-G (3GPP2)
395c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @return true if successful, false otherwise
396c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @see #disableCellBroadcast(int)
397c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
398c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * {@hide}
399c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
400c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public boolean enableCellBroadcast(int messageIdentifier) {
401c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        boolean success = false;
402c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
403c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        try {
404c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
405c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (iccISms != null) {
406c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                success = iccISms.enableCellBroadcast(messageIdentifier);
407c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
408c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } catch (RemoteException ex) {
409c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // ignore it
410c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
411c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
412c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return success;
413c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
414c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
415c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
416c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Disable reception of cell broadcast (SMS-CB) messages with the given
417c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * message identifier. Note that if two different clients enable the same
418c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * message identifier, they must both disable it for the device to stop
419c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * receiving those messages.
420c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Note: This call is blocking, callers may want to avoid calling it from
421c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * the main thread of an application.
422c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
423a63f55cf17629426d976830429a7612387532195Rika Brooks     * @param messageIdentifier Message identifier as specified in TS 23.041 (3GPP)
424a63f55cf17629426d976830429a7612387532195Rika Brooks     * or C.R1001-G (3GPP2)
425c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @return true if successful, false otherwise
426c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
427c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @see #enableCellBroadcast(int)
428c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
429c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * {@hide}
430c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
431c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public boolean disableCellBroadcast(int messageIdentifier) {
432c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        boolean success = false;
433c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
434c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        try {
435c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
436c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (iccISms != null) {
437c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                success = iccISms.disableCellBroadcast(messageIdentifier);
438c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
439c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } catch (RemoteException ex) {
440c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // ignore it
441c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
442c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
443c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return success;
444c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
445c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
446c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
447c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Enable reception of cell broadcast (SMS-CB) messages with the given
448c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * message identifier range. Note that if two different clients enable the same
449c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * message identifier, they must both disable it for the device to stop
450c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * receiving those messages. All received messages will be broadcast in an
451c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * intent with the action "android.provider.Telephony.SMS_CB_RECEIVED".
452c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Note: This call is blocking, callers may want to avoid calling it from
453c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * the main thread of an application.
454c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
455a63f55cf17629426d976830429a7612387532195Rika Brooks     * @param startMessageId first message identifier as specified in TS 23.041 (3GPP)
456a63f55cf17629426d976830429a7612387532195Rika Brooks     * or C.R1001-G (3GPP2)
457a63f55cf17629426d976830429a7612387532195Rika Brooks     * @param endMessageId last message identifier as specified in TS 23.041 (3GPP)
458a63f55cf17629426d976830429a7612387532195Rika Brooks     * or C.R1001-G (3GPP2)
459c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @return true if successful, false otherwise
460c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @see #disableCellBroadcastRange(int, int)
461c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
462910825a2ed10bd5cc454b91380b7db0dac2e616eRika Brooks     * @throws IllegalArgumentException if endMessageId < startMessageId
463c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * {@hide}
464c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
465c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public boolean enableCellBroadcastRange(int startMessageId, int endMessageId) {
466c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        boolean success = false;
467c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
468910825a2ed10bd5cc454b91380b7db0dac2e616eRika Brooks        if (endMessageId < startMessageId) {
469910825a2ed10bd5cc454b91380b7db0dac2e616eRika Brooks            throw new IllegalArgumentException("endMessageId < startMessageId");
470910825a2ed10bd5cc454b91380b7db0dac2e616eRika Brooks        }
471c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        try {
472c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
473c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (iccISms != null) {
474c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                success = iccISms.enableCellBroadcastRange(startMessageId, endMessageId);
475c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
476c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } catch (RemoteException ex) {
477c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // ignore it
478c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
479c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
480c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return success;
481c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
482c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
483c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
484c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Disable reception of cell broadcast (SMS-CB) messages with the given
485c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * message identifier range. Note that if two different clients enable the same
486c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * message identifier, they must both disable it for the device to stop
487c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * receiving those messages.
488c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Note: This call is blocking, callers may want to avoid calling it from
489c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * the main thread of an application.
490c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
491a63f55cf17629426d976830429a7612387532195Rika Brooks     * @param startMessageId first message identifier as specified in TS 23.041 (3GPP)
492a63f55cf17629426d976830429a7612387532195Rika Brooks     * or C.R1001-G (3GPP2)
493a63f55cf17629426d976830429a7612387532195Rika Brooks     * @param endMessageId last message identifier as specified in TS 23.041 (3GPP)
494a63f55cf17629426d976830429a7612387532195Rika Brooks     * or C.R1001-G (3GPP2)
495c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @return true if successful, false otherwise
496c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
497c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @see #enableCellBroadcastRange(int, int)
498c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
499910825a2ed10bd5cc454b91380b7db0dac2e616eRika Brooks     * @throws IllegalArgumentException if endMessageId < startMessageId
500c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * {@hide}
501c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
502c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    public boolean disableCellBroadcastRange(int startMessageId, int endMessageId) {
503c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        boolean success = false;
504c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
505910825a2ed10bd5cc454b91380b7db0dac2e616eRika Brooks        if (endMessageId < startMessageId) {
506910825a2ed10bd5cc454b91380b7db0dac2e616eRika Brooks            throw new IllegalArgumentException("endMessageId < startMessageId");
507910825a2ed10bd5cc454b91380b7db0dac2e616eRika Brooks        }
508c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        try {
509c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
510c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            if (iccISms != null) {
511c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                success = iccISms.disableCellBroadcastRange(startMessageId, endMessageId);
512c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
513c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        } catch (RemoteException ex) {
514c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            // ignore it
515c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
516c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
517c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return success;
518c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
519c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
520c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /**
521c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * Create a list of <code>SmsMessage</code>s from a list of RawSmsData
522c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * records returned by <code>getAllMessagesFromIcc()</code>
523c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *
524c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @param records SMS EF records, returned by
525c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     *   <code>getAllMessagesFromIcc</code>
526c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     * @return <code>ArrayList</code> of <code>SmsMessage</code> objects.
527c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville     */
528c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    private static ArrayList<SmsMessage> createMessageListFromRawRecords(List<SmsRawData> records) {
529c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        ArrayList<SmsMessage> messages = new ArrayList<SmsMessage>();
530c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        if (records != null) {
531c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            int count = records.size();
532c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            for (int i = 0; i < count; i++) {
533c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                SmsRawData data = records.get(i);
534c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                // List contains all records, including "free" records (null)
535c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                if (data != null) {
536c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    SmsMessage sms = SmsMessage.createFromEfRecord(i+1, data.getBytes());
537c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    if (sms != null) {
538c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                        messages.add(sms);
539c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                    }
540c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville                }
541c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville            }
542c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        }
543c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville        return messages;
544c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    }
545c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
5461260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa    /**
5471260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa     * SMS over IMS is supported if IMS is registered and SMS is supported
5481260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa     * on IMS.
5491260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa     *
5501260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa     * @return true if SMS over IMS is supported, false otherwise
5511260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa     *
5521260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa     * @see #getImsSmsFormat()
5531260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa     *
5541260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa     * @hide
5551260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa     */
5561260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa    boolean isImsSmsSupported() {
5571260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        boolean boSupported = false;
5581260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        try {
5591260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
5601260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            if (iccISms != null) {
5611260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                boSupported = iccISms.isImsSmsSupported();
5621260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            }
5631260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        } catch (RemoteException ex) {
5641260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            // ignore it
5651260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        }
5661260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        return boSupported;
5671260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa    }
5681260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa
5691260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa    /**
5701260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa     * Gets SMS format supported on IMS.  SMS over IMS format is
5711260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa     * either 3GPP or 3GPP2.
5721260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa     *
5731260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa     * @return SmsMessage.FORMAT_3GPP,
5741260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa     *         SmsMessage.FORMAT_3GPP2
5751260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa     *      or SmsMessage.FORMAT_UNKNOWN
5761260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa     *
5771260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa     * @see #isImsSmsSupported()
5781260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa     *
5791260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa     * @hide
5801260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa     */
5811260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa    String getImsSmsFormat() {
5821260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        String format = com.android.internal.telephony.SmsConstants.FORMAT_UNKNOWN;
5831260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        try {
5841260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
5851260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            if (iccISms != null) {
5861260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa                format = iccISms.getImsSmsFormat();
5871260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            }
5881260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        } catch (RemoteException ex) {
5891260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa            // ignore it
5901260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        }
5911260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa        return format;
5921260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa    }
5931260f1c6c909f2940989b72afe1b91fd83845eaaSukanya Rajkhowa
594c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // see SmsMessage.getStatusOnIcc
595c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
596c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** Free space (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */
597c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static public final int STATUS_ON_ICC_FREE      = 0;
598c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
599c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** Received and read (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */
600c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static public final int STATUS_ON_ICC_READ      = 1;
601c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
602c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** Received and unread (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */
603c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static public final int STATUS_ON_ICC_UNREAD    = 3;
604c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
605c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** Stored and sent (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */
606c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static public final int STATUS_ON_ICC_SENT      = 5;
607c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
608c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** Stored and unsent (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */
609c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static public final int STATUS_ON_ICC_UNSENT    = 7;
610c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
611c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    // SMS send failure result codes
612c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville
613c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** Generic failure cause */
614c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static public final int RESULT_ERROR_GENERIC_FAILURE    = 1;
615c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** Failed because radio was explicitly turned off */
616c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static public final int RESULT_ERROR_RADIO_OFF          = 2;
617c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** Failed because no pdu provided */
618c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static public final int RESULT_ERROR_NULL_PDU           = 3;
619c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** Failed because service is currently unavailable */
620c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static public final int RESULT_ERROR_NO_SERVICE         = 4;
621c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** Failed because we reached the sending queue limit.  {@hide} */
622c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static public final int RESULT_ERROR_LIMIT_EXCEEDED     = 5;
623c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    /** Failed because FDN is enabled. {@hide} */
624c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville    static public final int RESULT_ERROR_FDN_CHECK_FAILURE  = 6;
625c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville}
626