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      */
BluetoothMapContract()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      */
buildAccountUri(String authority)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      */
buildAccountUriwithId(String authority, String accountId)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      */
buildMessageUri(String authority)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      */
buildMessageUri(String authority, String accountId)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      */
buildMessageUriWithId(String authority, String accountId, String messageId)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      */
buildFolderUri(String authority, String accountId)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      */
buildConversationUri(String authority, String accountId)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      */
buildConvoContactsUri(String authority)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      */
buildConvoContactsUri(String authority, String accountId)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      */
buildConvoContactsUriWithId(String authority, String accountId, String contactId)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@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