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