1/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.provider;
18
19import android.annotation.SdkConstant;
20import android.annotation.SdkConstant.SdkConstantType;
21import android.content.ContentResolver;
22import android.content.ContentValues;
23import android.content.Context;
24import android.content.Intent;
25import android.database.Cursor;
26import android.database.sqlite.SqliteWrapper;
27import android.net.Uri;
28import android.os.Environment;
29import android.telephony.SmsMessage;
30import android.text.TextUtils;
31import android.util.Log;
32import android.util.Patterns;
33
34
35import java.util.HashSet;
36import java.util.Set;
37import java.util.regex.Matcher;
38import java.util.regex.Pattern;
39
40/**
41 * The Telephony provider contains data related to phone operation.
42 *
43 * @hide
44 */
45public final class Telephony {
46    private static final String TAG = "Telephony";
47    private static final boolean DEBUG = true;
48    private static final boolean LOCAL_LOGV = false;
49
50    // Constructor
51    public Telephony() {
52    }
53
54    /**
55     * Base columns for tables that contain text based SMSs.
56     */
57    public interface TextBasedSmsColumns {
58        /**
59         * The type of the message
60         * <P>Type: INTEGER</P>
61         */
62        public static final String TYPE = "type";
63
64        public static final int MESSAGE_TYPE_ALL    = 0;
65        public static final int MESSAGE_TYPE_INBOX  = 1;
66        public static final int MESSAGE_TYPE_SENT   = 2;
67        public static final int MESSAGE_TYPE_DRAFT  = 3;
68        public static final int MESSAGE_TYPE_OUTBOX = 4;
69        public static final int MESSAGE_TYPE_FAILED = 5; // for failed outgoing messages
70        public static final int MESSAGE_TYPE_QUEUED = 6; // for messages to send later
71
72
73        /**
74         * The thread ID of the message
75         * <P>Type: INTEGER</P>
76         */
77        public static final String THREAD_ID = "thread_id";
78
79        /**
80         * The address of the other party
81         * <P>Type: TEXT</P>
82         */
83        public static final String ADDRESS = "address";
84
85        /**
86         * The person ID of the sender
87         * <P>Type: INTEGER (long)</P>
88         */
89        public static final String PERSON_ID = "person";
90
91        /**
92         * The date the message was received
93         * <P>Type: INTEGER (long)</P>
94         */
95        public static final String DATE = "date";
96
97        /**
98         * The date the message was sent
99         * <P>Type: INTEGER (long)</P>
100         */
101        public static final String DATE_SENT = "date_sent";
102
103        /**
104         * Has the message been read
105         * <P>Type: INTEGER (boolean)</P>
106         */
107        public static final String READ = "read";
108
109        /**
110         * Indicates whether this message has been seen by the user. The "seen" flag will be
111         * used to figure out whether we need to throw up a statusbar notification or not.
112         */
113        public static final String SEEN = "seen";
114
115        /**
116         * The TP-Status value for the message, or -1 if no status has
117         * been received
118         */
119        public static final String STATUS = "status";
120
121        public static final int STATUS_NONE = -1;
122        public static final int STATUS_COMPLETE = 0;
123        public static final int STATUS_PENDING = 32;
124        public static final int STATUS_FAILED = 64;
125
126        /**
127         * The subject of the message, if present
128         * <P>Type: TEXT</P>
129         */
130        public static final String SUBJECT = "subject";
131
132        /**
133         * The body of the message
134         * <P>Type: TEXT</P>
135         */
136        public static final String BODY = "body";
137
138        /**
139         * The id of the sender of the conversation, if present
140         * <P>Type: INTEGER (reference to item in content://contacts/people)</P>
141         */
142        public static final String PERSON = "person";
143
144        /**
145         * The protocol identifier code
146         * <P>Type: INTEGER</P>
147         */
148        public static final String PROTOCOL = "protocol";
149
150        /**
151         * Whether the <code>TP-Reply-Path</code> bit was set on this message
152         * <P>Type: BOOLEAN</P>
153         */
154        public static final String REPLY_PATH_PRESENT = "reply_path_present";
155
156        /**
157         * The service center (SC) through which to send the message, if present
158         * <P>Type: TEXT</P>
159         */
160        public static final String SERVICE_CENTER = "service_center";
161
162        /**
163         * Has the message been locked?
164         * <P>Type: INTEGER (boolean)</P>
165         */
166        public static final String LOCKED = "locked";
167
168        /**
169         * Error code associated with sending or receiving this message
170         * <P>Type: INTEGER</P>
171         */
172        public static final String ERROR_CODE = "error_code";
173
174        /**
175         * Meta data used externally.
176         * <P>Type: TEXT</P>
177         */
178        public static final String META_DATA = "meta_data";
179}
180
181    /**
182     * Contains all text based SMS messages.
183     */
184    public static final class Sms implements BaseColumns, TextBasedSmsColumns {
185        public static final Cursor query(ContentResolver cr, String[] projection) {
186            return cr.query(CONTENT_URI, projection, null, null, DEFAULT_SORT_ORDER);
187        }
188
189        public static final Cursor query(ContentResolver cr, String[] projection,
190                String where, String orderBy) {
191            return cr.query(CONTENT_URI, projection, where,
192                                         null, orderBy == null ? DEFAULT_SORT_ORDER : orderBy);
193        }
194
195        /**
196         * The content:// style URL for this table
197         */
198        public static final Uri CONTENT_URI =
199            Uri.parse("content://sms");
200
201        /**
202         * The default sort order for this table
203         */
204        public static final String DEFAULT_SORT_ORDER = "date DESC";
205
206        /**
207         * Add an SMS to the given URI.
208         *
209         * @param resolver the content resolver to use
210         * @param uri the URI to add the message to
211         * @param address the address of the sender
212         * @param body the body of the message
213         * @param subject the psuedo-subject of the message
214         * @param date the timestamp for the message
215         * @param read true if the message has been read, false if not
216         * @param deliveryReport true if a delivery report was requested, false if not
217         * @return the URI for the new message
218         */
219        public static Uri addMessageToUri(ContentResolver resolver,
220                Uri uri, String address, String body, String subject,
221                Long date, boolean read, boolean deliveryReport) {
222            return addMessageToUri(resolver, uri, address, body, subject,
223                    date, read, deliveryReport, -1L);
224        }
225
226        /**
227         * Add an SMS to the given URI with thread_id specified.
228         *
229         * @param resolver the content resolver to use
230         * @param uri the URI to add the message to
231         * @param address the address of the sender
232         * @param body the body of the message
233         * @param subject the psuedo-subject of the message
234         * @param date the timestamp for the message
235         * @param read true if the message has been read, false if not
236         * @param deliveryReport true if a delivery report was requested, false if not
237         * @param threadId the thread_id of the message
238         * @return the URI for the new message
239         */
240        public static Uri addMessageToUri(ContentResolver resolver,
241                Uri uri, String address, String body, String subject,
242                Long date, boolean read, boolean deliveryReport, long threadId) {
243            ContentValues values = new ContentValues(7);
244
245            values.put(ADDRESS, address);
246            if (date != null) {
247                values.put(DATE, date);
248            }
249            values.put(READ, read ? Integer.valueOf(1) : Integer.valueOf(0));
250            values.put(SUBJECT, subject);
251            values.put(BODY, body);
252            if (deliveryReport) {
253                values.put(STATUS, STATUS_PENDING);
254            }
255            if (threadId != -1L) {
256                values.put(THREAD_ID, threadId);
257            }
258            return resolver.insert(uri, values);
259        }
260
261        /**
262         * Move a message to the given folder.
263         *
264         * @param context the context to use
265         * @param uri the message to move
266         * @param folder the folder to move to
267         * @return true if the operation succeeded
268         */
269        public static boolean moveMessageToFolder(Context context,
270                Uri uri, int folder, int error) {
271            if (uri == null) {
272                return false;
273            }
274
275            boolean markAsUnread = false;
276            boolean markAsRead = false;
277            switch(folder) {
278            case MESSAGE_TYPE_INBOX:
279            case MESSAGE_TYPE_DRAFT:
280                break;
281            case MESSAGE_TYPE_OUTBOX:
282            case MESSAGE_TYPE_SENT:
283                markAsRead = true;
284                break;
285            case MESSAGE_TYPE_FAILED:
286            case MESSAGE_TYPE_QUEUED:
287                markAsUnread = true;
288                break;
289            default:
290                return false;
291            }
292
293            ContentValues values = new ContentValues(3);
294
295            values.put(TYPE, folder);
296            if (markAsUnread) {
297                values.put(READ, Integer.valueOf(0));
298            } else if (markAsRead) {
299                values.put(READ, Integer.valueOf(1));
300            }
301            values.put(ERROR_CODE, error);
302
303            return 1 == SqliteWrapper.update(context, context.getContentResolver(),
304                            uri, values, null, null);
305        }
306
307        /**
308         * Returns true iff the folder (message type) identifies an
309         * outgoing message.
310         */
311        public static boolean isOutgoingFolder(int messageType) {
312            return  (messageType == MESSAGE_TYPE_FAILED)
313                    || (messageType == MESSAGE_TYPE_OUTBOX)
314                    || (messageType == MESSAGE_TYPE_SENT)
315                    || (messageType == MESSAGE_TYPE_QUEUED);
316        }
317
318        /**
319         * Contains all text based SMS messages in the SMS app's inbox.
320         */
321        public static final class Inbox implements BaseColumns, TextBasedSmsColumns {
322            /**
323             * The content:// style URL for this table
324             */
325            public static final Uri CONTENT_URI =
326                Uri.parse("content://sms/inbox");
327
328            /**
329             * The default sort order for this table
330             */
331            public static final String DEFAULT_SORT_ORDER = "date DESC";
332
333            /**
334             * Add an SMS to the Draft box.
335             *
336             * @param resolver the content resolver to use
337             * @param address the address of the sender
338             * @param body the body of the message
339             * @param subject the psuedo-subject of the message
340             * @param date the timestamp for the message
341             * @param read true if the message has been read, false if not
342             * @return the URI for the new message
343             */
344            public static Uri addMessage(ContentResolver resolver,
345                    String address, String body, String subject, Long date,
346                    boolean read) {
347                return addMessageToUri(resolver, CONTENT_URI, address, body,
348                        subject, date, read, false);
349            }
350        }
351
352        /**
353         * Contains all sent text based SMS messages in the SMS app's.
354         */
355        public static final class Sent implements BaseColumns, TextBasedSmsColumns {
356            /**
357             * The content:// style URL for this table
358             */
359            public static final Uri CONTENT_URI =
360                    Uri.parse("content://sms/sent");
361
362            /**
363             * The default sort order for this table
364             */
365            public static final String DEFAULT_SORT_ORDER = "date DESC";
366
367            /**
368             * Add an SMS to the Draft box.
369             *
370             * @param resolver the content resolver to use
371             * @param address the address of the sender
372             * @param body the body of the message
373             * @param subject the psuedo-subject of the message
374             * @param date the timestamp for the message
375             * @return the URI for the new message
376             */
377            public static Uri addMessage(ContentResolver resolver,
378                    String address, String body, String subject, Long date) {
379                return addMessageToUri(resolver, CONTENT_URI, address, body,
380                        subject, date, true, false);
381            }
382        }
383
384        /**
385         * Contains all sent text based SMS messages in the SMS app's.
386         */
387        public static final class Draft implements BaseColumns, TextBasedSmsColumns {
388            /**
389             * The content:// style URL for this table
390             */
391            public static final Uri CONTENT_URI =
392                    Uri.parse("content://sms/draft");
393
394            /**
395             * The default sort order for this table
396             */
397            public static final String DEFAULT_SORT_ORDER = "date DESC";
398
399            /**
400             * Add an SMS to the Draft box.
401             *
402             * @param resolver the content resolver to use
403             * @param address the address of the sender
404             * @param body the body of the message
405             * @param subject the psuedo-subject of the message
406             * @param date the timestamp for the message
407             * @return the URI for the new message
408             */
409            public static Uri addMessage(ContentResolver resolver,
410                    String address, String body, String subject, Long date) {
411                return addMessageToUri(resolver, CONTENT_URI, address, body,
412                        subject, date, true, false);
413            }
414
415            /**
416             * Save over an existing draft message.
417             *
418             * @param resolver the content resolver to use
419             * @param uri of existing message
420             * @param body the new body for the draft message
421             * @return true is successful, false otherwise
422             */
423            public static boolean saveMessage(ContentResolver resolver,
424                    Uri uri, String body) {
425                ContentValues values = new ContentValues(2);
426                values.put(BODY, body);
427                values.put(DATE, System.currentTimeMillis());
428                return resolver.update(uri, values, null, null) == 1;
429            }
430        }
431
432        /**
433         * Contains all pending outgoing text based SMS messages.
434         */
435        public static final class Outbox implements BaseColumns, TextBasedSmsColumns {
436            /**
437             * The content:// style URL for this table
438             */
439            public static final Uri CONTENT_URI =
440                Uri.parse("content://sms/outbox");
441
442            /**
443             * The default sort order for this table
444             */
445            public static final String DEFAULT_SORT_ORDER = "date DESC";
446
447            /**
448             * Add an SMS to the Out box.
449             *
450             * @param resolver the content resolver to use
451             * @param address the address of the sender
452             * @param body the body of the message
453             * @param subject the psuedo-subject of the message
454             * @param date the timestamp for the message
455             * @param deliveryReport whether a delivery report was requested for the message
456             * @return the URI for the new message
457             */
458            public static Uri addMessage(ContentResolver resolver,
459                    String address, String body, String subject, Long date,
460                    boolean deliveryReport, long threadId) {
461                return addMessageToUri(resolver, CONTENT_URI, address, body,
462                        subject, date, true, deliveryReport, threadId);
463            }
464        }
465
466        /**
467         * Contains all sent text-based SMS messages in the SMS app's.
468         */
469        public static final class Conversations
470                implements BaseColumns, TextBasedSmsColumns {
471            /**
472             * The content:// style URL for this table
473             */
474            public static final Uri CONTENT_URI =
475                Uri.parse("content://sms/conversations");
476
477            /**
478             * The default sort order for this table
479             */
480            public static final String DEFAULT_SORT_ORDER = "date DESC";
481
482            /**
483             * The first 45 characters of the body of the message
484             * <P>Type: TEXT</P>
485             */
486            public static final String SNIPPET = "snippet";
487
488            /**
489             * The number of messages in the conversation
490             * <P>Type: INTEGER</P>
491             */
492            public static final String MESSAGE_COUNT = "msg_count";
493        }
494
495        /**
496         * Contains info about SMS related Intents that are broadcast.
497         */
498        public static final class Intents {
499            /**
500             * Set by BroadcastReceiver. Indicates the message was handled
501             * successfully.
502             */
503            public static final int RESULT_SMS_HANDLED = 1;
504
505            /**
506             * Set by BroadcastReceiver. Indicates a generic error while
507             * processing the message.
508             */
509            public static final int RESULT_SMS_GENERIC_ERROR = 2;
510
511            /**
512             * Set by BroadcastReceiver. Indicates insufficient memory to store
513             * the message.
514             */
515            public static final int RESULT_SMS_OUT_OF_MEMORY = 3;
516
517            /**
518             * Set by BroadcastReceiver. Indicates the message, while
519             * possibly valid, is of a format or encoding that is not
520             * supported.
521             */
522            public static final int RESULT_SMS_UNSUPPORTED = 4;
523
524            /**
525             * Broadcast Action: A new text based SMS message has been received
526             * by the device. The intent will have the following extra
527             * values:</p>
528             *
529             * <ul>
530             *   <li><em>pdus</em> - An Object[] od byte[]s containing the PDUs
531             *   that make up the message.</li>
532             * </ul>
533             *
534             * <p>The extra values can be extracted using
535             * {@link #getMessagesFromIntent(Intent)}.</p>
536             *
537             * <p>If a BroadcastReceiver encounters an error while processing
538             * this intent it should set the result code appropriately.</p>
539             */
540            @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
541            public static final String SMS_RECEIVED_ACTION =
542                    "android.provider.Telephony.SMS_RECEIVED";
543
544            /**
545             * Broadcast Action: A new data based SMS message has been received
546             * by the device. The intent will have the following extra
547             * values:</p>
548             *
549             * <ul>
550             *   <li><em>pdus</em> - An Object[] of byte[]s containing the PDUs
551             *   that make up the message.</li>
552             * </ul>
553             *
554             * <p>The extra values can be extracted using
555             * {@link #getMessagesFromIntent(Intent)}.</p>
556             *
557             * <p>If a BroadcastReceiver encounters an error while processing
558             * this intent it should set the result code appropriately.</p>
559             */
560            @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
561            public static final String DATA_SMS_RECEIVED_ACTION =
562                    "android.intent.action.DATA_SMS_RECEIVED";
563
564            /**
565             * Broadcast Action: A new WAP PUSH message has been received by the
566             * device. The intent will have the following extra
567             * values:</p>
568             *
569             * <ul>
570             *   <li><em>transactionId (Integer)</em> - The WAP transaction ID</li>
571             *   <li><em>pduType (Integer)</em> - The WAP PDU type</li>
572             *   <li><em>header (byte[])</em> - The header of the message</li>
573             *   <li><em>data (byte[])</em> - The data payload of the message</li>
574             *   <li><em>contentTypeParameters (HashMap&lt;String,String&gt;)</em>
575             *   - Any parameters associated with the content type
576             *   (decoded from the WSP Content-Type header)</li>
577             * </ul>
578             *
579             * <p>If a BroadcastReceiver encounters an error while processing
580             * this intent it should set the result code appropriately.</p>
581             *
582             * <p>The contentTypeParameters extra value is map of content parameters keyed by
583             * their names.</p>
584             *
585             * <p>If any unassigned well-known parameters are encountered, the key of the map will
586             * be 'unassigned/0x...', where '...' is the hex value of the unassigned parameter.  If
587             * a parameter has No-Value the value in the map will be null.</p>
588             */
589            @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
590            public static final String WAP_PUSH_RECEIVED_ACTION =
591                    "android.provider.Telephony.WAP_PUSH_RECEIVED";
592
593            /**
594             * Broadcast Action: A new Cell Broadcast message has been received
595             * by the device. The intent will have the following extra
596             * values:</p>
597             *
598             * <ul>
599             *   <li><em>pdus</em> - An Object[] of byte[]s containing the PDUs
600             *   that make up the message.</li>
601             * </ul>
602             *
603             * <p>The extra values can be extracted using
604             * {@link #getMessagesFromIntent(Intent)}.</p>
605             *
606             * <p>If a BroadcastReceiver encounters an error while processing
607             * this intent it should set the result code appropriately.</p>
608             */
609            @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
610            public static final String SMS_CB_RECEIVED_ACTION =
611                    "android.provider.Telephony.SMS_CB_RECEIVED";
612
613            /**
614             * Broadcast Action: A new Emergency Broadcast message has been received
615             * by the device. The intent will have the following extra
616             * values:</p>
617             *
618             * <ul>
619             *   <li><em>pdus</em> - An Object[] of byte[]s containing the PDUs
620             *   that make up the message.</li>
621             * </ul>
622             *
623             * <p>The extra values can be extracted using
624             * {@link #getMessagesFromIntent(Intent)}.</p>
625             *
626             * <p>If a BroadcastReceiver encounters an error while processing
627             * this intent it should set the result code appropriately.</p>
628             */
629            @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
630            public static final String SMS_EMERGENCY_CB_RECEIVED_ACTION =
631                    "android.provider.Telephony.SMS_EMERGENCY_CB_RECEIVED";
632
633            /**
634             * Broadcast Action: The SIM storage for SMS messages is full.  If
635             * space is not freed, messages targeted for the SIM (class 2) may
636             * not be saved.
637             */
638            @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
639            public static final String SIM_FULL_ACTION =
640                    "android.provider.Telephony.SIM_FULL";
641
642            /**
643             * Broadcast Action: An incoming SMS has been rejected by the
644             * telephony framework.  This intent is sent in lieu of any
645             * of the RECEIVED_ACTION intents.  The intent will have the
646             * following extra value:</p>
647             *
648             * <ul>
649             *   <li><em>result</em> - An int result code, eg,
650             *   <code>{@link #RESULT_SMS_OUT_OF_MEMORY}</code>,
651             *   indicating the error returned to the network.</li>
652             * </ul>
653
654             */
655            @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
656            public static final String SMS_REJECTED_ACTION =
657                "android.provider.Telephony.SMS_REJECTED";
658
659            /**
660             * Read the PDUs out of an {@link #SMS_RECEIVED_ACTION} or a
661             * {@link #DATA_SMS_RECEIVED_ACTION} intent.
662             *
663             * @param intent the intent to read from
664             * @return an array of SmsMessages for the PDUs
665             */
666            public static SmsMessage[] getMessagesFromIntent(
667                    Intent intent) {
668                Object[] messages = (Object[]) intent.getSerializableExtra("pdus");
669                String format = intent.getStringExtra("format");
670                byte[][] pduObjs = new byte[messages.length][];
671
672                for (int i = 0; i < messages.length; i++) {
673                    pduObjs[i] = (byte[]) messages[i];
674                }
675                byte[][] pdus = new byte[pduObjs.length][];
676                int pduCount = pdus.length;
677                SmsMessage[] msgs = new SmsMessage[pduCount];
678                for (int i = 0; i < pduCount; i++) {
679                    pdus[i] = pduObjs[i];
680                    msgs[i] = SmsMessage.createFromPdu(pdus[i], format);
681                }
682                return msgs;
683            }
684        }
685    }
686
687    /**
688     * Base columns for tables that contain MMSs.
689     */
690    public interface BaseMmsColumns extends BaseColumns {
691
692        public static final int MESSAGE_BOX_ALL    = 0;
693        public static final int MESSAGE_BOX_INBOX  = 1;
694        public static final int MESSAGE_BOX_SENT   = 2;
695        public static final int MESSAGE_BOX_DRAFTS = 3;
696        public static final int MESSAGE_BOX_OUTBOX = 4;
697
698        /**
699         * The date the message was received.
700         * <P>Type: INTEGER (long)</P>
701         */
702        public static final String DATE = "date";
703
704        /**
705         * The date the message was sent.
706         * <P>Type: INTEGER (long)</P>
707         */
708        public static final String DATE_SENT = "date_sent";
709
710        /**
711         * The box which the message belong to, for example, MESSAGE_BOX_INBOX.
712         * <P>Type: INTEGER</P>
713         */
714        public static final String MESSAGE_BOX = "msg_box";
715
716        /**
717         * Has the message been read.
718         * <P>Type: INTEGER (boolean)</P>
719         */
720        public static final String READ = "read";
721
722        /**
723         * Indicates whether this message has been seen by the user. The "seen" flag will be
724         * used to figure out whether we need to throw up a statusbar notification or not.
725         */
726        public static final String SEEN = "seen";
727
728        /**
729         * The Message-ID of the message.
730         * <P>Type: TEXT</P>
731         */
732        public static final String MESSAGE_ID = "m_id";
733
734        /**
735         * The subject of the message, if present.
736         * <P>Type: TEXT</P>
737         */
738        public static final String SUBJECT = "sub";
739
740        /**
741         * The character set of the subject, if present.
742         * <P>Type: INTEGER</P>
743         */
744        public static final String SUBJECT_CHARSET = "sub_cs";
745
746        /**
747         * The Content-Type of the message.
748         * <P>Type: TEXT</P>
749         */
750        public static final String CONTENT_TYPE = "ct_t";
751
752        /**
753         * The Content-Location of the message.
754         * <P>Type: TEXT</P>
755         */
756        public static final String CONTENT_LOCATION = "ct_l";
757
758        /**
759         * The address of the sender.
760         * <P>Type: TEXT</P>
761         */
762        public static final String FROM = "from";
763
764        /**
765         * The address of the recipients.
766         * <P>Type: TEXT</P>
767         */
768        public static final String TO = "to";
769
770        /**
771         * The address of the cc. recipients.
772         * <P>Type: TEXT</P>
773         */
774        public static final String CC = "cc";
775
776        /**
777         * The address of the bcc. recipients.
778         * <P>Type: TEXT</P>
779         */
780        public static final String BCC = "bcc";
781
782        /**
783         * The expiry time of the message.
784         * <P>Type: INTEGER</P>
785         */
786        public static final String EXPIRY = "exp";
787
788        /**
789         * The class of the message.
790         * <P>Type: TEXT</P>
791         */
792        public static final String MESSAGE_CLASS = "m_cls";
793
794        /**
795         * The type of the message defined by MMS spec.
796         * <P>Type: INTEGER</P>
797         */
798        public static final String MESSAGE_TYPE = "m_type";
799
800        /**
801         * The version of specification that this message conform.
802         * <P>Type: INTEGER</P>
803         */
804        public static final String MMS_VERSION = "v";
805
806        /**
807         * The size of the message.
808         * <P>Type: INTEGER</P>
809         */
810        public static final String MESSAGE_SIZE = "m_size";
811
812        /**
813         * The priority of the message.
814         * <P>Type: TEXT</P>
815         */
816        public static final String PRIORITY = "pri";
817
818        /**
819         * The read-report of the message.
820         * <P>Type: TEXT</P>
821         */
822        public static final String READ_REPORT = "rr";
823
824        /**
825         * Whether the report is allowed.
826         * <P>Type: TEXT</P>
827         */
828        public static final String REPORT_ALLOWED = "rpt_a";
829
830        /**
831         * The response-status of the message.
832         * <P>Type: INTEGER</P>
833         */
834        public static final String RESPONSE_STATUS = "resp_st";
835
836        /**
837         * The status of the message.
838         * <P>Type: INTEGER</P>
839         */
840        public static final String STATUS = "st";
841
842        /**
843         * The transaction-id of the message.
844         * <P>Type: TEXT</P>
845         */
846        public static final String TRANSACTION_ID = "tr_id";
847
848        /**
849         * The retrieve-status of the message.
850         * <P>Type: INTEGER</P>
851         */
852        public static final String RETRIEVE_STATUS = "retr_st";
853
854        /**
855         * The retrieve-text of the message.
856         * <P>Type: TEXT</P>
857         */
858        public static final String RETRIEVE_TEXT = "retr_txt";
859
860        /**
861         * The character set of the retrieve-text.
862         * <P>Type: TEXT</P>
863         */
864        public static final String RETRIEVE_TEXT_CHARSET = "retr_txt_cs";
865
866        /**
867         * The read-status of the message.
868         * <P>Type: INTEGER</P>
869         */
870        public static final String READ_STATUS = "read_status";
871
872        /**
873         * The content-class of the message.
874         * <P>Type: INTEGER</P>
875         */
876        public static final String CONTENT_CLASS = "ct_cls";
877
878        /**
879         * The delivery-report of the message.
880         * <P>Type: INTEGER</P>
881         */
882        public static final String DELIVERY_REPORT = "d_rpt";
883
884        /**
885         * The delivery-time-token of the message.
886         * <P>Type: INTEGER</P>
887         */
888        public static final String DELIVERY_TIME_TOKEN = "d_tm_tok";
889
890        /**
891         * The delivery-time of the message.
892         * <P>Type: INTEGER</P>
893         */
894        public static final String DELIVERY_TIME = "d_tm";
895
896        /**
897         * The response-text of the message.
898         * <P>Type: TEXT</P>
899         */
900        public static final String RESPONSE_TEXT = "resp_txt";
901
902        /**
903         * The sender-visibility of the message.
904         * <P>Type: TEXT</P>
905         */
906        public static final String SENDER_VISIBILITY = "s_vis";
907
908        /**
909         * The reply-charging of the message.
910         * <P>Type: INTEGER</P>
911         */
912        public static final String REPLY_CHARGING = "r_chg";
913
914        /**
915         * The reply-charging-deadline-token of the message.
916         * <P>Type: INTEGER</P>
917         */
918        public static final String REPLY_CHARGING_DEADLINE_TOKEN = "r_chg_dl_tok";
919
920        /**
921         * The reply-charging-deadline of the message.
922         * <P>Type: INTEGER</P>
923         */
924        public static final String REPLY_CHARGING_DEADLINE = "r_chg_dl";
925
926        /**
927         * The reply-charging-id of the message.
928         * <P>Type: TEXT</P>
929         */
930        public static final String REPLY_CHARGING_ID = "r_chg_id";
931
932        /**
933         * The reply-charging-size of the message.
934         * <P>Type: INTEGER</P>
935         */
936        public static final String REPLY_CHARGING_SIZE = "r_chg_sz";
937
938        /**
939         * The previously-sent-by of the message.
940         * <P>Type: TEXT</P>
941         */
942        public static final String PREVIOUSLY_SENT_BY = "p_s_by";
943
944        /**
945         * The previously-sent-date of the message.
946         * <P>Type: INTEGER</P>
947         */
948        public static final String PREVIOUSLY_SENT_DATE = "p_s_d";
949
950        /**
951         * The store of the message.
952         * <P>Type: TEXT</P>
953         */
954        public static final String STORE = "store";
955
956        /**
957         * The mm-state of the message.
958         * <P>Type: INTEGER</P>
959         */
960        public static final String MM_STATE = "mm_st";
961
962        /**
963         * The mm-flags-token of the message.
964         * <P>Type: INTEGER</P>
965         */
966        public static final String MM_FLAGS_TOKEN = "mm_flg_tok";
967
968        /**
969         * The mm-flags of the message.
970         * <P>Type: TEXT</P>
971         */
972        public static final String MM_FLAGS = "mm_flg";
973
974        /**
975         * The store-status of the message.
976         * <P>Type: TEXT</P>
977         */
978        public static final String STORE_STATUS = "store_st";
979
980        /**
981         * The store-status-text of the message.
982         * <P>Type: TEXT</P>
983         */
984        public static final String STORE_STATUS_TEXT = "store_st_txt";
985
986        /**
987         * The stored of the message.
988         * <P>Type: TEXT</P>
989         */
990        public static final String STORED = "stored";
991
992        /**
993         * The totals of the message.
994         * <P>Type: TEXT</P>
995         */
996        public static final String TOTALS = "totals";
997
998        /**
999         * The mbox-totals of the message.
1000         * <P>Type: TEXT</P>
1001         */
1002        public static final String MBOX_TOTALS = "mb_t";
1003
1004        /**
1005         * The mbox-totals-token of the message.
1006         * <P>Type: INTEGER</P>
1007         */
1008        public static final String MBOX_TOTALS_TOKEN = "mb_t_tok";
1009
1010        /**
1011         * The quotas of the message.
1012         * <P>Type: TEXT</P>
1013         */
1014        public static final String QUOTAS = "qt";
1015
1016        /**
1017         * The mbox-quotas of the message.
1018         * <P>Type: TEXT</P>
1019         */
1020        public static final String MBOX_QUOTAS = "mb_qt";
1021
1022        /**
1023         * The mbox-quotas-token of the message.
1024         * <P>Type: INTEGER</P>
1025         */
1026        public static final String MBOX_QUOTAS_TOKEN = "mb_qt_tok";
1027
1028        /**
1029         * The message-count of the message.
1030         * <P>Type: INTEGER</P>
1031         */
1032        public static final String MESSAGE_COUNT = "m_cnt";
1033
1034        /**
1035         * The start of the message.
1036         * <P>Type: INTEGER</P>
1037         */
1038        public static final String START = "start";
1039
1040        /**
1041         * The distribution-indicator of the message.
1042         * <P>Type: TEXT</P>
1043         */
1044        public static final String DISTRIBUTION_INDICATOR = "d_ind";
1045
1046        /**
1047         * The element-descriptor of the message.
1048         * <P>Type: TEXT</P>
1049         */
1050        public static final String ELEMENT_DESCRIPTOR = "e_des";
1051
1052        /**
1053         * The limit of the message.
1054         * <P>Type: INTEGER</P>
1055         */
1056        public static final String LIMIT = "limit";
1057
1058        /**
1059         * The recommended-retrieval-mode of the message.
1060         * <P>Type: INTEGER</P>
1061         */
1062        public static final String RECOMMENDED_RETRIEVAL_MODE = "r_r_mod";
1063
1064        /**
1065         * The recommended-retrieval-mode-text of the message.
1066         * <P>Type: TEXT</P>
1067         */
1068        public static final String RECOMMENDED_RETRIEVAL_MODE_TEXT = "r_r_mod_txt";
1069
1070        /**
1071         * The status-text of the message.
1072         * <P>Type: TEXT</P>
1073         */
1074        public static final String STATUS_TEXT = "st_txt";
1075
1076        /**
1077         * The applic-id of the message.
1078         * <P>Type: TEXT</P>
1079         */
1080        public static final String APPLIC_ID = "apl_id";
1081
1082        /**
1083         * The reply-applic-id of the message.
1084         * <P>Type: TEXT</P>
1085         */
1086        public static final String REPLY_APPLIC_ID = "r_apl_id";
1087
1088        /**
1089         * The aux-applic-id of the message.
1090         * <P>Type: TEXT</P>
1091         */
1092        public static final String AUX_APPLIC_ID = "aux_apl_id";
1093
1094        /**
1095         * The drm-content of the message.
1096         * <P>Type: TEXT</P>
1097         */
1098        public static final String DRM_CONTENT = "drm_c";
1099
1100        /**
1101         * The adaptation-allowed of the message.
1102         * <P>Type: TEXT</P>
1103         */
1104        public static final String ADAPTATION_ALLOWED = "adp_a";
1105
1106        /**
1107         * The replace-id of the message.
1108         * <P>Type: TEXT</P>
1109         */
1110        public static final String REPLACE_ID = "repl_id";
1111
1112        /**
1113         * The cancel-id of the message.
1114         * <P>Type: TEXT</P>
1115         */
1116        public static final String CANCEL_ID = "cl_id";
1117
1118        /**
1119         * The cancel-status of the message.
1120         * <P>Type: INTEGER</P>
1121         */
1122        public static final String CANCEL_STATUS = "cl_st";
1123
1124        /**
1125         * The thread ID of the message
1126         * <P>Type: INTEGER</P>
1127         */
1128        public static final String THREAD_ID = "thread_id";
1129
1130        /**
1131         * Has the message been locked?
1132         * <P>Type: INTEGER (boolean)</P>
1133         */
1134        public static final String LOCKED = "locked";
1135
1136        /**
1137         * Meta data used externally.
1138         * <P>Type: TEXT</P>
1139         */
1140        public static final String META_DATA = "meta_data";
1141    }
1142
1143    /**
1144     * Columns for the "canonical_addresses" table used by MMS and
1145     * SMS."
1146     */
1147    public interface CanonicalAddressesColumns extends BaseColumns {
1148        /**
1149         * An address used in MMS or SMS.  Email addresses are
1150         * converted to lower case and are compared by string
1151         * equality.  Other addresses are compared using
1152         * PHONE_NUMBERS_EQUAL.
1153         * <P>Type: TEXT</P>
1154         */
1155        public static final String ADDRESS = "address";
1156    }
1157
1158    /**
1159     * Columns for the "threads" table used by MMS and SMS.
1160     */
1161    public interface ThreadsColumns extends BaseColumns {
1162        /**
1163         * The date at which the thread was created.
1164         *
1165         * <P>Type: INTEGER (long)</P>
1166         */
1167        public static final String DATE = "date";
1168
1169        /**
1170         * A string encoding of the recipient IDs of the recipients of
1171         * the message, in numerical order and separated by spaces.
1172         * <P>Type: TEXT</P>
1173         */
1174        public static final String RECIPIENT_IDS = "recipient_ids";
1175
1176        /**
1177         * The message count of the thread.
1178         * <P>Type: INTEGER</P>
1179         */
1180        public static final String MESSAGE_COUNT = "message_count";
1181        /**
1182         * Indicates whether all messages of the thread have been read.
1183         * <P>Type: INTEGER</P>
1184         */
1185        public static final String READ = "read";
1186
1187        /**
1188         * The snippet of the latest message in the thread.
1189         * <P>Type: TEXT</P>
1190         */
1191        public static final String SNIPPET = "snippet";
1192        /**
1193         * The charset of the snippet.
1194         * <P>Type: INTEGER</P>
1195         */
1196        public static final String SNIPPET_CHARSET = "snippet_cs";
1197        /**
1198         * Type of the thread, either Threads.COMMON_THREAD or
1199         * Threads.BROADCAST_THREAD.
1200         * <P>Type: INTEGER</P>
1201         */
1202        public static final String TYPE = "type";
1203        /**
1204         * Indicates whether there is a transmission error in the thread.
1205         * <P>Type: INTEGER</P>
1206         */
1207        public static final String ERROR = "error";
1208        /**
1209         * Indicates whether this thread contains any attachments.
1210         * <P>Type: INTEGER</P>
1211         */
1212        public static final String HAS_ATTACHMENT = "has_attachment";
1213    }
1214
1215    /**
1216     * Helper functions for the "threads" table used by MMS and SMS.
1217     */
1218    public static final class Threads implements ThreadsColumns {
1219        private static final String[] ID_PROJECTION = { BaseColumns._ID };
1220        private static final String STANDARD_ENCODING = "UTF-8";
1221        private static final Uri THREAD_ID_CONTENT_URI = Uri.parse(
1222                "content://mms-sms/threadID");
1223        public static final Uri CONTENT_URI = Uri.withAppendedPath(
1224                MmsSms.CONTENT_URI, "conversations");
1225        public static final Uri OBSOLETE_THREADS_URI = Uri.withAppendedPath(
1226                CONTENT_URI, "obsolete");
1227
1228        public static final int COMMON_THREAD    = 0;
1229        public static final int BROADCAST_THREAD = 1;
1230
1231        // No one should construct an instance of this class.
1232        private Threads() {
1233        }
1234
1235        /**
1236         * This is a single-recipient version of
1237         * getOrCreateThreadId.  It's convenient for use with SMS
1238         * messages.
1239         */
1240        public static long getOrCreateThreadId(Context context, String recipient) {
1241            Set<String> recipients = new HashSet<String>();
1242
1243            recipients.add(recipient);
1244            return getOrCreateThreadId(context, recipients);
1245        }
1246
1247        /**
1248         * Given the recipients list and subject of an unsaved message,
1249         * return its thread ID.  If the message starts a new thread,
1250         * allocate a new thread ID.  Otherwise, use the appropriate
1251         * existing thread ID.
1252         *
1253         * Find the thread ID of the same set of recipients (in
1254         * any order, without any additions). If one
1255         * is found, return it.  Otherwise, return a unique thread ID.
1256         */
1257        public static long getOrCreateThreadId(
1258                Context context, Set<String> recipients) {
1259            Uri.Builder uriBuilder = THREAD_ID_CONTENT_URI.buildUpon();
1260
1261            for (String recipient : recipients) {
1262                if (Mms.isEmailAddress(recipient)) {
1263                    recipient = Mms.extractAddrSpec(recipient);
1264                }
1265
1266                uriBuilder.appendQueryParameter("recipient", recipient);
1267            }
1268
1269            Uri uri = uriBuilder.build();
1270            //if (DEBUG) Log.v(TAG, "getOrCreateThreadId uri: " + uri);
1271
1272            Cursor cursor = SqliteWrapper.query(context, context.getContentResolver(),
1273                    uri, ID_PROJECTION, null, null, null);
1274            if (cursor != null) {
1275                try {
1276                    if (cursor.moveToFirst()) {
1277                        return cursor.getLong(0);
1278                    } else {
1279                        Log.e(TAG, "getOrCreateThreadId returned no rows!");
1280                    }
1281                } finally {
1282                    cursor.close();
1283                }
1284            }
1285
1286            Log.e(TAG, "getOrCreateThreadId failed with uri " + uri.toString());
1287            throw new IllegalArgumentException("Unable to find or allocate a thread ID.");
1288        }
1289    }
1290
1291    /**
1292     * Contains all MMS messages.
1293     */
1294    public static final class Mms implements BaseMmsColumns {
1295        /**
1296         * The content:// style URL for this table
1297         */
1298        public static final Uri CONTENT_URI = Uri.parse("content://mms");
1299
1300        public static final Uri REPORT_REQUEST_URI = Uri.withAppendedPath(
1301                                            CONTENT_URI, "report-request");
1302
1303        public static final Uri REPORT_STATUS_URI = Uri.withAppendedPath(
1304                                            CONTENT_URI, "report-status");
1305
1306        /**
1307         * The default sort order for this table
1308         */
1309        public static final String DEFAULT_SORT_ORDER = "date DESC";
1310
1311        /**
1312         * mailbox         =       name-addr
1313         * name-addr       =       [display-name] angle-addr
1314         * angle-addr      =       [CFWS] "<" addr-spec ">" [CFWS]
1315         */
1316        public static final Pattern NAME_ADDR_EMAIL_PATTERN =
1317                Pattern.compile("\\s*(\"[^\"]*\"|[^<>\"]+)\\s*<([^<>]+)>\\s*");
1318
1319        /**
1320         * quoted-string   =       [CFWS]
1321         *                         DQUOTE *([FWS] qcontent) [FWS] DQUOTE
1322         *                         [CFWS]
1323         */
1324        public static final Pattern QUOTED_STRING_PATTERN =
1325                Pattern.compile("\\s*\"([^\"]*)\"\\s*");
1326
1327        public static final Cursor query(
1328                ContentResolver cr, String[] projection) {
1329            return cr.query(CONTENT_URI, projection, null, null, DEFAULT_SORT_ORDER);
1330        }
1331
1332        public static final Cursor query(
1333                ContentResolver cr, String[] projection,
1334                String where, String orderBy) {
1335            return cr.query(CONTENT_URI, projection,
1336                    where, null, orderBy == null ? DEFAULT_SORT_ORDER : orderBy);
1337        }
1338
1339        public static final String getMessageBoxName(int msgBox) {
1340            switch (msgBox) {
1341                case MESSAGE_BOX_ALL:
1342                    return "all";
1343                case MESSAGE_BOX_INBOX:
1344                    return "inbox";
1345                case MESSAGE_BOX_SENT:
1346                    return "sent";
1347                case MESSAGE_BOX_DRAFTS:
1348                    return "drafts";
1349                case MESSAGE_BOX_OUTBOX:
1350                    return "outbox";
1351                default:
1352                    throw new IllegalArgumentException("Invalid message box: " + msgBox);
1353            }
1354        }
1355
1356        public static String extractAddrSpec(String address) {
1357            Matcher match = NAME_ADDR_EMAIL_PATTERN.matcher(address);
1358
1359            if (match.matches()) {
1360                return match.group(2);
1361            }
1362            return address;
1363        }
1364
1365        /**
1366         * Returns true if the address is an email address
1367         *
1368         * @param address the input address to be tested
1369         * @return true if address is an email address
1370         */
1371        public static boolean isEmailAddress(String address) {
1372            if (TextUtils.isEmpty(address)) {
1373                return false;
1374            }
1375
1376            String s = extractAddrSpec(address);
1377            Matcher match = Patterns.EMAIL_ADDRESS.matcher(s);
1378            return match.matches();
1379        }
1380
1381        /**
1382         * Returns true if the number is a Phone number
1383         *
1384         * @param number the input number to be tested
1385         * @return true if number is a Phone number
1386         */
1387        public static boolean isPhoneNumber(String number) {
1388            if (TextUtils.isEmpty(number)) {
1389                return false;
1390            }
1391
1392            Matcher match = Patterns.PHONE.matcher(number);
1393            return match.matches();
1394        }
1395
1396        /**
1397         * Contains all MMS messages in the MMS app's inbox.
1398         */
1399        public static final class Inbox implements BaseMmsColumns {
1400            /**
1401             * The content:// style URL for this table
1402             */
1403            public static final Uri
1404                    CONTENT_URI = Uri.parse("content://mms/inbox");
1405
1406            /**
1407             * The default sort order for this table
1408             */
1409            public static final String DEFAULT_SORT_ORDER = "date DESC";
1410        }
1411
1412        /**
1413         * Contains all MMS messages in the MMS app's sent box.
1414         */
1415        public static final class Sent implements BaseMmsColumns {
1416            /**
1417             * The content:// style URL for this table
1418             */
1419            public static final Uri
1420                    CONTENT_URI = Uri.parse("content://mms/sent");
1421
1422            /**
1423             * The default sort order for this table
1424             */
1425            public static final String DEFAULT_SORT_ORDER = "date DESC";
1426        }
1427
1428        /**
1429         * Contains all MMS messages in the MMS app's drafts box.
1430         */
1431        public static final class Draft implements BaseMmsColumns {
1432            /**
1433             * The content:// style URL for this table
1434             */
1435            public static final Uri
1436                    CONTENT_URI = Uri.parse("content://mms/drafts");
1437
1438            /**
1439             * The default sort order for this table
1440             */
1441            public static final String DEFAULT_SORT_ORDER = "date DESC";
1442        }
1443
1444        /**
1445         * Contains all MMS messages in the MMS app's outbox.
1446         */
1447        public static final class Outbox implements BaseMmsColumns {
1448            /**
1449             * The content:// style URL for this table
1450             */
1451            public static final Uri
1452                    CONTENT_URI = Uri.parse("content://mms/outbox");
1453
1454            /**
1455             * The default sort order for this table
1456             */
1457            public static final String DEFAULT_SORT_ORDER = "date DESC";
1458        }
1459
1460        public static final class Addr implements BaseColumns {
1461            /**
1462             * The ID of MM which this address entry belongs to.
1463             */
1464            public static final String MSG_ID = "msg_id";
1465
1466            /**
1467             * The ID of contact entry in Phone Book.
1468             */
1469            public static final String CONTACT_ID = "contact_id";
1470
1471            /**
1472             * The address text.
1473             */
1474            public static final String ADDRESS = "address";
1475
1476            /**
1477             * Type of address, must be one of PduHeaders.BCC,
1478             * PduHeaders.CC, PduHeaders.FROM, PduHeaders.TO.
1479             */
1480            public static final String TYPE = "type";
1481
1482            /**
1483             * Character set of this entry.
1484             */
1485            public static final String CHARSET = "charset";
1486        }
1487
1488        public static final class Part implements BaseColumns {
1489            /**
1490             * The identifier of the message which this part belongs to.
1491             * <P>Type: INTEGER</P>
1492             */
1493            public static final String MSG_ID = "mid";
1494
1495            /**
1496             * The order of the part.
1497             * <P>Type: INTEGER</P>
1498             */
1499            public static final String SEQ = "seq";
1500
1501            /**
1502             * The content type of the part.
1503             * <P>Type: TEXT</P>
1504             */
1505            public static final String CONTENT_TYPE = "ct";
1506
1507            /**
1508             * The name of the part.
1509             * <P>Type: TEXT</P>
1510             */
1511            public static final String NAME = "name";
1512
1513            /**
1514             * The charset of the part.
1515             * <P>Type: TEXT</P>
1516             */
1517            public static final String CHARSET = "chset";
1518
1519            /**
1520             * The file name of the part.
1521             * <P>Type: TEXT</P>
1522             */
1523            public static final String FILENAME = "fn";
1524
1525            /**
1526             * The content disposition of the part.
1527             * <P>Type: TEXT</P>
1528             */
1529            public static final String CONTENT_DISPOSITION = "cd";
1530
1531            /**
1532             * The content ID of the part.
1533             * <P>Type: INTEGER</P>
1534             */
1535            public static final String CONTENT_ID = "cid";
1536
1537            /**
1538             * The content location of the part.
1539             * <P>Type: INTEGER</P>
1540             */
1541            public static final String CONTENT_LOCATION = "cl";
1542
1543            /**
1544             * The start of content-type of the message.
1545             * <P>Type: INTEGER</P>
1546             */
1547            public static final String CT_START = "ctt_s";
1548
1549            /**
1550             * The type of content-type of the message.
1551             * <P>Type: TEXT</P>
1552             */
1553            public static final String CT_TYPE = "ctt_t";
1554
1555            /**
1556             * The location(on filesystem) of the binary data of the part.
1557             * <P>Type: INTEGER</P>
1558             */
1559            public static final String _DATA = "_data";
1560
1561            public static final String TEXT = "text";
1562
1563        }
1564
1565        public static final class Rate {
1566            public static final Uri CONTENT_URI = Uri.withAppendedPath(
1567                    Mms.CONTENT_URI, "rate");
1568            /**
1569             * When a message was successfully sent.
1570             * <P>Type: INTEGER</P>
1571             */
1572            public static final String SENT_TIME = "sent_time";
1573        }
1574
1575        public static final class Intents {
1576            private Intents() {
1577                // Non-instantiatable.
1578            }
1579
1580            /**
1581             * The extra field to store the contents of the Intent,
1582             * which should be an array of Uri.
1583             */
1584            public static final String EXTRA_CONTENTS = "contents";
1585            /**
1586             * The extra field to store the type of the contents,
1587             * which should be an array of String.
1588             */
1589            public static final String EXTRA_TYPES    = "types";
1590            /**
1591             * The extra field to store the 'Cc' addresses.
1592             */
1593            public static final String EXTRA_CC       = "cc";
1594            /**
1595             * The extra field to store the 'Bcc' addresses;
1596             */
1597            public static final String EXTRA_BCC      = "bcc";
1598            /**
1599             * The extra field to store the 'Subject'.
1600             */
1601            public static final String EXTRA_SUBJECT  = "subject";
1602            /**
1603             * Indicates that the contents of specified URIs were changed.
1604             * The application which is showing or caching these contents
1605             * should be updated.
1606             */
1607            public static final String
1608            CONTENT_CHANGED_ACTION = "android.intent.action.CONTENT_CHANGED";
1609            /**
1610             * An extra field which stores the URI of deleted contents.
1611             */
1612            public static final String DELETED_CONTENTS = "deleted_contents";
1613        }
1614    }
1615
1616    /**
1617     * Contains all MMS and SMS messages.
1618     */
1619    public static final class MmsSms implements BaseColumns {
1620        /**
1621         * The column to distinguish SMS &amp; MMS messages in query results.
1622         */
1623        public static final String TYPE_DISCRIMINATOR_COLUMN =
1624                "transport_type";
1625
1626        public static final Uri CONTENT_URI = Uri.parse("content://mms-sms/");
1627
1628        public static final Uri CONTENT_CONVERSATIONS_URI = Uri.parse(
1629                "content://mms-sms/conversations");
1630
1631        public static final Uri CONTENT_FILTER_BYPHONE_URI = Uri.parse(
1632                "content://mms-sms/messages/byphone");
1633
1634        public static final Uri CONTENT_UNDELIVERED_URI = Uri.parse(
1635                "content://mms-sms/undelivered");
1636
1637        public static final Uri CONTENT_DRAFT_URI = Uri.parse(
1638                "content://mms-sms/draft");
1639
1640        public static final Uri CONTENT_LOCKED_URI = Uri.parse(
1641                "content://mms-sms/locked");
1642
1643        /***
1644         * Pass in a query parameter called "pattern" which is the text
1645         * to search for.
1646         * The sort order is fixed to be thread_id ASC,date DESC.
1647         */
1648        public static final Uri SEARCH_URI = Uri.parse(
1649                "content://mms-sms/search");
1650
1651        // Constants for message protocol types.
1652        public static final int SMS_PROTO = 0;
1653        public static final int MMS_PROTO = 1;
1654
1655        // Constants for error types of pending messages.
1656        public static final int NO_ERROR                      = 0;
1657        public static final int ERR_TYPE_GENERIC              = 1;
1658        public static final int ERR_TYPE_SMS_PROTO_TRANSIENT  = 2;
1659        public static final int ERR_TYPE_MMS_PROTO_TRANSIENT  = 3;
1660        public static final int ERR_TYPE_TRANSPORT_FAILURE    = 4;
1661        public static final int ERR_TYPE_GENERIC_PERMANENT    = 10;
1662        public static final int ERR_TYPE_SMS_PROTO_PERMANENT  = 11;
1663        public static final int ERR_TYPE_MMS_PROTO_PERMANENT  = 12;
1664
1665        public static final class PendingMessages implements BaseColumns {
1666            public static final Uri CONTENT_URI = Uri.withAppendedPath(
1667                    MmsSms.CONTENT_URI, "pending");
1668            /**
1669             * The type of transport protocol(MMS or SMS).
1670             * <P>Type: INTEGER</P>
1671             */
1672            public static final String PROTO_TYPE = "proto_type";
1673            /**
1674             * The ID of the message to be sent or downloaded.
1675             * <P>Type: INTEGER</P>
1676             */
1677            public static final String MSG_ID = "msg_id";
1678            /**
1679             * The type of the message to be sent or downloaded.
1680             * This field is only valid for MM. For SM, its value is always
1681             * set to 0.
1682             */
1683            public static final String MSG_TYPE = "msg_type";
1684            /**
1685             * The type of the error code.
1686             * <P>Type: INTEGER</P>
1687             */
1688            public static final String ERROR_TYPE = "err_type";
1689            /**
1690             * The error code of sending/retrieving process.
1691             * <P>Type:  INTEGER</P>
1692             */
1693            public static final String ERROR_CODE = "err_code";
1694            /**
1695             * How many times we tried to send or download the message.
1696             * <P>Type:  INTEGER</P>
1697             */
1698            public static final String RETRY_INDEX = "retry_index";
1699            /**
1700             * The time to do next retry.
1701             */
1702            public static final String DUE_TIME = "due_time";
1703            /**
1704             * The time we last tried to send or download the message.
1705             */
1706            public static final String LAST_TRY = "last_try";
1707        }
1708
1709        public static final class WordsTable {
1710            public static final String ID = "_id";
1711            public static final String SOURCE_ROW_ID = "source_id";
1712            public static final String TABLE_ID = "table_to_use";
1713            public static final String INDEXED_TEXT = "index_text";
1714        }
1715    }
1716
1717    public static final class Carriers implements BaseColumns {
1718        /**
1719         * The content:// style URL for this table
1720         */
1721        public static final Uri CONTENT_URI =
1722            Uri.parse("content://telephony/carriers");
1723
1724        /**
1725         * The default sort order for this table
1726         */
1727        public static final String DEFAULT_SORT_ORDER = "name ASC";
1728
1729        public static final String NAME = "name";
1730
1731        public static final String APN = "apn";
1732
1733        public static final String PROXY = "proxy";
1734
1735        public static final String PORT = "port";
1736
1737        public static final String MMSPROXY = "mmsproxy";
1738
1739        public static final String MMSPORT = "mmsport";
1740
1741        public static final String SERVER = "server";
1742
1743        public static final String USER = "user";
1744
1745        public static final String PASSWORD = "password";
1746
1747        public static final String MMSC = "mmsc";
1748
1749        public static final String MCC = "mcc";
1750
1751        public static final String MNC = "mnc";
1752
1753        public static final String NUMERIC = "numeric";
1754
1755        public static final String AUTH_TYPE = "authtype";
1756
1757        public static final String TYPE = "type";
1758
1759        public static final String INACTIVE_TIMER = "inactivetimer";
1760
1761        // Only if enabled try Data Connection.
1762        public static final String ENABLED = "enabled";
1763
1764        // Rules apply based on class.
1765        public static final String CLASS = "class";
1766
1767        /**
1768         * The protocol to be used to connect to this APN.
1769         *
1770         * One of the PDP_type values in TS 27.007 section 10.1.1.
1771         * For example, "IP", "IPV6", "IPV4V6", or "PPP".
1772         */
1773        public static final String PROTOCOL = "protocol";
1774
1775        /**
1776          * The protocol to be used to connect to this APN when roaming.
1777          *
1778          * The syntax is the same as protocol.
1779          */
1780        public static final String ROAMING_PROTOCOL = "roaming_protocol";
1781
1782        public static final String CURRENT = "current";
1783
1784        /**
1785          * Current status of APN
1786          * true : enabled APN, false : disabled APN.
1787          */
1788        public static final String CARRIER_ENABLED = "carrier_enabled";
1789
1790        /**
1791          * Radio Access Technology info
1792          * To check what values can hold, refer to ServiceState.java.
1793          * This should be spread to other technologies,
1794          * but currently only used for LTE(14) and EHRPD(13).
1795          */
1796        public static final String BEARER = "bearer";
1797    }
1798
1799    public static final class Intents {
1800        private Intents() {
1801            // Not instantiable
1802        }
1803
1804        /**
1805         * Broadcast Action: A "secret code" has been entered in the dialer. Secret codes are
1806         * of the form *#*#<code>#*#*. The intent will have the data URI:</p>
1807         *
1808         * <p><code>android_secret_code://&lt;code&gt;</code></p>
1809         */
1810        public static final String SECRET_CODE_ACTION =
1811                "android.provider.Telephony.SECRET_CODE";
1812
1813        /**
1814         * Broadcast Action: The Service Provider string(s) have been updated.  Activities or
1815         * services that use these strings should update their display.
1816         * The intent will have the following extra values:</p>
1817         * <ul>
1818         *   <li><em>showPlmn</em> - Boolean that indicates whether the PLMN should be shown.</li>
1819         *   <li><em>plmn</em> - The operator name of the registered network, as a string.</li>
1820         *   <li><em>showSpn</em> - Boolean that indicates whether the SPN should be shown.</li>
1821         *   <li><em>spn</em> - The service provider name, as a string.</li>
1822         * </ul>
1823         * Note that <em>showPlmn</em> may indicate that <em>plmn</em> should be displayed, even
1824         * though the value for <em>plmn</em> is null.  This can happen, for example, if the phone
1825         * has not registered to a network yet.  In this case the receiver may substitute an
1826         * appropriate placeholder string (eg, "No service").
1827         *
1828         * It is recommended to display <em>plmn</em> before / above <em>spn</em> if
1829         * both are displayed.
1830         *
1831         * <p>Note this is a protected intent that can only be sent
1832         * by the system.
1833         */
1834        public static final String SPN_STRINGS_UPDATED_ACTION =
1835                "android.provider.Telephony.SPN_STRINGS_UPDATED";
1836
1837        public static final String EXTRA_SHOW_PLMN  = "showPlmn";
1838        public static final String EXTRA_PLMN       = "plmn";
1839        public static final String EXTRA_SHOW_SPN   = "showSpn";
1840        public static final String EXTRA_SPN        = "spn";
1841    }
1842}
1843