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