Home | History | Annotate | Download | only in provider
      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 
     17 package android.provider;
     18 
     19 import android.annotation.SdkConstant;
     20 import android.annotation.SdkConstant.SdkConstantType;
     21 import android.content.ContentResolver;
     22 import android.content.ContentValues;
     23 import android.content.Context;
     24 import android.content.Intent;
     25 import android.database.Cursor;
     26 import android.database.sqlite.SqliteWrapper;
     27 import android.net.Uri;
     28 import android.telephony.SmsMessage;
     29 import android.text.TextUtils;
     30 import android.util.Config;
     31 import android.util.Log;
     32 import android.util.Patterns;
     33 
     34 
     35 import java.util.HashSet;
     36 import java.util.Set;
     37 import java.util.regex.Matcher;
     38 import java.util.regex.Pattern;
     39 
     40 /**
     41  * The Telephony provider contains data related to phone operation.
     42  *
     43  * @hide
     44  */
     45 public 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) Log.v(TAG, "getOrCreateThreadId uri: " + uri);
   1209 
   1210             Cursor cursor = SqliteWrapper.query(context, context.getContentResolver(),
   1211                     uri, ID_PROJECTION, null, null, null);
   1212             if (DEBUG) {
   1213                 Log.v(TAG, "getOrCreateThreadId cursor cnt: " + cursor.getCount());
   1214             }
   1215             if (cursor != null) {
   1216                 try {
   1217                     if (cursor.moveToFirst()) {
   1218                         return cursor.getLong(0);
   1219                     } else {
   1220                         Log.e(TAG, "getOrCreateThreadId returned no rows!");
   1221                     }
   1222                 } finally {
   1223                     cursor.close();
   1224                 }
   1225             }
   1226 
   1227             Log.e(TAG, "getOrCreateThreadId failed with uri " + uri.toString());
   1228             throw new IllegalArgumentException("Unable to find or allocate a thread ID.");
   1229         }
   1230     }
   1231 
   1232     /**
   1233      * Contains all MMS messages.
   1234      */
   1235     public static final class Mms implements BaseMmsColumns {
   1236         /**
   1237          * The content:// style URL for this table
   1238          */
   1239         public static final Uri CONTENT_URI = Uri.parse("content://mms");
   1240 
   1241         public static final Uri REPORT_REQUEST_URI = Uri.withAppendedPath(
   1242                                             CONTENT_URI, "report-request");
   1243 
   1244         public static final Uri REPORT_STATUS_URI = Uri.withAppendedPath(
   1245                                             CONTENT_URI, "report-status");
   1246 
   1247         /**
   1248          * The default sort order for this table
   1249          */
   1250         public static final String DEFAULT_SORT_ORDER = "date DESC";
   1251 
   1252         /**
   1253          * mailbox         =       name-addr
   1254          * name-addr       =       [display-name] angle-addr
   1255          * angle-addr      =       [CFWS] "<" addr-spec ">" [CFWS]
   1256          */
   1257         public static final Pattern NAME_ADDR_EMAIL_PATTERN =
   1258                 Pattern.compile("\\s*(\"[^\"]*\"|[^<>\"]+)\\s*<([^<>]+)>\\s*");
   1259 
   1260         /**
   1261          * quoted-string   =       [CFWS]
   1262          *                         DQUOTE *([FWS] qcontent) [FWS] DQUOTE
   1263          *                         [CFWS]
   1264          */
   1265         public static final Pattern QUOTED_STRING_PATTERN =
   1266                 Pattern.compile("\\s*\"([^\"]*)\"\\s*");
   1267 
   1268         public static final Cursor query(
   1269                 ContentResolver cr, String[] projection) {
   1270             return cr.query(CONTENT_URI, projection, null, null, DEFAULT_SORT_ORDER);
   1271         }
   1272 
   1273         public static final Cursor query(
   1274                 ContentResolver cr, String[] projection,
   1275                 String where, String orderBy) {
   1276             return cr.query(CONTENT_URI, projection,
   1277                     where, null, orderBy == null ? DEFAULT_SORT_ORDER : orderBy);
   1278         }
   1279 
   1280         public static final String getMessageBoxName(int msgBox) {
   1281             switch (msgBox) {
   1282                 case MESSAGE_BOX_ALL:
   1283                     return "all";
   1284                 case MESSAGE_BOX_INBOX:
   1285                     return "inbox";
   1286                 case MESSAGE_BOX_SENT:
   1287                     return "sent";
   1288                 case MESSAGE_BOX_DRAFTS:
   1289                     return "drafts";
   1290                 case MESSAGE_BOX_OUTBOX:
   1291                     return "outbox";
   1292                 default:
   1293                     throw new IllegalArgumentException("Invalid message box: " + msgBox);
   1294             }
   1295         }
   1296 
   1297         public static String extractAddrSpec(String address) {
   1298             Matcher match = NAME_ADDR_EMAIL_PATTERN.matcher(address);
   1299 
   1300             if (match.matches()) {
   1301                 return match.group(2);
   1302             }
   1303             return address;
   1304         }
   1305 
   1306         /**
   1307          * Returns true if the address is an email address
   1308          *
   1309          * @param address the input address to be tested
   1310          * @return true if address is an email address
   1311          */
   1312         public static boolean isEmailAddress(String address) {
   1313             if (TextUtils.isEmpty(address)) {
   1314                 return false;
   1315             }
   1316 
   1317             String s = extractAddrSpec(address);
   1318             Matcher match = Patterns.EMAIL_ADDRESS.matcher(s);
   1319             return match.matches();
   1320         }
   1321 
   1322         /**
   1323          * Returns true if the number is a Phone number
   1324          *
   1325          * @param number the input number to be tested
   1326          * @return true if number is a Phone number
   1327          */
   1328         public static boolean isPhoneNumber(String number) {
   1329             if (TextUtils.isEmpty(number)) {
   1330                 return false;
   1331             }
   1332 
   1333             Matcher match = Patterns.PHONE.matcher(number);
   1334             return match.matches();
   1335         }
   1336 
   1337         /**
   1338          * Contains all MMS messages in the MMS app's inbox.
   1339          */
   1340         public static final class Inbox implements BaseMmsColumns {
   1341             /**
   1342              * The content:// style URL for this table
   1343              */
   1344             public static final Uri
   1345                     CONTENT_URI = Uri.parse("content://mms/inbox");
   1346 
   1347             /**
   1348              * The default sort order for this table
   1349              */
   1350             public static final String DEFAULT_SORT_ORDER = "date DESC";
   1351         }
   1352 
   1353         /**
   1354          * Contains all MMS messages in the MMS app's sent box.
   1355          */
   1356         public static final class Sent implements BaseMmsColumns {
   1357             /**
   1358              * The content:// style URL for this table
   1359              */
   1360             public static final Uri
   1361                     CONTENT_URI = Uri.parse("content://mms/sent");
   1362 
   1363             /**
   1364              * The default sort order for this table
   1365              */
   1366             public static final String DEFAULT_SORT_ORDER = "date DESC";
   1367         }
   1368 
   1369         /**
   1370          * Contains all MMS messages in the MMS app's drafts box.
   1371          */
   1372         public static final class Draft implements BaseMmsColumns {
   1373             /**
   1374              * The content:// style URL for this table
   1375              */
   1376             public static final Uri
   1377                     CONTENT_URI = Uri.parse("content://mms/drafts");
   1378 
   1379             /**
   1380              * The default sort order for this table
   1381              */
   1382             public static final String DEFAULT_SORT_ORDER = "date DESC";
   1383         }
   1384 
   1385         /**
   1386          * Contains all MMS messages in the MMS app's outbox.
   1387          */
   1388         public static final class Outbox implements BaseMmsColumns {
   1389             /**
   1390              * The content:// style URL for this table
   1391              */
   1392             public static final Uri
   1393                     CONTENT_URI = Uri.parse("content://mms/outbox");
   1394 
   1395             /**
   1396              * The default sort order for this table
   1397              */
   1398             public static final String DEFAULT_SORT_ORDER = "date DESC";
   1399         }
   1400 
   1401         public static final class Addr implements BaseColumns {
   1402             /**
   1403              * The ID of MM which this address entry belongs to.
   1404              */
   1405             public static final String MSG_ID = "msg_id";
   1406 
   1407             /**
   1408              * The ID of contact entry in Phone Book.
   1409              */
   1410             public static final String CONTACT_ID = "contact_id";
   1411 
   1412             /**
   1413              * The address text.
   1414              */
   1415             public static final String ADDRESS = "address";
   1416 
   1417             /**
   1418              * Type of address, must be one of PduHeaders.BCC,
   1419              * PduHeaders.CC, PduHeaders.FROM, PduHeaders.TO.
   1420              */
   1421             public static final String TYPE = "type";
   1422 
   1423             /**
   1424              * Character set of this entry.
   1425              */
   1426             public static final String CHARSET = "charset";
   1427         }
   1428 
   1429         public static final class Part implements BaseColumns {
   1430             /**
   1431              * The identifier of the message which this part belongs to.
   1432              * <P>Type: INTEGER</P>
   1433              */
   1434             public static final String MSG_ID = "mid";
   1435 
   1436             /**
   1437              * The order of the part.
   1438              * <P>Type: INTEGER</P>
   1439              */
   1440             public static final String SEQ = "seq";
   1441 
   1442             /**
   1443              * The content type of the part.
   1444              * <P>Type: TEXT</P>
   1445              */
   1446             public static final String CONTENT_TYPE = "ct";
   1447 
   1448             /**
   1449              * The name of the part.
   1450              * <P>Type: TEXT</P>
   1451              */
   1452             public static final String NAME = "name";
   1453 
   1454             /**
   1455              * The charset of the part.
   1456              * <P>Type: TEXT</P>
   1457              */
   1458             public static final String CHARSET = "chset";
   1459 
   1460             /**
   1461              * The file name of the part.
   1462              * <P>Type: TEXT</P>
   1463              */
   1464             public static final String FILENAME = "fn";
   1465 
   1466             /**
   1467              * The content disposition of the part.
   1468              * <P>Type: TEXT</P>
   1469              */
   1470             public static final String CONTENT_DISPOSITION = "cd";
   1471 
   1472             /**
   1473              * The content ID of the part.
   1474              * <P>Type: INTEGER</P>
   1475              */
   1476             public static final String CONTENT_ID = "cid";
   1477 
   1478             /**
   1479              * The content location of the part.
   1480              * <P>Type: INTEGER</P>
   1481              */
   1482             public static final String CONTENT_LOCATION = "cl";
   1483 
   1484             /**
   1485              * The start of content-type of the message.
   1486              * <P>Type: INTEGER</P>
   1487              */
   1488             public static final String CT_START = "ctt_s";
   1489 
   1490             /**
   1491              * The type of content-type of the message.
   1492              * <P>Type: TEXT</P>
   1493              */
   1494             public static final String CT_TYPE = "ctt_t";
   1495 
   1496             /**
   1497              * The location(on filesystem) of the binary data of the part.
   1498              * <P>Type: INTEGER</P>
   1499              */
   1500             public static final String _DATA = "_data";
   1501 
   1502             public static final String TEXT = "text";
   1503 
   1504         }
   1505 
   1506         public static final class Rate {
   1507             public static final Uri CONTENT_URI = Uri.withAppendedPath(
   1508                     Mms.CONTENT_URI, "rate");
   1509             /**
   1510              * When a message was successfully sent.
   1511              * <P>Type: INTEGER</P>
   1512              */
   1513             public static final String SENT_TIME = "sent_time";
   1514         }
   1515 
   1516         public static final class ScrapSpace {
   1517             /**
   1518              * The content:// style URL for this table
   1519              */
   1520             public static final Uri CONTENT_URI = Uri.parse("content://mms/scrapSpace");
   1521 
   1522             /**
   1523              * This is the scrap file we use to store the media attachment when the user
   1524              * chooses to capture a photo to be attached . We pass {#link@Uri} to the Camera app,
   1525              * which streams the captured image to the uri. Internally we write the media content
   1526              * to this file. It's named '.temp.jpg' so Gallery won't pick it up.
   1527              */
   1528             public static final String SCRAP_FILE_PATH = "/sdcard/mms/scrapSpace/.temp.jpg";
   1529         }
   1530 
   1531         public static final class Intents {
   1532             private Intents() {
   1533                 // Non-instantiatable.
   1534             }
   1535 
   1536             /**
   1537              * The extra field to store the contents of the Intent,
   1538              * which should be an array of Uri.
   1539              */
   1540             public static final String EXTRA_CONTENTS = "contents";
   1541             /**
   1542              * The extra field to store the type of the contents,
   1543              * which should be an array of String.
   1544              */
   1545             public static final String EXTRA_TYPES    = "types";
   1546             /**
   1547              * The extra field to store the 'Cc' addresses.
   1548              */
   1549             public static final String EXTRA_CC       = "cc";
   1550             /**
   1551              * The extra field to store the 'Bcc' addresses;
   1552              */
   1553             public static final String EXTRA_BCC      = "bcc";
   1554             /**
   1555              * The extra field to store the 'Subject'.
   1556              */
   1557             public static final String EXTRA_SUBJECT  = "subject";
   1558             /**
   1559              * Indicates that the contents of specified URIs were changed.
   1560              * The application which is showing or caching these contents
   1561              * should be updated.
   1562              */
   1563             public static final String
   1564             CONTENT_CHANGED_ACTION = "android.intent.action.CONTENT_CHANGED";
   1565             /**
   1566              * An extra field which stores the URI of deleted contents.
   1567              */
   1568             public static final String DELETED_CONTENTS = "deleted_contents";
   1569         }
   1570     }
   1571 
   1572     /**
   1573      * Contains all MMS and SMS messages.
   1574      */
   1575     public static final class MmsSms implements BaseColumns {
   1576         /**
   1577          * The column to distinguish SMS &amp; MMS messages in query results.
   1578          */
   1579         public static final String TYPE_DISCRIMINATOR_COLUMN =
   1580                 "transport_type";
   1581 
   1582         public static final Uri CONTENT_URI = Uri.parse("content://mms-sms/");
   1583 
   1584         public static final Uri CONTENT_CONVERSATIONS_URI = Uri.parse(
   1585                 "content://mms-sms/conversations");
   1586 
   1587         public static final Uri CONTENT_FILTER_BYPHONE_URI = Uri.parse(
   1588                 "content://mms-sms/messages/byphone");
   1589 
   1590         public static final Uri CONTENT_UNDELIVERED_URI = Uri.parse(
   1591                 "content://mms-sms/undelivered");
   1592 
   1593         public static final Uri CONTENT_DRAFT_URI = Uri.parse(
   1594                 "content://mms-sms/draft");
   1595 
   1596         public static final Uri CONTENT_LOCKED_URI = Uri.parse(
   1597                 "content://mms-sms/locked");
   1598 
   1599         /***
   1600          * Pass in a query parameter called "pattern" which is the text
   1601          * to search for.
   1602          * The sort order is fixed to be thread_id ASC,date DESC.
   1603          */
   1604         public static final Uri SEARCH_URI = Uri.parse(
   1605                 "content://mms-sms/search");
   1606 
   1607         // Constants for message protocol types.
   1608         public static final int SMS_PROTO = 0;
   1609         public static final int MMS_PROTO = 1;
   1610 
   1611         // Constants for error types of pending messages.
   1612         public static final int NO_ERROR                      = 0;
   1613         public static final int ERR_TYPE_GENERIC              = 1;
   1614         public static final int ERR_TYPE_SMS_PROTO_TRANSIENT  = 2;
   1615         public static final int ERR_TYPE_MMS_PROTO_TRANSIENT  = 3;
   1616         public static final int ERR_TYPE_TRANSPORT_FAILURE    = 4;
   1617         public static final int ERR_TYPE_GENERIC_PERMANENT    = 10;
   1618         public static final int ERR_TYPE_SMS_PROTO_PERMANENT  = 11;
   1619         public static final int ERR_TYPE_MMS_PROTO_PERMANENT  = 12;
   1620 
   1621         public static final class PendingMessages implements BaseColumns {
   1622             public static final Uri CONTENT_URI = Uri.withAppendedPath(
   1623                     MmsSms.CONTENT_URI, "pending");
   1624             /**
   1625              * The type of transport protocol(MMS or SMS).
   1626              * <P>Type: INTEGER</P>
   1627              */
   1628             public static final String PROTO_TYPE = "proto_type";
   1629             /**
   1630              * The ID of the message to be sent or downloaded.
   1631              * <P>Type: INTEGER</P>
   1632              */
   1633             public static final String MSG_ID = "msg_id";
   1634             /**
   1635              * The type of the message to be sent or downloaded.
   1636              * This field is only valid for MM. For SM, its value is always
   1637              * set to 0.
   1638              */
   1639             public static final String MSG_TYPE = "msg_type";
   1640             /**
   1641              * The type of the error code.
   1642              * <P>Type: INTEGER</P>
   1643              */
   1644             public static final String ERROR_TYPE = "err_type";
   1645             /**
   1646              * The error code of sending/retrieving process.
   1647              * <P>Type:  INTEGER</P>
   1648              */
   1649             public static final String ERROR_CODE = "err_code";
   1650             /**
   1651              * How many times we tried to send or download the message.
   1652              * <P>Type:  INTEGER</P>
   1653              */
   1654             public static final String RETRY_INDEX = "retry_index";
   1655             /**
   1656              * The time to do next retry.
   1657              */
   1658             public static final String DUE_TIME = "due_time";
   1659             /**
   1660              * The time we last tried to send or download the message.
   1661              */
   1662             public static final String LAST_TRY = "last_try";
   1663         }
   1664 
   1665         public static final class WordsTable {
   1666             public static final String ID = "_id";
   1667             public static final String SOURCE_ROW_ID = "source_id";
   1668             public static final String TABLE_ID = "table_to_use";
   1669             public static final String INDEXED_TEXT = "index_text";
   1670         }
   1671     }
   1672 
   1673     public static final class Carriers implements BaseColumns {
   1674         /**
   1675          * The content:// style URL for this table
   1676          */
   1677         public static final Uri CONTENT_URI =
   1678             Uri.parse("content://telephony/carriers");
   1679 
   1680         /**
   1681          * The default sort order for this table
   1682          */
   1683         public static final String DEFAULT_SORT_ORDER = "name ASC";
   1684 
   1685         public static final String NAME = "name";
   1686 
   1687         public static final String APN = "apn";
   1688 
   1689         public static final String PROXY = "proxy";
   1690 
   1691         public static final String PORT = "port";
   1692 
   1693         public static final String MMSPROXY = "mmsproxy";
   1694 
   1695         public static final String MMSPORT = "mmsport";
   1696 
   1697         public static final String SERVER = "server";
   1698 
   1699         public static final String USER = "user";
   1700 
   1701         public static final String PASSWORD = "password";
   1702 
   1703         public static final String MMSC = "mmsc";
   1704 
   1705         public static final String MCC = "mcc";
   1706 
   1707         public static final String MNC = "mnc";
   1708 
   1709         public static final String NUMERIC = "numeric";
   1710 
   1711         public static final String AUTH_TYPE = "authtype";
   1712 
   1713         public static final String TYPE = "type";
   1714 
   1715         public static final String CURRENT = "current";
   1716     }
   1717 
   1718     public static final class Intents {
   1719         private Intents() {
   1720             // Not instantiable
   1721         }
   1722 
   1723         /**
   1724          * Broadcast Action: A "secret code" has been entered in the dialer. Secret codes are
   1725          * of the form *#*#<code>#*#*. The intent will have the data URI:</p>
   1726          *
   1727          * <p><code>android_secret_code://&lt;code&gt;</code></p>
   1728          */
   1729         public static final String SECRET_CODE_ACTION =
   1730                 "android.provider.Telephony.SECRET_CODE";
   1731 
   1732         /**
   1733          * Broadcast Action: The Service Provider string(s) have been updated.  Activities or
   1734          * services that use these strings should update their display.
   1735          * The intent will have the following extra values:</p>
   1736          * <ul>
   1737          *   <li><em>showPlmn</em> - Boolean that indicates whether the PLMN should be shown.</li>
   1738          *   <li><em>plmn</em> - The operator name of the registered network, as a string.</li>
   1739          *   <li><em>showSpn</em> - Boolean that indicates whether the SPN should be shown.</li>
   1740          *   <li><em>spn</em> - The service provider name, as a string.</li>
   1741          * </ul>
   1742          * Note that <em>showPlmn</em> may indicate that <em>plmn</em> should be displayed, even
   1743          * though the value for <em>plmn</em> is null.  This can happen, for example, if the phone
   1744          * has not registered to a network yet.  In this case the receiver may substitute an
   1745          * appropriate placeholder string (eg, "No service").
   1746          *
   1747          * It is recommended to display <em>plmn</em> before / above <em>spn</em> if
   1748          * both are displayed.
   1749          *
   1750          * <p>Note this is a protected intent that can only be sent
   1751          * by the system.
   1752          */
   1753         public static final String SPN_STRINGS_UPDATED_ACTION =
   1754                 "android.provider.Telephony.SPN_STRINGS_UPDATED";
   1755 
   1756         public static final String EXTRA_SHOW_PLMN  = "showPlmn";
   1757         public static final String EXTRA_PLMN       = "plmn";
   1758         public static final String EXTRA_SHOW_SPN   = "showSpn";
   1759         public static final String EXTRA_SPN        = "spn";
   1760     }
   1761 }
   1762