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