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