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