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).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