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 = 32;
118        public static final int STATUS_FAILED = 64;
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[] of 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: A new Cell Broadcast message has been received
580             * by the device. The intent will have the following extra
581             * values:</p>
582             *
583             * <ul>
584             *   <li><em>pdus</em> - An Object[] of byte[]s containing the PDUs
585             *   that make up the message.</li>
586             * </ul>
587             *
588             * <p>The extra values can be extracted using
589             * {@link #getMessagesFromIntent(Intent)}.</p>
590             *
591             * <p>If a BroadcastReceiver encounters an error while processing
592             * this intent it should set the result code appropriately.</p>
593             */
594            @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
595            public static final String SMS_CB_RECEIVED_ACTION =
596                    "android.provider.Telephony.SMS_CB_RECEIVED";
597
598            /**
599             * Broadcast Action: A new Emergency Broadcast message has been received
600             * by the device. The intent will have the following extra
601             * values:</p>
602             *
603             * <ul>
604             *   <li><em>pdus</em> - An Object[] of byte[]s containing the PDUs
605             *   that make up the message.</li>
606             * </ul>
607             *
608             * <p>The extra values can be extracted using
609             * {@link #getMessagesFromIntent(Intent)}.</p>
610             *
611             * <p>If a BroadcastReceiver encounters an error while processing
612             * this intent it should set the result code appropriately.</p>
613             */
614            @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
615            public static final String SMS_EMERGENCY_CB_RECEIVED_ACTION =
616                    "android.provider.Telephony.SMS_EMERGENCY_CB_RECEIVED";
617
618            /**
619             * Broadcast Action: The SIM storage for SMS messages is full.  If
620             * space is not freed, messages targeted for the SIM (class 2) may
621             * not be saved.
622             */
623            @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
624            public static final String SIM_FULL_ACTION =
625                "android.provider.Telephony.SIM_FULL";
626
627            /**
628             * Broadcast Action: An incoming SMS has been rejected by the
629             * telephony framework.  This intent is sent in lieu of any
630             * of the RECEIVED_ACTION intents.  The intent will have the
631             * following extra value:</p>
632             *
633             * <ul>
634             *   <li><em>result</em> - An int result code, eg,
635             *   <code>{@link #RESULT_SMS_OUT_OF_MEMORY}</code>,
636             *   indicating the error returned to the network.</li>
637             * </ul>
638
639             */
640            @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
641            public static final String SMS_REJECTED_ACTION =
642                "android.provider.Telephony.SMS_REJECTED";
643
644            /**
645             * Read the PDUs out of an {@link #SMS_RECEIVED_ACTION} or a
646             * {@link #DATA_SMS_RECEIVED_ACTION} intent.
647             *
648             * @param intent the intent to read from
649             * @return an array of SmsMessages for the PDUs
650             */
651            public static SmsMessage[] getMessagesFromIntent(
652                    Intent intent) {
653                Object[] messages = (Object[]) intent.getSerializableExtra("pdus");
654                byte[][] pduObjs = new byte[messages.length][];
655
656                for (int i = 0; i < messages.length; i++) {
657                    pduObjs[i] = (byte[]) messages[i];
658                }
659                byte[][] pdus = new byte[pduObjs.length][];
660                int pduCount = pdus.length;
661                SmsMessage[] msgs = new SmsMessage[pduCount];
662                for (int i = 0; i < pduCount; i++) {
663                    pdus[i] = pduObjs[i];
664                    msgs[i] = SmsMessage.createFromPdu(pdus[i]);
665                }
666                return msgs;
667            }
668        }
669    }
670
671    /**
672     * Base columns for tables that contain MMSs.
673     */
674    public interface BaseMmsColumns extends BaseColumns {
675
676        public static final int MESSAGE_BOX_ALL    = 0;
677        public static final int MESSAGE_BOX_INBOX  = 1;
678        public static final int MESSAGE_BOX_SENT   = 2;
679        public static final int MESSAGE_BOX_DRAFTS = 3;
680        public static final int MESSAGE_BOX_OUTBOX = 4;
681
682        /**
683         * The date the message was sent.
684         * <P>Type: INTEGER (long)</P>
685         */
686        public static final String DATE = "date";
687
688        /**
689         * The box which the message belong to, for example, MESSAGE_BOX_INBOX.
690         * <P>Type: INTEGER</P>
691         */
692        public static final String MESSAGE_BOX = "msg_box";
693
694        /**
695         * Has the message been read.
696         * <P>Type: INTEGER (boolean)</P>
697         */
698        public static final String READ = "read";
699
700        /**
701         * Indicates whether this message has been seen by the user. The "seen" flag will be
702         * used to figure out whether we need to throw up a statusbar notification or not.
703         */
704        public static final String SEEN = "seen";
705
706        /**
707         * The Message-ID of the message.
708         * <P>Type: TEXT</P>
709         */
710        public static final String MESSAGE_ID = "m_id";
711
712        /**
713         * The subject of the message, if present.
714         * <P>Type: TEXT</P>
715         */
716        public static final String SUBJECT = "sub";
717
718        /**
719         * The character set of the subject, if present.
720         * <P>Type: INTEGER</P>
721         */
722        public static final String SUBJECT_CHARSET = "sub_cs";
723
724        /**
725         * The Content-Type of the message.
726         * <P>Type: TEXT</P>
727         */
728        public static final String CONTENT_TYPE = "ct_t";
729
730        /**
731         * The Content-Location of the message.
732         * <P>Type: TEXT</P>
733         */
734        public static final String CONTENT_LOCATION = "ct_l";
735
736        /**
737         * The address of the sender.
738         * <P>Type: TEXT</P>
739         */
740        public static final String FROM = "from";
741
742        /**
743         * The address of the recipients.
744         * <P>Type: TEXT</P>
745         */
746        public static final String TO = "to";
747
748        /**
749         * The address of the cc. recipients.
750         * <P>Type: TEXT</P>
751         */
752        public static final String CC = "cc";
753
754        /**
755         * The address of the bcc. recipients.
756         * <P>Type: TEXT</P>
757         */
758        public static final String BCC = "bcc";
759
760        /**
761         * The expiry time of the message.
762         * <P>Type: INTEGER</P>
763         */
764        public static final String EXPIRY = "exp";
765
766        /**
767         * The class of the message.
768         * <P>Type: TEXT</P>
769         */
770        public static final String MESSAGE_CLASS = "m_cls";
771
772        /**
773         * The type of the message defined by MMS spec.
774         * <P>Type: INTEGER</P>
775         */
776        public static final String MESSAGE_TYPE = "m_type";
777
778        /**
779         * The version of specification that this message conform.
780         * <P>Type: INTEGER</P>
781         */
782        public static final String MMS_VERSION = "v";
783
784        /**
785         * The size of the message.
786         * <P>Type: INTEGER</P>
787         */
788        public static final String MESSAGE_SIZE = "m_size";
789
790        /**
791         * The priority of the message.
792         * <P>Type: TEXT</P>
793         */
794        public static final String PRIORITY = "pri";
795
796        /**
797         * The read-report of the message.
798         * <P>Type: TEXT</P>
799         */
800        public static final String READ_REPORT = "rr";
801
802        /**
803         * Whether the report is allowed.
804         * <P>Type: TEXT</P>
805         */
806        public static final String REPORT_ALLOWED = "rpt_a";
807
808        /**
809         * The response-status of the message.
810         * <P>Type: INTEGER</P>
811         */
812        public static final String RESPONSE_STATUS = "resp_st";
813
814        /**
815         * The status of the message.
816         * <P>Type: INTEGER</P>
817         */
818        public static final String STATUS = "st";
819
820        /**
821         * The transaction-id of the message.
822         * <P>Type: TEXT</P>
823         */
824        public static final String TRANSACTION_ID = "tr_id";
825
826        /**
827         * The retrieve-status of the message.
828         * <P>Type: INTEGER</P>
829         */
830        public static final String RETRIEVE_STATUS = "retr_st";
831
832        /**
833         * The retrieve-text of the message.
834         * <P>Type: TEXT</P>
835         */
836        public static final String RETRIEVE_TEXT = "retr_txt";
837
838        /**
839         * The character set of the retrieve-text.
840         * <P>Type: TEXT</P>
841         */
842        public static final String RETRIEVE_TEXT_CHARSET = "retr_txt_cs";
843
844        /**
845         * The read-status of the message.
846         * <P>Type: INTEGER</P>
847         */
848        public static final String READ_STATUS = "read_status";
849
850        /**
851         * The content-class of the message.
852         * <P>Type: INTEGER</P>
853         */
854        public static final String CONTENT_CLASS = "ct_cls";
855
856        /**
857         * The delivery-report of the message.
858         * <P>Type: INTEGER</P>
859         */
860        public static final String DELIVERY_REPORT = "d_rpt";
861
862        /**
863         * The delivery-time-token of the message.
864         * <P>Type: INTEGER</P>
865         */
866        public static final String DELIVERY_TIME_TOKEN = "d_tm_tok";
867
868        /**
869         * The delivery-time of the message.
870         * <P>Type: INTEGER</P>
871         */
872        public static final String DELIVERY_TIME = "d_tm";
873
874        /**
875         * The response-text of the message.
876         * <P>Type: TEXT</P>
877         */
878        public static final String RESPONSE_TEXT = "resp_txt";
879
880        /**
881         * The sender-visibility of the message.
882         * <P>Type: TEXT</P>
883         */
884        public static final String SENDER_VISIBILITY = "s_vis";
885
886        /**
887         * The reply-charging of the message.
888         * <P>Type: INTEGER</P>
889         */
890        public static final String REPLY_CHARGING = "r_chg";
891
892        /**
893         * The reply-charging-deadline-token of the message.
894         * <P>Type: INTEGER</P>
895         */
896        public static final String REPLY_CHARGING_DEADLINE_TOKEN = "r_chg_dl_tok";
897
898        /**
899         * The reply-charging-deadline of the message.
900         * <P>Type: INTEGER</P>
901         */
902        public static final String REPLY_CHARGING_DEADLINE = "r_chg_dl";
903
904        /**
905         * The reply-charging-id of the message.
906         * <P>Type: TEXT</P>
907         */
908        public static final String REPLY_CHARGING_ID = "r_chg_id";
909
910        /**
911         * The reply-charging-size of the message.
912         * <P>Type: INTEGER</P>
913         */
914        public static final String REPLY_CHARGING_SIZE = "r_chg_sz";
915
916        /**
917         * The previously-sent-by of the message.
918         * <P>Type: TEXT</P>
919         */
920        public static final String PREVIOUSLY_SENT_BY = "p_s_by";
921
922        /**
923         * The previously-sent-date of the message.
924         * <P>Type: INTEGER</P>
925         */
926        public static final String PREVIOUSLY_SENT_DATE = "p_s_d";
927
928        /**
929         * The store of the message.
930         * <P>Type: TEXT</P>
931         */
932        public static final String STORE = "store";
933
934        /**
935         * The mm-state of the message.
936         * <P>Type: INTEGER</P>
937         */
938        public static final String MM_STATE = "mm_st";
939
940        /**
941         * The mm-flags-token of the message.
942         * <P>Type: INTEGER</P>
943         */
944        public static final String MM_FLAGS_TOKEN = "mm_flg_tok";
945
946        /**
947         * The mm-flags of the message.
948         * <P>Type: TEXT</P>
949         */
950        public static final String MM_FLAGS = "mm_flg";
951
952        /**
953         * The store-status of the message.
954         * <P>Type: TEXT</P>
955         */
956        public static final String STORE_STATUS = "store_st";
957
958        /**
959         * The store-status-text of the message.
960         * <P>Type: TEXT</P>
961         */
962        public static final String STORE_STATUS_TEXT = "store_st_txt";
963
964        /**
965         * The stored of the message.
966         * <P>Type: TEXT</P>
967         */
968        public static final String STORED = "stored";
969
970        /**
971         * The totals of the message.
972         * <P>Type: TEXT</P>
973         */
974        public static final String TOTALS = "totals";
975
976        /**
977         * The mbox-totals of the message.
978         * <P>Type: TEXT</P>
979         */
980        public static final String MBOX_TOTALS = "mb_t";
981
982        /**
983         * The mbox-totals-token of the message.
984         * <P>Type: INTEGER</P>
985         */
986        public static final String MBOX_TOTALS_TOKEN = "mb_t_tok";
987
988        /**
989         * The quotas of the message.
990         * <P>Type: TEXT</P>
991         */
992        public static final String QUOTAS = "qt";
993
994        /**
995         * The mbox-quotas of the message.
996         * <P>Type: TEXT</P>
997         */
998        public static final String MBOX_QUOTAS = "mb_qt";
999
1000        /**
1001         * The mbox-quotas-token of the message.
1002         * <P>Type: INTEGER</P>
1003         */
1004        public static final String MBOX_QUOTAS_TOKEN = "mb_qt_tok";
1005
1006        /**
1007         * The message-count of the message.
1008         * <P>Type: INTEGER</P>
1009         */
1010        public static final String MESSAGE_COUNT = "m_cnt";
1011
1012        /**
1013         * The start of the message.
1014         * <P>Type: INTEGER</P>
1015         */
1016        public static final String START = "start";
1017
1018        /**
1019         * The distribution-indicator of the message.
1020         * <P>Type: TEXT</P>
1021         */
1022        public static final String DISTRIBUTION_INDICATOR = "d_ind";
1023
1024        /**
1025         * The element-descriptor of the message.
1026         * <P>Type: TEXT</P>
1027         */
1028        public static final String ELEMENT_DESCRIPTOR = "e_des";
1029
1030        /**
1031         * The limit of the message.
1032         * <P>Type: INTEGER</P>
1033         */
1034        public static final String LIMIT = "limit";
1035
1036        /**
1037         * The recommended-retrieval-mode of the message.
1038         * <P>Type: INTEGER</P>
1039         */
1040        public static final String RECOMMENDED_RETRIEVAL_MODE = "r_r_mod";
1041
1042        /**
1043         * The recommended-retrieval-mode-text of the message.
1044         * <P>Type: TEXT</P>
1045         */
1046        public static final String RECOMMENDED_RETRIEVAL_MODE_TEXT = "r_r_mod_txt";
1047
1048        /**
1049         * The status-text of the message.
1050         * <P>Type: TEXT</P>
1051         */
1052        public static final String STATUS_TEXT = "st_txt";
1053
1054        /**
1055         * The applic-id of the message.
1056         * <P>Type: TEXT</P>
1057         */
1058        public static final String APPLIC_ID = "apl_id";
1059
1060        /**
1061         * The reply-applic-id of the message.
1062         * <P>Type: TEXT</P>
1063         */
1064        public static final String REPLY_APPLIC_ID = "r_apl_id";
1065
1066        /**
1067         * The aux-applic-id of the message.
1068         * <P>Type: TEXT</P>
1069         */
1070        public static final String AUX_APPLIC_ID = "aux_apl_id";
1071
1072        /**
1073         * The drm-content of the message.
1074         * <P>Type: TEXT</P>
1075         */
1076        public static final String DRM_CONTENT = "drm_c";
1077
1078        /**
1079         * The adaptation-allowed of the message.
1080         * <P>Type: TEXT</P>
1081         */
1082        public static final String ADAPTATION_ALLOWED = "adp_a";
1083
1084        /**
1085         * The replace-id of the message.
1086         * <P>Type: TEXT</P>
1087         */
1088        public static final String REPLACE_ID = "repl_id";
1089
1090        /**
1091         * The cancel-id of the message.
1092         * <P>Type: TEXT</P>
1093         */
1094        public static final String CANCEL_ID = "cl_id";
1095
1096        /**
1097         * The cancel-status of the message.
1098         * <P>Type: INTEGER</P>
1099         */
1100        public static final String CANCEL_STATUS = "cl_st";
1101
1102        /**
1103         * The thread ID of the message
1104         * <P>Type: INTEGER</P>
1105         */
1106        public static final String THREAD_ID = "thread_id";
1107
1108        /**
1109         * Has the message been locked?
1110         * <P>Type: INTEGER (boolean)</P>
1111         */
1112        public static final String LOCKED = "locked";
1113
1114        /**
1115         * Meta data used externally.
1116         * <P>Type: TEXT</P>
1117         */
1118        public static final String META_DATA = "meta_data";
1119    }
1120
1121    /**
1122     * Columns for the "canonical_addresses" table used by MMS and
1123     * SMS."
1124     */
1125    public interface CanonicalAddressesColumns extends BaseColumns {
1126        /**
1127         * An address used in MMS or SMS.  Email addresses are
1128         * converted to lower case and are compared by string
1129         * equality.  Other addresses are compared using
1130         * PHONE_NUMBERS_EQUAL.
1131         * <P>Type: TEXT</P>
1132         */
1133        public static final String ADDRESS = "address";
1134    }
1135
1136    /**
1137     * Columns for the "threads" table used by MMS and SMS.
1138     */
1139    public interface ThreadsColumns extends BaseColumns {
1140        /**
1141         * The date at which the thread was created.
1142         *
1143         * <P>Type: INTEGER (long)</P>
1144         */
1145        public static final String DATE = "date";
1146
1147        /**
1148         * A string encoding of the recipient IDs of the recipients of
1149         * the message, in numerical order and separated by spaces.
1150         * <P>Type: TEXT</P>
1151         */
1152        public static final String RECIPIENT_IDS = "recipient_ids";
1153
1154        /**
1155         * The message count of the thread.
1156         * <P>Type: INTEGER</P>
1157         */
1158        public static final String MESSAGE_COUNT = "message_count";
1159        /**
1160         * Indicates whether all messages of the thread have been read.
1161         * <P>Type: INTEGER</P>
1162         */
1163        public static final String READ = "read";
1164
1165        /**
1166         * The snippet of the latest message in the thread.
1167         * <P>Type: TEXT</P>
1168         */
1169        public static final String SNIPPET = "snippet";
1170        /**
1171         * The charset of the snippet.
1172         * <P>Type: INTEGER</P>
1173         */
1174        public static final String SNIPPET_CHARSET = "snippet_cs";
1175        /**
1176         * Type of the thread, either Threads.COMMON_THREAD or
1177         * Threads.BROADCAST_THREAD.
1178         * <P>Type: INTEGER</P>
1179         */
1180        public static final String TYPE = "type";
1181        /**
1182         * Indicates whether there is a transmission error in the thread.
1183         * <P>Type: INTEGER</P>
1184         */
1185        public static final String ERROR = "error";
1186        /**
1187         * Indicates whether this thread contains any attachments.
1188         * <P>Type: INTEGER</P>
1189         */
1190        public static final String HAS_ATTACHMENT = "has_attachment";
1191    }
1192
1193    /**
1194     * Helper functions for the "threads" table used by MMS and SMS.
1195     */
1196    public static final class Threads implements ThreadsColumns {
1197        private static final String[] ID_PROJECTION = { BaseColumns._ID };
1198        private static final String STANDARD_ENCODING = "UTF-8";
1199        private static final Uri THREAD_ID_CONTENT_URI = Uri.parse(
1200                "content://mms-sms/threadID");
1201        public static final Uri CONTENT_URI = Uri.withAppendedPath(
1202                MmsSms.CONTENT_URI, "conversations");
1203        public static final Uri OBSOLETE_THREADS_URI = Uri.withAppendedPath(
1204                CONTENT_URI, "obsolete");
1205
1206        public static final int COMMON_THREAD    = 0;
1207        public static final int BROADCAST_THREAD = 1;
1208
1209        // No one should construct an instance of this class.
1210        private Threads() {
1211        }
1212
1213        /**
1214         * This is a single-recipient version of
1215         * getOrCreateThreadId.  It's convenient for use with SMS
1216         * messages.
1217         */
1218        public static long getOrCreateThreadId(Context context, String recipient) {
1219            Set<String> recipients = new HashSet<String>();
1220
1221            recipients.add(recipient);
1222            return getOrCreateThreadId(context, recipients);
1223        }
1224
1225        /**
1226         * Given the recipients list and subject of an unsaved message,
1227         * return its thread ID.  If the message starts a new thread,
1228         * allocate a new thread ID.  Otherwise, use the appropriate
1229         * existing thread ID.
1230         *
1231         * Find the thread ID of the same set of recipients (in
1232         * any order, without any additions). If one
1233         * is found, return it.  Otherwise, return a unique thread ID.
1234         */
1235        public static long getOrCreateThreadId(
1236                Context context, Set<String> recipients) {
1237            Uri.Builder uriBuilder = THREAD_ID_CONTENT_URI.buildUpon();
1238
1239            for (String recipient : recipients) {
1240                if (Mms.isEmailAddress(recipient)) {
1241                    recipient = Mms.extractAddrSpec(recipient);
1242                }
1243
1244                uriBuilder.appendQueryParameter("recipient", recipient);
1245            }
1246
1247            Uri uri = uriBuilder.build();
1248            //if (DEBUG) Log.v(TAG, "getOrCreateThreadId uri: " + uri);
1249
1250            Cursor cursor = SqliteWrapper.query(context, context.getContentResolver(),
1251                    uri, ID_PROJECTION, null, null, null);
1252            if (DEBUG) {
1253                Log.v(TAG, "getOrCreateThreadId cursor cnt: " + cursor.getCount());
1254            }
1255            if (cursor != null) {
1256                try {
1257                    if (cursor.moveToFirst()) {
1258                        return cursor.getLong(0);
1259                    } else {
1260                        Log.e(TAG, "getOrCreateThreadId returned no rows!");
1261                    }
1262                } finally {
1263                    cursor.close();
1264                }
1265            }
1266
1267            Log.e(TAG, "getOrCreateThreadId failed with uri " + uri.toString());
1268            throw new IllegalArgumentException("Unable to find or allocate a thread ID.");
1269        }
1270    }
1271
1272    /**
1273     * Contains all MMS messages.
1274     */
1275    public static final class Mms implements BaseMmsColumns {
1276        /**
1277         * The content:// style URL for this table
1278         */
1279        public static final Uri CONTENT_URI = Uri.parse("content://mms");
1280
1281        public static final Uri REPORT_REQUEST_URI = Uri.withAppendedPath(
1282                                            CONTENT_URI, "report-request");
1283
1284        public static final Uri REPORT_STATUS_URI = Uri.withAppendedPath(
1285                                            CONTENT_URI, "report-status");
1286
1287        /**
1288         * The default sort order for this table
1289         */
1290        public static final String DEFAULT_SORT_ORDER = "date DESC";
1291
1292        /**
1293         * mailbox         =       name-addr
1294         * name-addr       =       [display-name] angle-addr
1295         * angle-addr      =       [CFWS] "<" addr-spec ">" [CFWS]
1296         */
1297        public static final Pattern NAME_ADDR_EMAIL_PATTERN =
1298                Pattern.compile("\\s*(\"[^\"]*\"|[^<>\"]+)\\s*<([^<>]+)>\\s*");
1299
1300        /**
1301         * quoted-string   =       [CFWS]
1302         *                         DQUOTE *([FWS] qcontent) [FWS] DQUOTE
1303         *                         [CFWS]
1304         */
1305        public static final Pattern QUOTED_STRING_PATTERN =
1306                Pattern.compile("\\s*\"([^\"]*)\"\\s*");
1307
1308        public static final Cursor query(
1309                ContentResolver cr, String[] projection) {
1310            return cr.query(CONTENT_URI, projection, null, null, DEFAULT_SORT_ORDER);
1311        }
1312
1313        public static final Cursor query(
1314                ContentResolver cr, String[] projection,
1315                String where, String orderBy) {
1316            return cr.query(CONTENT_URI, projection,
1317                    where, null, orderBy == null ? DEFAULT_SORT_ORDER : orderBy);
1318        }
1319
1320        public static final String getMessageBoxName(int msgBox) {
1321            switch (msgBox) {
1322                case MESSAGE_BOX_ALL:
1323                    return "all";
1324                case MESSAGE_BOX_INBOX:
1325                    return "inbox";
1326                case MESSAGE_BOX_SENT:
1327                    return "sent";
1328                case MESSAGE_BOX_DRAFTS:
1329                    return "drafts";
1330                case MESSAGE_BOX_OUTBOX:
1331                    return "outbox";
1332                default:
1333                    throw new IllegalArgumentException("Invalid message box: " + msgBox);
1334            }
1335        }
1336
1337        public static String extractAddrSpec(String address) {
1338            Matcher match = NAME_ADDR_EMAIL_PATTERN.matcher(address);
1339
1340            if (match.matches()) {
1341                return match.group(2);
1342            }
1343            return address;
1344        }
1345
1346        /**
1347         * Returns true if the address is an email address
1348         *
1349         * @param address the input address to be tested
1350         * @return true if address is an email address
1351         */
1352        public static boolean isEmailAddress(String address) {
1353            if (TextUtils.isEmpty(address)) {
1354                return false;
1355            }
1356
1357            String s = extractAddrSpec(address);
1358            Matcher match = Patterns.EMAIL_ADDRESS.matcher(s);
1359            return match.matches();
1360        }
1361
1362        /**
1363         * Returns true if the number is a Phone number
1364         *
1365         * @param number the input number to be tested
1366         * @return true if number is a Phone number
1367         */
1368        public static boolean isPhoneNumber(String number) {
1369            if (TextUtils.isEmpty(number)) {
1370                return false;
1371            }
1372
1373            Matcher match = Patterns.PHONE.matcher(number);
1374            return match.matches();
1375        }
1376
1377        /**
1378         * Contains all MMS messages in the MMS app's inbox.
1379         */
1380        public static final class Inbox implements BaseMmsColumns {
1381            /**
1382             * The content:// style URL for this table
1383             */
1384            public static final Uri
1385                    CONTENT_URI = Uri.parse("content://mms/inbox");
1386
1387            /**
1388             * The default sort order for this table
1389             */
1390            public static final String DEFAULT_SORT_ORDER = "date DESC";
1391        }
1392
1393        /**
1394         * Contains all MMS messages in the MMS app's sent box.
1395         */
1396        public static final class Sent implements BaseMmsColumns {
1397            /**
1398             * The content:// style URL for this table
1399             */
1400            public static final Uri
1401                    CONTENT_URI = Uri.parse("content://mms/sent");
1402
1403            /**
1404             * The default sort order for this table
1405             */
1406            public static final String DEFAULT_SORT_ORDER = "date DESC";
1407        }
1408
1409        /**
1410         * Contains all MMS messages in the MMS app's drafts box.
1411         */
1412        public static final class Draft implements BaseMmsColumns {
1413            /**
1414             * The content:// style URL for this table
1415             */
1416            public static final Uri
1417                    CONTENT_URI = Uri.parse("content://mms/drafts");
1418
1419            /**
1420             * The default sort order for this table
1421             */
1422            public static final String DEFAULT_SORT_ORDER = "date DESC";
1423        }
1424
1425        /**
1426         * Contains all MMS messages in the MMS app's outbox.
1427         */
1428        public static final class Outbox implements BaseMmsColumns {
1429            /**
1430             * The content:// style URL for this table
1431             */
1432            public static final Uri
1433                    CONTENT_URI = Uri.parse("content://mms/outbox");
1434
1435            /**
1436             * The default sort order for this table
1437             */
1438            public static final String DEFAULT_SORT_ORDER = "date DESC";
1439        }
1440
1441        public static final class Addr implements BaseColumns {
1442            /**
1443             * The ID of MM which this address entry belongs to.
1444             */
1445            public static final String MSG_ID = "msg_id";
1446
1447            /**
1448             * The ID of contact entry in Phone Book.
1449             */
1450            public static final String CONTACT_ID = "contact_id";
1451
1452            /**
1453             * The address text.
1454             */
1455            public static final String ADDRESS = "address";
1456
1457            /**
1458             * Type of address, must be one of PduHeaders.BCC,
1459             * PduHeaders.CC, PduHeaders.FROM, PduHeaders.TO.
1460             */
1461            public static final String TYPE = "type";
1462
1463            /**
1464             * Character set of this entry.
1465             */
1466            public static final String CHARSET = "charset";
1467        }
1468
1469        public static final class Part implements BaseColumns {
1470            /**
1471             * The identifier of the message which this part belongs to.
1472             * <P>Type: INTEGER</P>
1473             */
1474            public static final String MSG_ID = "mid";
1475
1476            /**
1477             * The order of the part.
1478             * <P>Type: INTEGER</P>
1479             */
1480            public static final String SEQ = "seq";
1481
1482            /**
1483             * The content type of the part.
1484             * <P>Type: TEXT</P>
1485             */
1486            public static final String CONTENT_TYPE = "ct";
1487
1488            /**
1489             * The name of the part.
1490             * <P>Type: TEXT</P>
1491             */
1492            public static final String NAME = "name";
1493
1494            /**
1495             * The charset of the part.
1496             * <P>Type: TEXT</P>
1497             */
1498            public static final String CHARSET = "chset";
1499
1500            /**
1501             * The file name of the part.
1502             * <P>Type: TEXT</P>
1503             */
1504            public static final String FILENAME = "fn";
1505
1506            /**
1507             * The content disposition of the part.
1508             * <P>Type: TEXT</P>
1509             */
1510            public static final String CONTENT_DISPOSITION = "cd";
1511
1512            /**
1513             * The content ID of the part.
1514             * <P>Type: INTEGER</P>
1515             */
1516            public static final String CONTENT_ID = "cid";
1517
1518            /**
1519             * The content location of the part.
1520             * <P>Type: INTEGER</P>
1521             */
1522            public static final String CONTENT_LOCATION = "cl";
1523
1524            /**
1525             * The start of content-type of the message.
1526             * <P>Type: INTEGER</P>
1527             */
1528            public static final String CT_START = "ctt_s";
1529
1530            /**
1531             * The type of content-type of the message.
1532             * <P>Type: TEXT</P>
1533             */
1534            public static final String CT_TYPE = "ctt_t";
1535
1536            /**
1537             * The location(on filesystem) of the binary data of the part.
1538             * <P>Type: INTEGER</P>
1539             */
1540            public static final String _DATA = "_data";
1541
1542            public static final String TEXT = "text";
1543
1544        }
1545
1546        public static final class Rate {
1547            public static final Uri CONTENT_URI = Uri.withAppendedPath(
1548                    Mms.CONTENT_URI, "rate");
1549            /**
1550             * When a message was successfully sent.
1551             * <P>Type: INTEGER</P>
1552             */
1553            public static final String SENT_TIME = "sent_time";
1554        }
1555
1556        public static final class ScrapSpace {
1557            /**
1558             * The content:// style URL for this table
1559             */
1560            public static final Uri CONTENT_URI = Uri.parse("content://mms/scrapSpace");
1561
1562            /**
1563             * This is the scrap file we use to store the media attachment when the user
1564             * chooses to capture a photo to be attached . We pass {#link@Uri} to the Camera app,
1565             * which streams the captured image to the uri. Internally we write the media content
1566             * to this file. It's named '.temp.jpg' so Gallery won't pick it up.
1567             */
1568            public static final String SCRAP_FILE_PATH = "/sdcard/mms/scrapSpace/.temp.jpg";
1569        }
1570
1571        public static final class Intents {
1572            private Intents() {
1573                // Non-instantiatable.
1574            }
1575
1576            /**
1577             * The extra field to store the contents of the Intent,
1578             * which should be an array of Uri.
1579             */
1580            public static final String EXTRA_CONTENTS = "contents";
1581            /**
1582             * The extra field to store the type of the contents,
1583             * which should be an array of String.
1584             */
1585            public static final String EXTRA_TYPES    = "types";
1586            /**
1587             * The extra field to store the 'Cc' addresses.
1588             */
1589            public static final String EXTRA_CC       = "cc";
1590            /**
1591             * The extra field to store the 'Bcc' addresses;
1592             */
1593            public static final String EXTRA_BCC      = "bcc";
1594            /**
1595             * The extra field to store the 'Subject'.
1596             */
1597            public static final String EXTRA_SUBJECT  = "subject";
1598            /**
1599             * Indicates that the contents of specified URIs were changed.
1600             * The application which is showing or caching these contents
1601             * should be updated.
1602             */
1603            public static final String
1604            CONTENT_CHANGED_ACTION = "android.intent.action.CONTENT_CHANGED";
1605            /**
1606             * An extra field which stores the URI of deleted contents.
1607             */
1608            public static final String DELETED_CONTENTS = "deleted_contents";
1609        }
1610    }
1611
1612    /**
1613     * Contains all MMS and SMS messages.
1614     */
1615    public static final class MmsSms implements BaseColumns {
1616        /**
1617         * The column to distinguish SMS &amp; MMS messages in query results.
1618         */
1619        public static final String TYPE_DISCRIMINATOR_COLUMN =
1620                "transport_type";
1621
1622        public static final Uri CONTENT_URI = Uri.parse("content://mms-sms/");
1623
1624        public static final Uri CONTENT_CONVERSATIONS_URI = Uri.parse(
1625                "content://mms-sms/conversations");
1626
1627        public static final Uri CONTENT_FILTER_BYPHONE_URI = Uri.parse(
1628                "content://mms-sms/messages/byphone");
1629
1630        public static final Uri CONTENT_UNDELIVERED_URI = Uri.parse(
1631                "content://mms-sms/undelivered");
1632
1633        public static final Uri CONTENT_DRAFT_URI = Uri.parse(
1634                "content://mms-sms/draft");
1635
1636        public static final Uri CONTENT_LOCKED_URI = Uri.parse(
1637                "content://mms-sms/locked");
1638
1639        /***
1640         * Pass in a query parameter called "pattern" which is the text
1641         * to search for.
1642         * The sort order is fixed to be thread_id ASC,date DESC.
1643         */
1644        public static final Uri SEARCH_URI = Uri.parse(
1645                "content://mms-sms/search");
1646
1647        // Constants for message protocol types.
1648        public static final int SMS_PROTO = 0;
1649        public static final int MMS_PROTO = 1;
1650
1651        // Constants for error types of pending messages.
1652        public static final int NO_ERROR                      = 0;
1653        public static final int ERR_TYPE_GENERIC              = 1;
1654        public static final int ERR_TYPE_SMS_PROTO_TRANSIENT  = 2;
1655        public static final int ERR_TYPE_MMS_PROTO_TRANSIENT  = 3;
1656        public static final int ERR_TYPE_TRANSPORT_FAILURE    = 4;
1657        public static final int ERR_TYPE_GENERIC_PERMANENT    = 10;
1658        public static final int ERR_TYPE_SMS_PROTO_PERMANENT  = 11;
1659        public static final int ERR_TYPE_MMS_PROTO_PERMANENT  = 12;
1660
1661        public static final class PendingMessages implements BaseColumns {
1662            public static final Uri CONTENT_URI = Uri.withAppendedPath(
1663                    MmsSms.CONTENT_URI, "pending");
1664            /**
1665             * The type of transport protocol(MMS or SMS).
1666             * <P>Type: INTEGER</P>
1667             */
1668            public static final String PROTO_TYPE = "proto_type";
1669            /**
1670             * The ID of the message to be sent or downloaded.
1671             * <P>Type: INTEGER</P>
1672             */
1673            public static final String MSG_ID = "msg_id";
1674            /**
1675             * The type of the message to be sent or downloaded.
1676             * This field is only valid for MM. For SM, its value is always
1677             * set to 0.
1678             */
1679            public static final String MSG_TYPE = "msg_type";
1680            /**
1681             * The type of the error code.
1682             * <P>Type: INTEGER</P>
1683             */
1684            public static final String ERROR_TYPE = "err_type";
1685            /**
1686             * The error code of sending/retrieving process.
1687             * <P>Type:  INTEGER</P>
1688             */
1689            public static final String ERROR_CODE = "err_code";
1690            /**
1691             * How many times we tried to send or download the message.
1692             * <P>Type:  INTEGER</P>
1693             */
1694            public static final String RETRY_INDEX = "retry_index";
1695            /**
1696             * The time to do next retry.
1697             */
1698            public static final String DUE_TIME = "due_time";
1699            /**
1700             * The time we last tried to send or download the message.
1701             */
1702            public static final String LAST_TRY = "last_try";
1703        }
1704
1705        public static final class WordsTable {
1706            public static final String ID = "_id";
1707            public static final String SOURCE_ROW_ID = "source_id";
1708            public static final String TABLE_ID = "table_to_use";
1709            public static final String INDEXED_TEXT = "index_text";
1710        }
1711    }
1712
1713    public static final class Carriers implements BaseColumns {
1714        /**
1715         * The content:// style URL for this table
1716         */
1717        public static final Uri CONTENT_URI =
1718            Uri.parse("content://telephony/carriers");
1719
1720        /**
1721         * The default sort order for this table
1722         */
1723        public static final String DEFAULT_SORT_ORDER = "name ASC";
1724
1725        public static final String NAME = "name";
1726
1727        public static final String APN = "apn";
1728
1729        public static final String PROXY = "proxy";
1730
1731        public static final String PORT = "port";
1732
1733        public static final String MMSPROXY = "mmsproxy";
1734
1735        public static final String MMSPORT = "mmsport";
1736
1737        public static final String SERVER = "server";
1738
1739        public static final String USER = "user";
1740
1741        public static final String PASSWORD = "password";
1742
1743        public static final String MMSC = "mmsc";
1744
1745        public static final String MCC = "mcc";
1746
1747        public static final String MNC = "mnc";
1748
1749        public static final String NUMERIC = "numeric";
1750
1751        public static final String AUTH_TYPE = "authtype";
1752
1753        public static final String TYPE = "type";
1754
1755        /**
1756         * The protocol to be used to connect to this APN.
1757         *
1758         * One of the PDP_type values in TS 27.007 section 10.1.1.
1759         * For example, "IP", "IPV6", "IPV4V6", or "PPP".
1760         */
1761        public static final String PROTOCOL = "protocol";
1762
1763        /**
1764          * The protocol to be used to connect to this APN when roaming.
1765          *
1766          * The syntax is the same as protocol.
1767          */
1768        public static final String ROAMING_PROTOCOL = "roaming_protocol";
1769
1770        public static final String CURRENT = "current";
1771    }
1772
1773    public static final class Intents {
1774        private Intents() {
1775            // Not instantiable
1776        }
1777
1778        /**
1779         * Broadcast Action: A "secret code" has been entered in the dialer. Secret codes are
1780         * of the form *#*#<code>#*#*. The intent will have the data URI:</p>
1781         *
1782         * <p><code>android_secret_code://&lt;code&gt;</code></p>
1783         */
1784        public static final String SECRET_CODE_ACTION =
1785                "android.provider.Telephony.SECRET_CODE";
1786
1787        /**
1788         * Broadcast Action: The Service Provider string(s) have been updated.  Activities or
1789         * services that use these strings should update their display.
1790         * The intent will have the following extra values:</p>
1791         * <ul>
1792         *   <li><em>showPlmn</em> - Boolean that indicates whether the PLMN should be shown.</li>
1793         *   <li><em>plmn</em> - The operator name of the registered network, as a string.</li>
1794         *   <li><em>showSpn</em> - Boolean that indicates whether the SPN should be shown.</li>
1795         *   <li><em>spn</em> - The service provider name, as a string.</li>
1796         * </ul>
1797         * Note that <em>showPlmn</em> may indicate that <em>plmn</em> should be displayed, even
1798         * though the value for <em>plmn</em> is null.  This can happen, for example, if the phone
1799         * has not registered to a network yet.  In this case the receiver may substitute an
1800         * appropriate placeholder string (eg, "No service").
1801         *
1802         * It is recommended to display <em>plmn</em> before / above <em>spn</em> if
1803         * both are displayed.
1804         *
1805         * <p>Note this is a protected intent that can only be sent
1806         * by the system.
1807         */
1808        public static final String SPN_STRINGS_UPDATED_ACTION =
1809                "android.provider.Telephony.SPN_STRINGS_UPDATED";
1810
1811        public static final String EXTRA_SHOW_PLMN  = "showPlmn";
1812        public static final String EXTRA_PLMN       = "plmn";
1813        public static final String EXTRA_SHOW_SPN   = "showSpn";
1814        public static final String EXTRA_SPN        = "spn";
1815    }
1816}
1817