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