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