Home | History | Annotate | Download | only in mapapi
      1 /*
      2  * Copyright (C) 2013 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 com.android.bluetooth.mapapi;
     18 
     19 import android.content.ContentResolver;
     20 import android.net.Uri;
     21 
     22 
     23 /**
     24  * This class defines the minimum sets of data needed for a client to
     25  * implement to claim support for the Bluetooth Message Access Profile.
     26  * Access to three data sets are needed:
     27  * <ul>
     28  *   <li>Message data set containing lists of messages.</li>
     29  *   <li>Account data set containing info on the existing accounts, and whether to expose
     30  *     these accounts. The content of the account data set is often sensitive information,
     31  *     hence care must be taken, not to reveal any personal information nor passwords.
     32  *     The accounts in this data base will be exposed in the settings menu, where the user
     33  *     is able to enable and disable the EXPOSE_FLAG, and thereby provide access to an
     34  *     account from another device, without any password protection the e-mail client
     35  *     might provide.</li>
     36  *   <li>Folder data set with the folder structure for the messages. Each message is linked to an
     37  *     entry in this data set.</li>
     38  *   <li>Conversation data set with the thread structure of the messages. Each message is linked
     39  *     to an entry in this data set.</li>
     40  * </ul>
     41  *
     42  * To enable that the Bluetooth Message Access Server can detect the content provider implementing
     43  * this interface, the {@code provider} tag for the Bluetooth related content provider must
     44  * have an intent-filter like the following in the manifest:
     45  * <pre class="prettyprint">&lt;provider  android:authorities="[PROVIDER AUTHORITY]"
     46               android:exported="true"
     47               android:enabled="true"
     48               android:permission="android.permission.BLUETOOTH_MAP"&gt;
     49  *   ...
     50  *      &lt;intent-filter&gt;
     51            &lt;action android:name="android.content.action.BLEUETOOT_MAP_PROVIDER" /&gt;
     52         &lt;/intent-filter&gt;
     53  *   ...
     54  *   &lt;/provider&gt;
     55  * [PROVIDER AUTHORITY] shall be the providers authority value which implements this
     56  * contract. Only a single authority shall be used. The android.permission.BLUETOOTH_MAP
     57  * permission is needed for the provider.
     58  */
     59 public final class BluetoothMapContract {
     60     /**
     61      * Constructor - should not be used
     62      */
     63     private BluetoothMapContract(){
     64       /* class should not be instantiated */
     65     }
     66 
     67     /**
     68      * Provider interface that should be used as intent-filter action in the provider section
     69      * of the manifest file.
     70      */
     71     public static final String PROVIDER_INTERFACE_EMAIL =
     72             "android.bluetooth.action.BLUETOOTH_MAP_PROVIDER";
     73     public static final String PROVIDER_INTERFACE_IM =
     74             "android.bluetooth.action.BLUETOOTH_MAP_IM_PROVIDER";
     75     /**
     76      * The Bluetooth Message Access profile allows a remote BT-MAP client to trigger
     77      * an update of a folder for a specific e-mail account, register for reception
     78      * of new messages from the server.
     79      *
     80      * Additionally the Bluetooth Message Access profile allows a remote BT-MAP client
     81      * to push a message to a folder - e.g. outbox or draft. The Bluetooth profile
     82      * implementation will place a new message in one of these existing folders through
     83      * the content provider.
     84      *
     85      * ContentProvider.call() is used for these purposes, and the METHOD_UPDATE_FOLDER
     86      * method name shall trigger an update of the specified folder for a specified
     87      * account.
     88      *
     89      * This shall be a non blocking call simply starting the update, and the update should
     90      * both send and receive messages, depending on what makes sense for the specified
     91      * folder.
     92      * Bundle extra parameter will carry two INTEGER (long) values:
     93      *   EXTRA_UPDATE_ACCOUNT_ID containing the account_id
     94      *   EXTRA_UPDATE_FOLDER_ID containing the folder_id of the folder to update
     95      *
     96      * The status for send complete of messages shall be reported by updating the sent-flag
     97      * and e.g. for outbox messages, move them to the sent folder in the message table of the
     98      * content provider and trigger a change notification to any attached content observer.
     99      */
    100     public static final String METHOD_UPDATE_FOLDER = "UpdateFolder";
    101     public static final String EXTRA_UPDATE_ACCOUNT_ID = "UpdateAccountId";
    102     public static final String EXTRA_UPDATE_FOLDER_ID = "UpdateFolderId";
    103 
    104     /**
    105      * The Bluetooth Message Access profile allows a remote BT-MAP Client to update
    106      * the owners presence and chat state
    107      *
    108      * ContentProvider.call() is used for these purposes, and the METHOD_SET_OWNER_STATUS
    109      * method name shall trigger a change in owner/users presence or chat properties for an
    110      * account or conversation.
    111      *
    112      * This shall be a non blocking call simply setting the properties, and the change should
    113      * be sent to the remote server/users, depending on what property is changed.
    114      * Bundle extra parameter will carry following values:
    115      *   EXTRA_ACCOUNT_ID containing the account_id
    116      *   EXTRA_PRESENCE_STATE containing the presence state of the owner account
    117      *   EXTRA_PRESENCE_STATUS containing the presence status text from the owner
    118      *   EXTRA_LAST_ACTIVE containing the last activity time stamp of the owner account
    119      *   EXTRA_CHAT_STATE containing the chat state of a specific conversation
    120      *   EXTRA_CONVERSATION_ID containing the conversation that is changed
    121      */
    122     public static final String METHOD_SET_OWNER_STATUS = "SetOwnerStatus";
    123     public static final String EXTRA_ACCOUNT_ID = "AccountId"; // Is this needed
    124     public static final String EXTRA_PRESENCE_STATE = "PresenceState";
    125     public static final String EXTRA_PRESENCE_STATUS = "PresenceStatus";
    126     public static final String EXTRA_LAST_ACTIVE = "LastActive";
    127     public static final String EXTRA_CHAT_STATE = "ChatState";
    128     public static final String EXTRA_CONVERSATION_ID = "ConversationId";
    129 
    130     /**
    131      * The Bluetooth Message Access profile can inform the messaging application of the Bluetooth
    132      * state, whether is is turned 'on' or 'off'
    133      *
    134      * ContentProvider.call() is used for these purposes, and the METHOD_SET_BLUETOOTH_STATE
    135      * method name shall trigger a change in owner/users presence or chat properties for an
    136      * account or conversation.
    137      *
    138      * This shall be a non blocking call simply setting the properties.
    139      *
    140      * Bundle extra parameter will carry following values:
    141      *   EXTRA_BLUETOOTH_STATE containing the state of the Bluetooth connectivity
    142      */
    143     public static final String METHOD_SET_BLUETOOTH_STATE = "SetBtState";
    144     public static final String EXTRA_BLUETOOTH_STATE = "BluetoothState";
    145 
    146     /**
    147      * These column names are used as last path segment of the URI (getLastPathSegment()).
    148      * Access to a specific row in the tables is done by using the where-clause, hence
    149      * support for .../#id if not needed for the Email clients.
    150      * The URI format for accessing the tables are as follows:
    151      *   content://ProviderAuthority/TABLE_ACCOUNT
    152      *   content://ProviderAuthority/account_id/TABLE_MESSAGE
    153      *   content://ProviderAuthority/account_id/TABLE_FOLDER
    154      *   content://ProviderAuthority/account_id/TABLE_CONVERSATION
    155      *   content://ProviderAuthority/account_id/TABLE_CONVOCONTACT
    156      **/
    157 
    158     /**
    159      * Build URI representing the given Accounts data-set in a
    160      * Bluetooth provider. When queried, the direct URI for the account
    161      * with the given accountID is returned.
    162      */
    163     public static Uri buildAccountUri(String authority) {
    164         return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
    165                 .authority(authority).appendPath(TABLE_ACCOUNT).build();
    166     }
    167     /**
    168      * Build URI representing the given Account data-set with specific Id in a
    169      * Bluetooth provider. When queried, the direct URI for the account
    170      * with the given accountID is returned.
    171      */
    172     public static Uri buildAccountUriwithId(String authority, String accountId) {
    173         return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
    174                 .authority(authority)
    175                 .appendPath(TABLE_ACCOUNT)
    176                 .appendPath(accountId)
    177                 .build();
    178     }
    179     /**
    180      * Build URI representing the entire Message table in a
    181      * Bluetooth provider.
    182      */
    183     public static Uri buildMessageUri(String authority) {
    184         return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
    185                 .authority(authority)
    186                 .appendPath(TABLE_MESSAGE)
    187                 .build();
    188     }
    189     /**
    190      * Build URI representing the given Message data-set in a
    191      * Bluetooth provider. When queried, the URI for the Messages
    192      * with the given accountID is returned.
    193      */
    194     public static Uri buildMessageUri(String authority, String accountId) {
    195         return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
    196                 .authority(authority)
    197                 .appendPath(accountId)
    198                 .appendPath(TABLE_MESSAGE)
    199                 .build();
    200     }
    201     /**
    202      * Build URI representing the given Message data-set with specific messageId in a
    203      * Bluetooth provider. When queried, the direct URI for the account
    204      * with the given accountID is returned.
    205      */
    206     public static Uri buildMessageUriWithId(String authority, String accountId,String messageId) {
    207         return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
    208                 .authority(authority)
    209                 .appendPath(accountId)
    210                 .appendPath(TABLE_MESSAGE)
    211                 .appendPath(messageId)
    212                 .build();
    213     }
    214     /**
    215      * Build URI representing the given Message data-set in a
    216      * Bluetooth provider. When queried, the direct URI for the folder
    217      * with the given accountID is returned.
    218      */
    219     public static Uri buildFolderUri(String authority, String accountId) {
    220         return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
    221                 .authority(authority)
    222                 .appendPath(accountId)
    223                 .appendPath(TABLE_FOLDER)
    224                 .build();
    225     }
    226 
    227     /**
    228      * Build URI representing the given Message data-set in a
    229      * Bluetooth provider. When queried, the direct URI for the conversation
    230      * with the given accountID is returned.
    231      */
    232     public static Uri buildConversationUri(String authority, String accountId) {
    233         return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
    234                 .authority(authority)
    235                 .appendPath(accountId)
    236                 .appendPath(TABLE_CONVERSATION)
    237                 .build();
    238     }
    239 
    240     /**
    241      * Build URI representing the given Contact data-set in a
    242      * Bluetooth provider. When queried, the direct URI for the contacts
    243      * with the given accountID is returned.
    244      */
    245     public static Uri buildConvoContactsUri(String authority) {
    246         return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
    247                 .authority(authority)
    248                 .appendPath(TABLE_CONVOCONTACT)
    249                 .build();
    250     }
    251 
    252     /**
    253      * Build URI representing the given Contact data-set in a
    254      * Bluetooth provider. When queried, the direct URI for the contacts
    255      * with the given accountID is returned.
    256      */
    257     public static Uri buildConvoContactsUri(String authority, String accountId) {
    258         return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
    259                 .authority(authority)
    260                 .appendPath(accountId)
    261                 .appendPath(TABLE_CONVOCONTACT)
    262                 .build();
    263     }
    264     /**
    265      * Build URI representing the given Contact data-set in a
    266      * Bluetooth provider. When queried, the direct URI for the contact
    267      * with the given contactID and accountID is returned.
    268      */
    269     public static Uri buildConvoContactsUriWithId(String authority, String accountId,
    270             String contactId) {
    271         return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
    272                 .authority(authority)
    273                 .appendPath(accountId)
    274                 .appendPath(TABLE_CONVOCONTACT)
    275                 .appendPath(contactId)
    276                 .build();
    277     }
    278     /**
    279      *  @hide
    280      */
    281     public static final String TABLE_ACCOUNT        = "Account";
    282     public static final String TABLE_MESSAGE        = "Message";
    283     public static final String TABLE_MESSAGE_PART   = "Part";
    284     public static final String TABLE_FOLDER         = "Folder";
    285     public static final String TABLE_CONVERSATION   = "Conversation";
    286     public static final String TABLE_CONVOCONTACT   = "ConvoContact";
    287 
    288 
    289     /**
    290      * Mandatory folders for the Bluetooth message access profile.
    291      * The email client shall at least implement the following root folders.
    292      * E.g. as a mapping for them such that the naming will match the underlying
    293      * matching folder ID's.
    294      */
    295     public static final String FOLDER_NAME_INBOX   = "INBOX";
    296     public static final String FOLDER_NAME_SENT    = "SENT";
    297     public static final String FOLDER_NAME_OUTBOX  = "OUTBOX";
    298     public static final String FOLDER_NAME_DRAFT   = "DRAFT";
    299     public static final String FOLDER_NAME_DELETED = "DELETED";
    300     public static final String FOLDER_NAME_OTHER   = "OTHER";
    301 
    302     /**
    303      * Folder IDs to be used with Instant Messaging virtual folders
    304      */
    305     public static final long FOLDER_ID_OTHER      = 0;
    306     public static final long FOLDER_ID_INBOX      = 1;
    307     public static final long FOLDER_ID_SENT       = 2;
    308     public static final long FOLDER_ID_DRAFT      = 3;
    309     public static final long FOLDER_ID_OUTBOX     = 4;
    310     public static final long FOLDER_ID_DELETED    = 5;
    311 
    312 
    313     /**
    314      * To push RFC2822 encoded messages into a folder and read RFC2822 encoded messages from
    315      * a folder, the openFile() interface will be used as follows:
    316      * Open a file descriptor to a message.
    317      * Two modes supported for read: With and without attachments.
    318      * One mode exist for write and the actual content will be with or without
    319      * attachments.
    320      *
    321      * mode will be "r" for read and "w" for write, never "rw".
    322      *
    323      * URI format:
    324      * The URI scheme is as follows.
    325      * For reading messages with attachments:
    326      *   content://ProviderAuthority/account_id/TABLE_MESSAGE/msgId
    327      *   Note: This shall be an offline operation, including only message parts and attachments
    328      *         already downloaded to the device.
    329      *
    330      * For reading messages without attachments:
    331      *   content://ProviderAuthority/account_id/TABLE_MESSAGE/msgId/FILE_MSG_NO_ATTACHMENTS
    332      *   Note: This shall be an offline operation, including only message parts already
    333      *         downloaded to the device.
    334      *
    335      * For downloading and reading messages with attachments:
    336      *   content://ProviderAuthority/account_id/TABLE_MESSAGE/msgId/FILE_MSG_DOWNLOAD
    337      *   Note: This shall download the message content and all attachments if possible,
    338      *         else throw an IOException.
    339      *
    340      * For downloading and reading messages without attachments:
    341      *   content://ProviderAuthority/account_id/TABLE_MESSAGE/msgId/FILE_MSG_DOWNLOAD_NO_ATTACHMENTS
    342      *   Note: This shall download the message content if possible, else throw an IOException.
    343      *
    344      * When reading from the file descriptor, the content provider shall return a stream
    345      * of bytes containing a RFC2822 encoded message, as if the message was send to an email
    346      * server.
    347      *
    348      * When a byte stream is written to the file descriptor, the content provider shall
    349      * decode the RFC2822 encoded data and insert the message into the TABLE_MESSAGE at the ID
    350      * supplied in URI - additionally the message content shall be stored in the underlying
    351      * data base structure as if the message was received from an email server. The Message ID
    352      * will be created using a insert on the TABLE_MESSAGE prior to calling openFile().
    353      * Hence the procedure for inserting a message is:
    354      *  - uri/msgId = insert(uri, value: folderId=xxx)
    355      *  - fd = openFile(uri/msgId)
    356      *  - fd.write (RFC2822 encoded data)
    357      *
    358      *  The Bluetooth Message Access Client might not know what to put into the From:
    359      *  header nor have a valid time stamp, hence the content provider shall check
    360      *  if the From: and Date: headers have been set by the message written, else
    361      *  it must fill in appropriate values.
    362      */
    363     public static final String FILE_MSG_NO_ATTACHMENTS = "NO_ATTACHMENTS";
    364     public static final String FILE_MSG_DOWNLOAD = "DOWNLOAD";
    365     public static final String FILE_MSG_DOWNLOAD_NO_ATTACHMENTS = "DOWNLOAD_NO_ATTACHMENTS";
    366 
    367     /**
    368      * Account Table
    369      * The columns needed to supply account information.
    370      * The e-mail client app may choose to expose all e-mails as being from the same account,
    371      * but it is not recommended, as this would be a violation of the Bluetooth specification.
    372      * The Bluetooth Message Access settings activity will provide the user the ability to
    373      * change the FLAG_EXPOSE values for each account in this table.
    374      * The Bluetooth Message Access service will read the values when Bluetooth is turned on,
    375      * and again on every notified change through the content observer interface.
    376      */
    377     public interface AccountColumns {
    378 
    379         /**
    380          * The unique ID for a row.
    381          * <P>Type: INTEGER (long)</P>
    382          */
    383         public static final String _ID = "_id";
    384 
    385         /**
    386          * The account name to display to the user on the device when selecting whether
    387          * or not to share the account over Bluetooth.
    388          *
    389          * The account display name should not reveal any sensitive information e.g. email-
    390          * address, as it will be added to the Bluetooth SDP record, which can be read by
    391          * any Bluetooth enabled device. (Access to any account content is only provided to
    392          * authenticated devices). It is recommended that if the email client uses the email
    393          * address as account name, then the address should be obfuscated (i.e. replace "@"
    394          * with ".")
    395          * <P>Type: TEXT</P>
    396          * read-only
    397          */
    398         public static final String ACCOUNT_DISPLAY_NAME = "account_display_name";
    399 
    400         /**
    401          * Expose this account to other authenticated Bluetooth devices. If the expose flag
    402          * is set, this account will be listed as an available account to access from another
    403          * Bluetooth device.
    404          *
    405          * This is a read/write flag, that can be set either from within the E-mail client
    406          * UI or the Bluetooth settings menu.
    407          *
    408          * It is recommended to either ask the user whether to expose the account, or set this
    409          * to "show" as default.
    410          *
    411          * This setting shall not be used to enforce whether or not an account should be shared
    412          * or not if the account is bound by an administrative security policy. In this case
    413          * the email app should not list the account at all if it is not to be sharable over BT.
    414          *
    415          * <P>Type: INTEGER (boolean) hide = 0, show = 1</P>
    416          */
    417         public static final String FLAG_EXPOSE = "flag_expose";
    418 
    419 
    420         /**
    421          * The account unique identifier representing this account. For most IM clients this will be
    422          * the fully qualified user name to which an invite message can be sent, from another use.
    423          *
    424          * e.g.: "map_test_user_12345 (at) gmail.com" - for a Hangouts account
    425          *
    426          * This value will only be visible to authenticated Bluetooth devices, and will be
    427          * transmitted using an encrypted link.
    428          * <P>Type: TEXT</P>
    429          * read-only
    430          */
    431         public static final String ACCOUNT_UCI = "account_uci";
    432 
    433 
    434         /**
    435          * The Bluetooth SIG maintains a list of assigned numbers(text strings) for IM clients.
    436          * If your client/account has such a string, this is the place to return it.
    437          * If supported by both devices, the presence of this prefix will make it possible to
    438          * respond to a message by making a voice-call, using the same account information.
    439          * (The call will be made using the HandsFree profile)
    440          * https://www.bluetooth.org/en-us/specification/assigned-numbers/uniform-caller-identifiers
    441          *
    442          * e.g.: "hgus" - for Hangouts
    443          *
    444          * <P>Type: TEXT</P>
    445          * read-only
    446          */
    447         public static final String ACCOUNT_UCI_PREFIX = "account_uci_PREFIX";
    448 
    449     }
    450 
    451     /**
    452      * Message Data Parts Table
    453      * The columns needed to contain the actual data of the messageparts in IM messages.
    454      * Each "part" has its own row and represent a single mime-part in a multipart-mime
    455      * formatted message.
    456      *
    457      */
    458     public interface MessagePartColumns {
    459 
    460         /**
    461          * The unique ID for a row.
    462          * <P>Type: INTEGER (long)</P>
    463          * read-only
    464          */
    465         public static final String _ID = "_id";
    466         // FIXME add message parts for IM attachments
    467         /**
    468          * is this a text part  yes/no?
    469          * <P>Type: TEXT</P>
    470          * read-only
    471          */
    472         public static final String TEXT = "text";
    473 
    474         /**
    475          * The charset used in the content if it is text or 8BIT if it is
    476          * binary data
    477          *
    478          * <P>Type: TEXT</P>
    479          * read-only
    480          */
    481         public static final String CHARSET = "charset";
    482 
    483         /**
    484          * The filename representing the data file of the raw data in the database
    485          * If this is empty, then it must be text and part of the message body.
    486          * This is the name that the data will have when it is included as attachment
    487          *
    488          * <P>Type: TEXT</P>
    489          * read-only
    490          */
    491 
    492         public static final String FILENAME = "filename";
    493 
    494         /**
    495          * Identifier for the content in the data. This can be used to
    496          * refer directly to the data in the body part.
    497          *
    498          * <P>Type: TEXT</P>
    499          * read-only
    500          */
    501 
    502         public static final String CONTENT_ID = "cid";
    503 
    504         /**
    505          * The raw data in either text format or binary format
    506          *
    507          * <P>Type: BLOB</P>
    508          * read-only
    509          */
    510         public static final String RAW_DATA = "raw_data";
    511 
    512     }
    513     /**
    514      * The actual message table containing all messages.
    515      * Content that must support filtering using WHERE clauses:
    516      *   - To, From, Cc, Bcc, Date, ReadFlag, PriorityFlag, folder_id, account_id
    517      * Additional content that must be supplied:
    518      *   - Subject, AttachmentFlag, LoadedState, MessageSize, AttachmentSize
    519      * Content that must support update:
    520      *   - FLAG_READ and FOLDER_ID (FOLDER_ID is used to move a message to deleted)
    521      * Additional insert of a new message with the following values shall be supported:
    522      *   - FOLDER_ID
    523      *
    524      * When doing an insert on this table, the actual content of the message (subject,
    525      * date etc) written through file-i/o takes precedence over the inserted values and should
    526      * overwrite them.
    527      */
    528     public interface MessageColumns extends EmailMessageColumns {
    529 
    530         /**
    531          * The unique ID for a row.
    532          * <P>Type: INTEGER (long)</P>
    533          */
    534         public static final String _ID = "_id";
    535 
    536         /**
    537          * The date the message was received as a unix timestamp
    538          * (miliseconds since 00:00:00 UTC 1/1-1970).
    539          *
    540          * <P>Type: INTEGER (long)</P>
    541          * read-only
    542          */
    543         public static final String DATE = "date";
    544 
    545         //TODO REMOVE WHEN Parts Table is in place
    546         /**
    547          * Message body. Used by Instant Messaging
    548          * <P>Type: TEXT</P>
    549          * read-only.
    550          */
    551         public static final String BODY = "body";
    552 
    553         /**
    554          * Message subject.
    555          * <P>Type: TEXT</P>
    556          * read-only.
    557          */
    558         public static final String SUBJECT = "subject";
    559 
    560         /**
    561          * Message Read flag
    562          * <P>Type: INTEGER (boolean) unread = 0, read = 1</P>
    563          *  read/write
    564          */
    565         public static final String FLAG_READ = "flag_read";
    566 
    567         /**
    568          * Message Priority flag
    569          * <P>Type: INTEGER (boolean) normal priority = 0, high priority = 1</P>
    570          * read-only
    571          */
    572         public static final String FLAG_HIGH_PRIORITY = "high_priority";
    573 
    574         /**
    575          * Reception state - the amount of the message that have been loaded from the server.
    576          * <P>Type: TEXT see RECEPTION_STATE_* constants below </P>
    577          * read-only
    578          */
    579         public static final String RECEPTION_STATE = "reception_state";
    580 
    581         /**
    582          * Delivery state - the amount of the message that have been loaded from the server.
    583          * <P>Type: TEXT see DELIVERY_STATE_* constants below </P>
    584          * read-only
    585          */
    586         public static final String DEVILERY_STATE = "delivery_state";
    587 
    588         /** To be able to filter messages with attachments, we need this flag.
    589          * <P>Type: INTEGER (boolean) no attachment = 0, attachment = 1 </P>
    590          * read-only
    591          */
    592         public static final String FLAG_ATTACHMENT = "flag_attachment";
    593 
    594         /** The overall size in bytes of the attachments of the message.
    595          * <P>Type: INTEGER </P>
    596          */
    597         public static final String ATTACHMENT_SIZE = "attachment_size";
    598 
    599         /** The mine type of the attachments for the message.
    600          * <P>Type: TEXT </P>
    601          * read-only
    602          */
    603         public static final String ATTACHMENT_MINE_TYPES = "attachment_mime_types";
    604 
    605         /** The overall size in bytes of the message including any attachments.
    606          * This value is informative only and should be the size an email client
    607          * would display as size for the message.
    608          * <P>Type: INTEGER </P>
    609          * read-only
    610          */
    611         public static final String MESSAGE_SIZE = "message_size";
    612 
    613         /** Indicates that the message or a part of it is protected by a DRM scheme.
    614          * <P>Type: INTEGER (boolean) no DRM = 0, DRM protected = 1 </P>
    615          * read-only
    616          */
    617         public static final String FLAG_PROTECTED = "flag_protected";
    618 
    619         /**
    620          * A comma-delimited list of FROM addresses in RFC2822 format.
    621          * The list must be compatible with Rfc822Tokenizer.tokenize();
    622          * <P>Type: TEXT</P>
    623          * read-only
    624          */
    625         public static final String FROM_LIST = "from_list";
    626 
    627         /**
    628          * A comma-delimited list of TO addresses in RFC2822 format.
    629          * The list must be compatible with Rfc822Tokenizer.tokenize();
    630          * <P>Type: TEXT</P>
    631          * read-only
    632          */
    633         public static final String TO_LIST = "to_list";
    634 
    635         /**
    636          * The unique ID for a row in the folder table in which this message belongs.
    637          * <P>Type: INTEGER (long)</P>
    638          * read/write
    639          */
    640         public static final String FOLDER_ID = "folder_id";
    641 
    642         /**
    643          * The unique ID for a row in the account table which owns this message.
    644          * <P>Type: INTEGER (long)</P>
    645          * read-only
    646          */
    647         public static final String ACCOUNT_ID = "account_id";
    648 
    649         /**
    650          * The ID identify the thread/conversation a message belongs to.
    651          * If no thread id is available, set value to "-1"
    652          * <P>Type: INTEGER (long)</P>
    653          * read-only
    654          */
    655         public static final String THREAD_ID = "thread_id";
    656 
    657         /**
    658          * The Name of the thread/conversation a message belongs to.
    659          * <P>Type: TEXT</P>
    660          * read-only
    661          */
    662         public static final String THREAD_NAME = "thread_name";
    663     }
    664 
    665     public interface EmailMessageColumns {
    666 
    667 
    668 
    669         /**
    670          * A comma-delimited list of CC addresses in RFC2822 format.
    671          * The list must be compatible with Rfc822Tokenizer.tokenize();
    672          * <P>Type: TEXT</P>
    673          * read-only
    674          */
    675         public static final String CC_LIST = "cc_list";
    676 
    677         /**
    678          * A comma-delimited list of BCC addresses in RFC2822 format.
    679          * The list must be compatible with Rfc822Tokenizer.tokenize();
    680          * <P>Type: TEXT</P>
    681          * read-only
    682          */
    683         public static final String BCC_LIST = "bcc_list";
    684 
    685         /**
    686          * A comma-delimited list of REPLY-TO addresses in RFC2822 format.
    687          * The list must be compatible with Rfc822Tokenizer.tokenize();
    688          * <P>Type: TEXT</P>
    689          * read-only
    690          */
    691         public static final String REPLY_TO_LIST = "reply_to_List";
    692 
    693 
    694     }
    695 
    696     /**
    697      * Indicates the complete message has been delivered to the recipient.
    698      */
    699     public static final String DELIVERY_STATE_DELIVERED = "delivered";
    700     /**
    701      * Indicates that the complete message has been sent from the MSE to the remote network.
    702      */
    703     public static final String DELIVERY_STATE_SENT = "sent";
    704 
    705     /**
    706      * Indicates that the message, including any attachments, has been received from the
    707      * server to the device.
    708      */
    709     public static final String RECEPTION_STATE_COMPLETE = "complete";
    710     /**
    711      * Indicates the message is partially received from the email server.
    712      */
    713     public static final String RECEPTION_STATE_FRACTIONED = "fractioned";
    714     /**
    715      * Indicates that only a notification about the message have been received.
    716      */
    717     public static final String RECEPTION_STATE_NOTIFICATION = "notification";
    718 
    719     /**
    720      * Message folder structure
    721      * MAP enforces use of a folder structure with mandatory folders:
    722      *   - inbox, outbox, sent, deleted, draft
    723      * User defined folders are supported.
    724      * The folder table must provide filtering (use of WHERE clauses) of the following entries:
    725      *   - account_id (linking the folder to an e-mail account)
    726      *   - parent_id (linking the folders individually)
    727      * The folder table must have a folder name for each entry, and the mandatory folders
    728      * MUST exist for each account_id. The folders may be empty.
    729      * Use the FOLDER_NAME_xxx constants for the mandatory folders. Their names must
    730      * not be translated into other languages, as the folder browsing is string based, and
    731      * many Bluetooth Message Clients will use these strings to navigate to the folders.
    732      */
    733     public interface FolderColumns {
    734 
    735         /**
    736          * The unique ID for a row.
    737          * <P>Type: INTEGER (long)</P>
    738          * read-only
    739          */
    740         public static final String _ID = "_id";
    741 
    742         /**
    743          * The folder display name to present to the user.
    744          * <P>Type: TEXT</P>
    745          * read-only
    746          */
    747         public static final String NAME = "name";
    748 
    749         /**
    750          * The _id-key to the account this folder refers to.
    751          * <P>Type: INTEGER (long)</P>
    752          * read-only
    753          */
    754         public static final String ACCOUNT_ID = "account_id";
    755 
    756         /**
    757          * The _id-key to the parent folder. -1 for root folders.
    758          * <P>Type: INTEGER (long)</P>
    759          * read-only
    760          */
    761         public static final String PARENT_FOLDER_ID = "parent_id";
    762     }
    763 
    764     /**
    765      * Message conversation structure. Enables use of a conversation structure for messages across
    766      * folders, further binding contacts to conversations.
    767      * Content that must be supplied:
    768      *   - Name, LastActivity, ReadStatus, VersionCounter
    769      * Content that must support update:
    770      *   - READ_STATUS, LAST_ACTIVITY and VERSION_COUNTER (VERSION_COUNTER used to validity of _ID)
    771      * Additional insert of a new conversation with the following values shall be supported:
    772      *   - FOLDER_ID
    773      * When querying this table, the cursor returned must contain one row for each contact member
    774      * in a thread.
    775      * For filter/search parameters attributes to the URI will be used. The following columns must
    776      * support filtering:
    777      *  - ConvoContactColumns.NAME
    778      *  - ConversationColumns.THREAD_ID
    779      *  - ConversationColumns.LAST_ACTIVITY
    780      *  - ConversationColumns.READ_STATUS
    781      */
    782     public interface ConversationColumns extends ConvoContactColumns {
    783 
    784         /**
    785          * The unique ID for a row.
    786          * <P>Type: INTEGER (long)</P>
    787          * read-only
    788          */
    789 // Should not be needed anymore        public static final String _ID = "_id";
    790 
    791         /**
    792          * The unique ID for a Thread.
    793          * <P>Type: INTEGER (long)</P>
    794          * read-only
    795          */
    796         public static final String THREAD_ID = "thread_id";
    797 
    798         /**
    799          * The unique ID for a row.
    800          * <P>Type: INTEGER (long)</P>
    801          * read-only
    802          */
    803 // TODO: IS THIS NECESSARY - or do we need the thread ID to hold thread Id from message
    804 //       or can we be sure we are in control and can use the _ID and put that in the message DB
    805         //public static final String THREAD_ID = "thread_id";
    806 
    807         /**
    808          * The type of conversation, see {@link ConversationType}
    809          * <P>Type: TEXT</P>
    810          * read-only
    811          */
    812 // TODO: IS THIS NECESSARY - no conversation type is available in the latest,
    813 //        guess it can be found from number of contacts in the conversation
    814         //public static final String TYPE = "type";
    815 
    816         /**
    817          * The name of the conversation, e.g. group name in case of group chat
    818          * <P>Type: TEXT</P>
    819          * read-only
    820          */
    821         public static final String THREAD_NAME = "thread_name";
    822 
    823         /**
    824          * The time stamp of the last activity in the conversation as a unix timestamp
    825          * (miliseconds since 00:00:00 UTC 1/1-1970)
    826          * <P>Type: INTEGER (long)</P>
    827          * read-only
    828          */
    829         public static final String LAST_THREAD_ACTIVITY = "last_thread_activity";
    830 
    831         /**
    832          * The status on the conversation, either 'read' or 'unread'
    833          *  <P>Type: INTEGER (boolean) unread = 0, read = 1</P>
    834          * read/write
    835          */
    836         public static final String READ_STATUS = "read_status";
    837 
    838         /**
    839          * A counter that keep tack of version of the table content, count up on ID reuse
    840          * <P>Type: INTEGER (long)</P>
    841          * read-only
    842          */
    843 // TODO: IS THIS NECESSARY - skal den ligge i databasen?
    844         // CB: If we need it, it must be in the database, or initialized with a random value at
    845         //     BT-ON
    846         // UPDATE: TODO: Change to the last_activity time stamp (as a long value). This will
    847         //         provide the information needed for BT clients - currently unused
    848         public static final String VERSION_COUNTER = "version_counter";
    849 
    850         /**
    851          * A short description of the latest activity on conversation - typically
    852          * part of the last message.
    853          * <P>Type: TEXT</P>
    854          * read-only
    855          */
    856         public static final String SUMMARY = "convo_summary";
    857 
    858 
    859     }
    860 
    861     /**
    862      * MAP enables access to contacts for the conversation
    863      * The conversation table must provide filtering (using WHERE clauses) of following entries:
    864      *   - convo_id linking contacts to conversations
    865      *   - x_bt_uid linking contacts to PBAP contacts
    866      * The conversation contact table must have a convo_id and a name for each entry.
    867      */
    868     public interface ConvoContactColumns extends ChatStatusColumns, PresenceColumns {
    869         /**
    870          * The unique ID for a contact in Conversation
    871          * <P>Type: INTEGER (long)</P>
    872          * read-only
    873          */
    874 // Should not be needed anymore        public static final String _ID = "_id";
    875 
    876         /**
    877         * The ID of the conversation the contact is part of.
    878         * <P>Type: INTEGER (long)</P>
    879         * read-only
    880         */
    881         public static final String CONVO_ID = "convo_id";
    882 
    883         /**
    884          * The name of contact in instant message application
    885          * <P>Type: TEXT</P>
    886          * read-only
    887          */
    888         public static final String NAME = "name";
    889 
    890         /**
    891          * The nickname of contact in instant message group chat conversation.
    892          * <P>Type: TEXT</P>
    893          * read-only
    894          */
    895         public static final String NICKNAME = "nickname";
    896 
    897 
    898         /**
    899          * The unique ID for all Bluetooth contacts available through PBAP.
    900          * <P>Type: INTEGER (long)</P>
    901          * read-only
    902          */
    903         public static final String X_BT_UID = "x_bt_uid";
    904 
    905         /**
    906          * The unique ID for the contact within the domain of the interfacing service.
    907          * (UCI: Unique Call Identity)
    908          * It is expected that a message send to this ID will reach the recipient regardless
    909          * through which interface the message is send.
    910          * For E-mail this will be the e-mail address, for Google+ this will be the e-mail address
    911          * associated with the contact account.
    912          * This ID
    913          * <P>Type: TEXT</P>
    914          * read-only
    915          */
    916         public static final String UCI = "x_bt_uci";
    917     }
    918 
    919     /**
    920      * The name of query parameter used to filter on recipient
    921      */
    922     public static final String FILTER_RECIPIENT_SUBSTRING = "rec_sub_str";
    923 
    924     /**
    925      * The name of query parameter used to filter on originator
    926      */
    927     public static final String FILTER_ORIGINATOR_SUBSTRING = "org_sub_str";
    928 
    929     /**
    930      * The name of query parameter used to filter on read status.
    931      *  - true - return only threads with all messages marked as read
    932      *  - false - return only threads with one or more unread messages
    933      *  - omitted as query parameter - do not filter on read status
    934      */
    935     public static final String FILTER_READ_STATUS = "read";
    936 
    937     /**
    938      * Time in ms since epoch. For conversations this will be for last activity
    939      * as a unix timestamp (miliseconds since 00:00:00 UTC 1/1-1970)
    940      */
    941     public static final String FILTER_PERIOD_BEGIN = "t_begin";
    942 
    943     /**
    944      * Time in ms since epoch. For conversations this will be for last activity
    945      * as a unix timestamp (miliseconds since 00:00:00 UTC 1/1-1970)
    946      */
    947     public static final String FILTER_PERIOD_END = "t_end";
    948 
    949     /**
    950      * Filter for a specific ThreadId
    951      */
    952     public static final String FILTER_THREAD_ID = "thread_id";
    953 
    954 
    955     public interface ChatState {
    956         int UNKNOWN     = 0;
    957         int INACITVE    = 1;
    958         int ACITVE      = 2;
    959         int COMPOSING   = 3;
    960         int PAUSED      = 4;
    961         int GONE        = 5;
    962     }
    963 
    964     /**
    965      * Instant Messaging contact chat state information
    966      * MAP enables access to contacts chat state for the instant messaging application
    967      * The chat state table must provide filtering (use of WHERE clauses) of the following entries:
    968      *   - contact_id (linking chat state to contacts)
    969      *   - thread_id (linking chat state to conversations and messages)
    970      * The presence table must have a contact_id for each entry.
    971      */
    972     public interface ChatStatusColumns {
    973 
    974 //        /**
    975 //         * The contact ID of a instant messaging contact.
    976 //         * <P>Type: TEXT </P>
    977 //         * read-only
    978 //         */
    979 //        public static final String CONTACT_ID = "contact_id";
    980 //
    981 //        /**
    982 //         * The thread id for a conversation.
    983 //         * <P>Type: INTEGER (long)</P>
    984 //         * read-only
    985 //         */
    986 //        public static final String CONVO_ID = "convo_id";
    987 
    988         /**
    989          * The chat state of contact in conversation, see {@link ChatState}
    990          * <P>Type: INTERGER</P>
    991          * read-only
    992          */
    993         public static final String CHAT_STATE = "chat_state";
    994 
    995 //        /**
    996 //         * The geo location of the contact
    997 //         * <P>Type: TEXT</P>
    998 //         * read-only
    999 //         */
   1000 //// TODO: IS THIS NEEDED - not in latest specification
   1001 //        public static final String GEOLOC = "geoloc";
   1002 
   1003         /**
   1004          * The time stamp of the last time this contact was active in the conversation
   1005          * <P>Type: INTEGER (long)</P>
   1006          * read-only
   1007          */
   1008         public static final String LAST_ACTIVE = "last_active";
   1009 
   1010     }
   1011 
   1012     public interface PresenceState {
   1013         int UNKNOWN         = 0;
   1014         int OFFLINE         = 1;
   1015         int ONLINE          = 2;
   1016         int AWAY            = 3;
   1017         int DO_NOT_DISTURB  = 4;
   1018         int BUSY            = 5;
   1019         int IN_A_MEETING    = 6;
   1020     }
   1021 
   1022     /**
   1023      * Instant Messaging contact presence information
   1024      * MAP enables access to contacts presences information for the instant messaging application
   1025      * The presence table must provide filtering (use of WHERE clauses) of the following entries:
   1026      *   - contact_id (linking contacts to presence)
   1027      * The presence table must have a contact_id for each entry.
   1028      */
   1029     public interface PresenceColumns {
   1030 
   1031 //        /**
   1032 //         * The contact ID of a instant messaging contact.
   1033 //         * <P>Type: TEXT </P>
   1034 //         * read-only
   1035 //         */
   1036 //        public static final String CONTACT_ID = "contact_id";
   1037 
   1038         /**
   1039          * The presence state of contact, see {@link PresenceState}
   1040          * <P>Type: INTERGER</P>
   1041          * read-only
   1042          */
   1043         public static final String PRESENCE_STATE = "presence_state";
   1044 
   1045         /**
   1046          * The priority of contact presence
   1047          * <P>Type: INTERGER</P>
   1048          * read-only
   1049          */
   1050 // TODO: IS THIS NEEDED - not in latest specification
   1051         public static final String PRIORITY = "priority";
   1052 
   1053         /**
   1054          * The last status text from contact
   1055          * <P>Type: TEXT</P>
   1056          * read-only
   1057          */
   1058         public static final String STATUS_TEXT = "status_text";
   1059 
   1060         /**
   1061          * The time stamp of the last time the contact was online
   1062          * <P>Type: INTEGER (long)</P>
   1063          * read-only
   1064          */
   1065         public static final String LAST_ONLINE = "last_online";
   1066 
   1067     }
   1068 
   1069 
   1070     /**
   1071      * A projection of all the columns in the Message table
   1072      */
   1073     public static final String[] BT_MESSAGE_PROJECTION = new String[] {
   1074         MessageColumns._ID,
   1075         MessageColumns.DATE,
   1076         MessageColumns.SUBJECT,
   1077         //TODO REMOVE WHEN Parts Table is in place
   1078         MessageColumns.BODY,
   1079         MessageColumns.MESSAGE_SIZE,
   1080         MessageColumns.FOLDER_ID,
   1081         MessageColumns.FLAG_READ,
   1082         MessageColumns.FLAG_PROTECTED,
   1083         MessageColumns.FLAG_HIGH_PRIORITY,
   1084         MessageColumns.FLAG_ATTACHMENT,
   1085         MessageColumns.ATTACHMENT_SIZE,
   1086         MessageColumns.FROM_LIST,
   1087         MessageColumns.TO_LIST,
   1088         MessageColumns.CC_LIST,
   1089         MessageColumns.BCC_LIST,
   1090         MessageColumns.REPLY_TO_LIST,
   1091         MessageColumns.RECEPTION_STATE,
   1092         MessageColumns.DEVILERY_STATE,
   1093         MessageColumns.THREAD_ID
   1094     };
   1095 
   1096     public static final String[] BT_INSTANT_MESSAGE_PROJECTION = new String[] {
   1097         MessageColumns._ID,
   1098         MessageColumns.DATE,
   1099         MessageColumns.SUBJECT,
   1100         MessageColumns.MESSAGE_SIZE,
   1101         MessageColumns.FOLDER_ID,
   1102         MessageColumns.FLAG_READ,
   1103         MessageColumns.FLAG_PROTECTED,
   1104         MessageColumns.FLAG_HIGH_PRIORITY,
   1105         MessageColumns.FLAG_ATTACHMENT,
   1106         MessageColumns.ATTACHMENT_SIZE,
   1107         MessageColumns.ATTACHMENT_MINE_TYPES,
   1108         MessageColumns.FROM_LIST,
   1109         MessageColumns.TO_LIST,
   1110         MessageColumns.RECEPTION_STATE,
   1111         MessageColumns.DEVILERY_STATE,
   1112         MessageColumns.THREAD_ID,
   1113         MessageColumns.THREAD_NAME
   1114     };
   1115 
   1116     /**
   1117      * A projection of all the columns in the Account table
   1118      */
   1119     public static final String[] BT_ACCOUNT_PROJECTION = new String[] {
   1120         AccountColumns._ID,
   1121         AccountColumns.ACCOUNT_DISPLAY_NAME,
   1122         AccountColumns.FLAG_EXPOSE,
   1123     };
   1124 
   1125     /**
   1126      * A projection of all the columns in the Account table
   1127      * TODO: Is this the way to differentiate
   1128      */
   1129     public static final String[] BT_IM_ACCOUNT_PROJECTION = new String[] {
   1130         AccountColumns._ID,
   1131         AccountColumns.ACCOUNT_DISPLAY_NAME,
   1132         AccountColumns.FLAG_EXPOSE,
   1133         AccountColumns.ACCOUNT_UCI,
   1134         AccountColumns.ACCOUNT_UCI_PREFIX
   1135     };
   1136 
   1137     /**
   1138      * A projection of all the columns in the Folder table
   1139      */
   1140     public static final String[] BT_FOLDER_PROJECTION = new String[] {
   1141         FolderColumns._ID,
   1142         FolderColumns.NAME,
   1143         FolderColumns.ACCOUNT_ID,
   1144         FolderColumns.PARENT_FOLDER_ID
   1145     };
   1146 
   1147 
   1148     /**
   1149      * A projection of all the columns in the Conversation table
   1150      */
   1151     public static final String[] BT_CONVERSATION_PROJECTION = new String[] {
   1152         /* Thread information */
   1153         ConversationColumns.THREAD_ID,
   1154         ConversationColumns.THREAD_NAME,
   1155         ConversationColumns.READ_STATUS,
   1156         ConversationColumns.LAST_THREAD_ACTIVITY,
   1157         ConversationColumns.VERSION_COUNTER,
   1158         ConversationColumns.SUMMARY,
   1159         /* Contact information */
   1160         ConversationColumns.UCI,
   1161         ConversationColumns.NAME,
   1162         ConversationColumns.NICKNAME,
   1163         ConversationColumns.CHAT_STATE,
   1164         ConversationColumns.LAST_ACTIVE,
   1165         ConversationColumns.X_BT_UID,
   1166         ConversationColumns.PRESENCE_STATE,
   1167         ConversationColumns.STATUS_TEXT,
   1168         ConversationColumns.PRIORITY
   1169     };
   1170 
   1171     /**
   1172      * A projection of the Contact Info and Presence columns in the Contact Info in table
   1173      */
   1174     public static final String[] BT_CONTACT_CHATSTATE_PRESENCE_PROJECTION = new String[] {
   1175         ConvoContactColumns.UCI,
   1176         ConvoContactColumns.CONVO_ID,
   1177         ConvoContactColumns.NAME,
   1178         ConvoContactColumns.NICKNAME,
   1179         ConvoContactColumns.X_BT_UID,
   1180         ConvoContactColumns.CHAT_STATE,
   1181         ConvoContactColumns.LAST_ACTIVE,
   1182         ConvoContactColumns.PRESENCE_STATE,
   1183         ConvoContactColumns.PRIORITY,
   1184         ConvoContactColumns.STATUS_TEXT,
   1185         ConvoContactColumns.LAST_ONLINE
   1186     };
   1187 
   1188     /**
   1189      * A projection of the Contact Info the columns in Contacts Info table
   1190      */
   1191     public static final String[] BT_CONTACT_PROJECTION = new String[] {
   1192         ConvoContactColumns.UCI,
   1193         ConvoContactColumns.CONVO_ID,
   1194         ConvoContactColumns.X_BT_UID,
   1195         ConvoContactColumns.NAME,
   1196         ConvoContactColumns.NICKNAME
   1197     };
   1198 
   1199 
   1200     /**
   1201      * A projection of all the columns in the Chat Status table
   1202      */
   1203     public static final String[] BT_CHATSTATUS_PROJECTION = new String[] {
   1204         ChatStatusColumns.CHAT_STATE,
   1205         ChatStatusColumns.LAST_ACTIVE,
   1206     };
   1207 
   1208     /**
   1209      * A projection of all the columns in the Presence table
   1210      */
   1211     public static final String[] BT_PRESENCE_PROJECTION = new String[] {
   1212         PresenceColumns.PRESENCE_STATE,
   1213         PresenceColumns.PRIORITY,
   1214         PresenceColumns.STATUS_TEXT,
   1215         PresenceColumns.LAST_ONLINE
   1216     };
   1217 
   1218 }
   1219