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"><provider android:authorities="[PROVIDER AUTHORITY]" 46 * android:exported="true" 47 * android:enabled="true" 48 * android:permission="android.permission.BLUETOOTH_MAP"> 49 * ... 50 * <intent-filter> 51 * <action android:name="android.content.action.BLEUETOOT_MAP_PROVIDER" /> 52 * </intent-filter> 53 * ... 54 * </provider> 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