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