UIProvider.java revision 36b6c8b6e87505ec106c7884e117db279d75c427
1/*******************************************************************************
2 *      Copyright (C) 2011 Google Inc.
3 *      Licensed to The Android Open Source Project.
4 *
5 *      Licensed under the Apache License, Version 2.0 (the "License");
6 *      you may not use this file except in compliance with the License.
7 *      You may obtain a copy of the License at
8 *
9 *           http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *      Unless required by applicable law or agreed to in writing, software
12 *      distributed under the License is distributed on an "AS IS" BASIS,
13 *      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *      See the License for the specific language governing permissions and
15 *      limitations under the License.
16 *******************************************************************************/
17
18package com.android.mail.providers;
19
20import android.content.Context;
21import android.provider.BaseColumns;
22import android.text.TextUtils;
23
24import com.android.common.contacts.DataUsageStatUpdater;
25
26import java.lang.String;
27import java.util.ArrayList;
28
29
30public class UIProvider {
31    public static final String EMAIL_SEPARATOR = "\n";
32    public static final long INVALID_CONVERSATION_ID = -1;
33    public static final long INVALID_MESSAGE_ID = -1;
34
35    // The actual content provider should define its own authority
36    public static final String AUTHORITY = "com.android.mail.providers";
37
38    public static final String ACCOUNT_LIST_TYPE =
39            "vnd.android.cursor.dir/vnd.com.android.mail.account";
40    public static final String ACCOUNT_TYPE =
41            "vnd.android.cursor.item/vnd.com.android.mail.account";
42
43    public static final String[] ACCOUNTS_PROJECTION = {
44            BaseColumns._ID,
45            AccountColumns.NAME,
46            AccountColumns.PROVIDER_VERSION,
47            AccountColumns.URI,
48            AccountColumns.CAPABILITIES,
49            AccountColumns.FOLDER_LIST_URI,
50            AccountColumns.SEARCH_URI,
51            AccountColumns.ACCOUNT_FROM_ADDRESSES_URI,
52            AccountColumns.SAVE_DRAFT_URI,
53            AccountColumns.SEND_MAIL_URI,
54            AccountColumns.EXPUNGE_MESSAGE_URI,
55            AccountColumns.UNDO_URI
56    };
57
58    public static final int ACCOUNT_ID_COLUMN = 0;
59    public static final int ACCOUNT_NAME_COLUMN = 1;
60    public static final int ACCOUNT_PROVIDER_VERISON_COLUMN = 2;
61    public static final int ACCOUNT_URI_COLUMN = 3;
62    public static final int ACCOUNT_CAPABILITIES_COLUMN = 4;
63    public static final int ACCOUNT_FOLDER_LIST_URI_COLUMN = 5;
64    public static final int ACCOUNT_SEARCH_URI_COLUMN = 6;
65    public static final int ACCOUNT_FROM_ADDRESSES_URI_COLUMN = 7;
66    public static final int ACCOUNT_SAVE_DRAFT_URI_COLUMN = 8;
67    public static final int ACCOUNT_SEND_MESSAGE_URI_COLUMN = 9;
68    public static final int ACCOUNT_EXPUNGE_MESSAGE_URI_COLUMN = 10;
69    public static final int ACCOUNT_UNDO_URI_COLUMN = 11;
70
71    public static final class AccountCapabilities {
72        /**
73         * Whether folders can be synchronized back to the server.
74         */
75        public static final int SYNCABLE_FOLDERS = 0x0001;
76        /**
77         * Whether the server allows reporting spam back.
78         */
79        public static final int REPORT_SPAM = 0x0002;
80        /**
81         * Whether the server supports a concept of Archive: removing mail from the Inbox but
82         * keeping it around.
83         */
84        public static final int ARCHIVE = 0x0004;
85        /**
86         * Whether the server will stop notifying on updates to this thread? This requires
87         * THREADED_CONVERSATIONS to be true, otherwise it should be ignored.
88         */
89        public static final int MUTE = 0x0008;
90        /**
91         * Whether the server supports searching over all messages. This requires SYNCABLE_FOLDERS
92         * to be true, otherwise it should be ignored.
93         */
94        public static final int SERVER_SEARCH = 0x0010;
95        /**
96         * Whether the server supports constraining search to a single folder. Requires
97         * SYNCABLE_FOLDERS, otherwise it should be ignored.
98         */
99        public static final int FOLDER_SERVER_SEARCH = 0x0020;
100        /**
101         * Whether the server sends us sanitized HTML (guaranteed to not contain malicious HTML).
102         */
103        public static final int SANITIZED_HTML = 0x0040;
104        /**
105         * Whether the server allows synchronization of draft messages. This does NOT require
106         * SYNCABLE_FOLDERS to be set.
107         */
108        public static final int DRAFT_SYNCHRONIZATION = 0x0080;
109        /**
110         * Does the server allow the user to compose mails (and reply) using addresses other than
111         * their account name? For instance, GMail allows users to set FROM addresses that are
112         * different from account@gmail.com address. For instance, user@gmail.com could have another
113         * FROM: address like user@android.com. If the user has enabled multiple FROM address, he
114         * can compose (and reply) using either address.
115         */
116        public static final int MULTIPLE_FROM_ADDRESSES = 0x0100;
117        /**
118         * Whether the server allows the original message to be included in the reply by setting a
119         * flag on the reply. If we can avoid including the entire previous message, we save on
120         * bandwidth (replies are shorter).
121         */
122        public static final int SMART_REPLY = 0x0200;
123        /**
124         * Does this account support searching locally, on the device? This requires the backend
125         * storage to support a mechanism for searching.
126         */
127        public static final int LOCAL_SEARCH = 0x0400;
128        /**
129         * Whether the server supports a notion of threaded conversations: where replies to messages
130         * are tagged to keep conversations grouped. This could be full threading (each message
131         * lists its parent) or conversation-level threading (each message lists one conversation
132         * which it belongs to)
133         */
134        public static final int THREADED_CONVERSATIONS = 0x0800;
135        /**
136         * Whether the server supports allowing a conversation to be in multiple folders. (Or allows
137         * multiple labels on a single conversation, since labels and folders are interchangeable
138         * in this application.)
139         */
140        public static final int MULTIPLE_FOLDERS_PER_CONV = 0x1000;
141    }
142
143    public static final class AccountColumns {
144        /**
145         * This string column contains the human visible name for the account.
146         */
147        public static final String NAME = "name";
148
149        /**
150         * This integer column returns the version of the UI provider schema from which this
151         * account provider will return results.
152         */
153        public static final String PROVIDER_VERSION = "providerVersion";
154
155        /**
156         * This string column contains the uri to directly access the information for this account.
157         */
158        public static final String URI = "accountUri";
159
160        /**
161         * This integer column contains a bit field of the possible cabibilities that this account
162         * supports.
163         */
164        public static final String CAPABILITIES = "capabilities";
165
166        /**
167         * This string column contains the content provider uri to return the
168         * list of top level folders for this account.
169         */
170        public static final String FOLDER_LIST_URI = "folderListUri";
171
172        /**
173         * This string column contains the content provider uri that can be queried for search
174         * results.
175         */
176        public static final String SEARCH_URI = "searchUri";
177
178        /**
179         * This string column contains the content provider uri that can be queried to access the
180         * from addresses for this account.
181         */
182        public static final String ACCOUNT_FROM_ADDRESSES_URI = "accountFromAddressesUri";
183
184        /**
185         * This string column contains the content provider uri that can be used to save (insert)
186         * new draft messages for this account. NOTE: This might be better to
187         * be an update operation on the messageUri.
188         */
189        public static final String SAVE_DRAFT_URI = "saveDraftUri";
190
191        /**
192         * This string column contains the content provider uri that can be used to send
193         * a message for this account.
194         * NOTE: This might be better to be an update operation on the messageUri.
195         */
196        public static final String SEND_MAIL_URI = "sendMailUri";
197
198        /**
199         * This string column contains the content provider uri that can be used
200         * to expunge a message from this account. NOTE: This might be better to
201         * be an update operation on the messageUri.
202         */
203        public static final String EXPUNGE_MESSAGE_URI = "expungeMessageUri";
204
205        /**
206         * This string column contains the content provider uri that can be used
207         * to undo the last committed action.
208         */
209        public static String UNDO_URI = "undoUri";
210    }
211
212    // We define a "folder" as anything that contains a list of conversations.
213    public static final String FOLDER_LIST_TYPE =
214            "vnd.android.cursor.dir/vnd.com.android.mail.folder";
215    public static final String FOLDER_TYPE =
216            "vnd.android.cursor.item/vnd.com.android.mail.folder";
217
218    public static final String[] FOLDERS_PROJECTION = {
219        BaseColumns._ID,
220        FolderColumns.URI,
221        FolderColumns.NAME,
222        FolderColumns.HAS_CHILDREN,
223        FolderColumns.CAPABILITIES,
224        FolderColumns.SYNC_FREQUENCY,
225        FolderColumns.SYNC_WINDOW,
226        FolderColumns.CONVERSATION_LIST_URI,
227        FolderColumns.CHILD_FOLDERS_LIST_URI,
228        FolderColumns.UNREAD_COUNT,
229        FolderColumns.TOTAL_COUNT,
230    };
231
232    public static final int FOLDER_ID_COLUMN = 0;
233    public static final int FOLDER_URI_COLUMN = 1;
234    public static final int FOLDER_NAME_COLUMN = 2;
235    public static final int FOLDER_HAS_CHILDREN_COLUMN = 3;
236    public static final int FOLDER_CAPABILITIES_COLUMN = 4;
237    public static final int FOLDER_SYNC_FREQUENCY_COLUMN = 5;
238    public static final int FOLDER_SYNC_WINDOW_COLUMN = 6;
239    public static final int FOLDER_CONVERSATION_LIST_URI_COLUMN = 7;
240    public static final int FOLDER_CHILD_FOLDERS_LIST_COLUMN = 8;
241    public static final int FOLDER_UNREAD_COUNT_COLUMN = 9;
242    public static final int FOLDER_TOTAL_COUNT_COLUMN = 10;
243
244    public static final class FolderCapabilities {
245        public static final int SYNCABLE = 0x0001;
246        public static final int PARENT = 0x0002;
247        public static final int CAN_HOLD_MAIL = 0x0004;
248        public static final int CAN_ACCEPT_MOVED_MESSAGES = 0x0008;
249    }
250
251    public static final class FolderColumns {
252        public static String URI = "folderUri";
253        /**
254         * This string column contains the human visible name for the folder.
255         */
256        public static final String NAME = "name";
257        /**
258         * This int column represents the capabilities of the folder specified by
259         * FolderCapabilities flags.
260         */
261        public static String CAPABILITIES = "capabilities";
262        /**
263         * This int column represents whether or not this folder has any
264         * child folders.
265         */
266        public static String HAS_CHILDREN = "hasChildren";
267        /**
268         * This int column represents how often the folder should be synchronized with the server.
269         */
270        public static String SYNC_FREQUENCY = "syncFrequency";
271        /**
272         * This int column represents how large the sync window is.
273         */
274        public static String SYNC_WINDOW = "syncWindow";
275        /**
276         * This string column contains the content provider uri to return the
277         * list of conversations for this folder.
278         */
279        public static final String CONVERSATION_LIST_URI = "conversationListUri";
280        /**
281         * This string column contains the content provider uri to return the
282         * list of child folders of this folder.
283         */
284        public static String CHILD_FOLDERS_LIST_URI = "childFoldersListUri";
285
286        public static String UNREAD_COUNT = "unreadCount";
287
288        public static String TOTAL_COUNT = "totalCount";
289
290        public FolderColumns() {}
291    }
292
293    // We define a "folder" as anything that contains a list of conversations.
294    public static final String CONVERSATION_LIST_TYPE =
295            "vnd.android.cursor.dir/vnd.com.android.mail.conversation";
296    public static final String CONVERSATION_TYPE =
297            "vnd.android.cursor.item/vnd.com.android.mail.conversation";
298
299
300    public static final String[] CONVERSATION_PROJECTION = {
301        BaseColumns._ID,
302        ConversationColumns.URI,
303        ConversationColumns.MESSAGE_LIST_URI,
304        ConversationColumns.SUBJECT,
305        ConversationColumns.SNIPPET,
306        ConversationColumns.SENDER_INFO,
307        ConversationColumns.DATE_RECEIVED_MS,
308        ConversationColumns.HAS_ATTACHMENTS,
309        ConversationColumns.NUM_MESSAGES,
310        ConversationColumns.NUM_DRAFTS,
311        ConversationColumns.SENDING_STATE,
312        ConversationColumns.PRIORITY,
313        ConversationColumns.READ,
314        ConversationColumns.STARRED,
315        ConversationColumns.FOLDER_LIST
316    };
317
318    // These column indexes only work when the caller uses the
319    // default CONVERSATION_PROJECTION defined above.
320    public static final int CONVERSATION_ID_COLUMN = 0;
321    public static final int CONVERSATION_URI_COLUMN = 1;
322    public static final int CONVERSATION_MESSAGE_LIST_URI_COLUMN = 2;
323    public static final int CONVERSATION_SUBJECT_COLUMN = 3;
324    public static final int CONVERSATION_SNIPPET_COLUMN = 4;
325    public static final int CONVERSATION_SENDER_INFO_COLUMN = 5;
326    public static final int CONVERSATION_DATE_RECEIVED_MS_COLUMN = 6;
327    public static final int CONVERSATION_HAS_ATTACHMENTS_COLUMN = 7;
328    public static final int CONVERSATION_NUM_MESSAGES_COLUMN = 8;
329    public static final int CONVERSATION_NUM_DRAFTS_COLUMN = 9;
330    public static final int CONVERSATION_SENDING_STATE_COLUMN = 10;
331    public static final int CONVERSATION_PRIORITY_COLUMN = 11;
332    public static final int CONVERSATION_READ_COLUMN = 12;
333    public static final int CONVERSATION_STARRED_COLUMN = 13;
334    public static final int CONVERSATION_FOLDER_LIST_COLUMN = 14;
335
336    public static final class ConversationSendingState {
337        public static final int OTHER = 0;
338        public static final int SENDING = 1;
339        public static final int SENT = 2;
340        public static final int SEND_ERROR = -1;
341    }
342
343    public static final class ConversationPriority {
344        public static final int LOW = 0;
345        public static final int HIGH = 1;
346    }
347
348    public static final class ConversationFlags {
349        public static final int READ = 1<<0;
350        public static final int STARRED = 1<<1;
351        public static final int REPLIED = 1<<2;
352        public static final int FORWARDED = 1<<3;
353    }
354
355    public static final class ConversationColumns {
356        public static final String URI = "conversationUri";
357        /**
358         * This string column contains the content provider uri to return the
359         * list of messages for this conversation.
360         */
361        public static final String MESSAGE_LIST_URI = "messageListUri";
362        /**
363         * This string column contains the subject string for a conversation.
364         */
365        public static final String SUBJECT = "subject";
366        /**
367         * This string column contains the snippet string for a conversation.
368         */
369        public static final String SNIPPET = "snippet";
370        /**
371         * This string column contains the sender info string for a
372         * conversation.
373         */
374        public static final String SENDER_INFO = "senderInfo";
375        /**
376         * This long column contains the time in ms of the latest update to a
377         * conversation.
378         */
379        public static final String DATE_RECEIVED_MS = "dateReceivedMs";
380
381        /**
382         * This boolean column contains whether any messages in this conversation
383         * have attachments.
384         */
385        public static final String HAS_ATTACHMENTS = "hasAttachments";
386
387        /**
388         * This int column contains the number of messages in this conversation.
389         * For unthreaded, this will always be 1.
390         */
391        public static String NUM_MESSAGES = "numMessages";
392
393        /**
394         * This int column contains the number of drafts associated with this
395         * conversation.
396         */
397        public static String NUM_DRAFTS = "numDrafts";
398
399        /**
400         * This int column contains the state of drafts and replies associated
401         * with this conversation. Use ConversationSendingState to interpret
402         * this field.
403         */
404        public static String SENDING_STATE = "sendingState";
405
406        /**
407         * This int column contains the priority of this conversation. Use
408         * ConversationPriority to interpret this field.
409         */
410        public static String PRIORITY = "priority";
411
412        /**
413         * This boolean column indicates whether the conversation has been read
414         */
415        public static String READ = "read";
416
417        /**
418         * This boolean column indicates whether the conversation has been read
419         */
420        public static String STARRED = "starred";
421
422        /**
423         * This string column contains a csv of all folders associated with this
424         * conversation
425         */
426        public static final String FOLDER_LIST = "folderList";
427
428        public ConversationColumns() {
429        }
430    }
431
432    /**
433     * Returns a uri that, when queried, will return a cursor with a list of information for the
434     * list of configured accounts.
435     * @return
436     */
437    // TODO: create a static registry for the starting point for the UI provider.
438//    public static Uri getAccountsUri() {
439//        return Uri.parse(BASE_URI_STRING + "/");
440//    }
441
442    public static final class DraftType {
443        public static final int NOT_A_DRAFT = 0;
444        public static final int COMPOSE = 1;
445        public static final int REPLY = 2;
446        public static final int REPLY_ALL = 3;
447        public static final int FORWARD = 4;
448
449        private DraftType() {}
450    }
451
452    public static final String[] MESSAGE_PROJECTION = {
453        BaseColumns._ID,
454        MessageColumns.SERVER_ID,
455        MessageColumns.URI,
456        MessageColumns.CONVERSATION_ID,
457        MessageColumns.SUBJECT,
458        MessageColumns.SNIPPET,
459        MessageColumns.FROM,
460        MessageColumns.TO,
461        MessageColumns.CC,
462        MessageColumns.BCC,
463        MessageColumns.REPLY_TO,
464        MessageColumns.DATE_RECEIVED_MS,
465        MessageColumns.BODY_HTML,
466        MessageColumns.BODY_TEXT,
467        MessageColumns.EMBEDS_EXTERNAL_RESOURCES,
468        MessageColumns.REF_MESSAGE_ID,
469        MessageColumns.DRAFT_TYPE,
470        MessageColumns.APPEND_REF_MESSAGE_CONTENT,
471        MessageColumns.HAS_ATTACHMENTS,
472        MessageColumns.ATTACHMENT_LIST_URI,
473        MessageColumns.MESSAGE_FLAGS,
474        MessageColumns.JOINED_ATTACHMENT_INFOS,
475        MessageColumns.SAVE_MESSAGE_URI,
476        MessageColumns.SEND_MESSAGE_URI
477    };
478
479    /** Separates attachment info parts in strings in a message. */
480    public static final String MESSAGE_ATTACHMENT_INFO_SEPARATOR = "\n";
481    public static final String MESSAGE_LIST_TYPE =
482            "vnd.android.cursor.dir/vnd.com.android.mail.message";
483    public static final String MESSAGE_TYPE =
484            "vnd.android.cursor.item/vnd.com.android.mail.message";
485
486    public static final int MESSAGE_ID_COLUMN = 0;
487    public static final int MESSAGE_SERVER_ID_COLUMN = 1;
488    public static final int MESSAGE_URI_COLUMN = 2;
489    public static final int MESSAGE_CONVERSATION_ID_COLUMN = 3;
490    public static final int MESSAGE_SUBJECT_COLUMN = 4;
491    public static final int MESSAGE_SNIPPET_COLUMN = 5;
492    public static final int MESSAGE_FROM_COLUMN = 6;
493    public static final int MESSAGE_TO_COLUMN = 7;
494    public static final int MESSAGE_CC_COLUMN = 8;
495    public static final int MESSAGE_BCC_COLUMN = 9;
496    public static final int MESSAGE_REPLY_TO_COLUMN = 10;
497    public static final int MESSAGE_DATE_RECEIVED_MS_COLUMN = 11;
498    public static final int MESSAGE_BODY_HTML_COLUMN = 12;
499    public static final int MESSAGE_BODY_TEXT_COLUMN = 13;
500    public static final int MESSAGE_EMBEDS_EXTERNAL_RESOURCES_COLUMN = 14;
501    public static final int MESSAGE_REF_MESSAGE_ID_COLUMN = 15;
502    public static final int MESSAGE_DRAFT_TYPE_COLUMN = 16;
503    public static final int MESSAGE_APPEND_REF_MESSAGE_CONTENT_COLUMN = 17;
504    public static final int MESSAGE_HAS_ATTACHMENTS_COLUMN = 18;
505    public static final int MESSAGE_ATTACHMENT_LIST_URI_COLUMN = 19;
506    public static final int MESSAGE_FLAGS_COLUMN = 20;
507    public static final int MESSAGE_JOINED_ATTACHMENT_INFOS_COLUMN = 21;
508    public static final int MESSAGE_SAVE_URI_COLUMN = 22;
509    public static final int MESSAGE_SEND_URI_COLUMN = 23;
510
511    public static final class MessageFlags {
512        public static final int STARRED =       1 << 0;
513        public static final int UNREAD =        1 << 1;
514        public static final int REPLIED =       1 << 2;
515        public static final int FORWARDED =     1 << 3;
516    }
517
518    public static final class MessageColumns {
519        /**
520         * This string column contains a content provider URI that points to this single message.
521         */
522        public static final String URI = "messageUri";
523        /**
524         * This string column contains a server-assigned ID for this message.
525         */
526        public static final String SERVER_ID = "serverMessageId";
527        public static final String CONVERSATION_ID = "conversationId";
528        /**
529         * This string column contains the subject of a message.
530         */
531        public static final String SUBJECT = "subject";
532        /**
533         * This string column contains a snippet of the message body.
534         */
535        public static final String SNIPPET = "snippet";
536        /**
537         * This string column contains the single email address (and optionally name) of the sender.
538         */
539        public static final String FROM = "fromAddress";
540        /**
541         * This string column contains a comma-delimited list of "To:" recipient email addresses.
542         */
543        public static final String TO = "toAddresses";
544        /**
545         * This string column contains a comma-delimited list of "CC:" recipient email addresses.
546         */
547        public static final String CC = "ccAddresses";
548        /**
549         * This string column contains a comma-delimited list of "BCC:" recipient email addresses.
550         * This value will be null for incoming messages.
551         */
552        public static final String BCC = "bccAddresses";
553        /**
554         * This string column contains the single email address (and optionally name) of the
555         * sender's reply-to address.
556         */
557        public static final String REPLY_TO = "replyToAddress";
558        /**
559         * This long column contains the timestamp (in millis) of receipt of the message.
560         */
561        public static final String DATE_RECEIVED_MS = "dateReceivedMs";
562        /**
563         * This string column contains the HTML form of the message body, if available. If not,
564         * a provider must populate BODY_TEXT.
565         */
566        public static final String BODY_HTML = "bodyHtml";
567        /**
568         * This string column contains the plaintext form of the message body, if HTML is not
569         * otherwise available. If HTML is available, this value should be left empty (null).
570         */
571        public static final String BODY_TEXT = "bodyText";
572        public static final String EMBEDS_EXTERNAL_RESOURCES = "bodyEmbedsExternalResources";
573        /**
574         * This string column contains an opaque string used by the sendMessage api.
575         */
576        public static final String REF_MESSAGE_ID = "refMessageId";
577        /**
578         * This integer column contains the type of this draft, or zero (0) if this message is not a
579         * draft. See {@link DraftType} for possible values.
580         */
581        public static final String DRAFT_TYPE = "draftType";
582        /**
583         * This boolean column indicates whether an outgoing message should trigger special quoted
584         * text processing upon send. The value should default to zero (0) for protocols that do
585         * not support or require this flag, and for all incoming messages.
586         */
587        public static final String APPEND_REF_MESSAGE_CONTENT = "appendRefMessageContent";
588        /**
589         * This boolean column indicates whether a message has attachments. The list of attachments
590         * can be retrieved using the URI in {@link MessageColumns#ATTACHMENT_LIST_URI}.
591         */
592        public static final String HAS_ATTACHMENTS = "hasAttachments";
593        /**
594         * This string column contains the content provider URI for the list of
595         * attachments associated with this message.
596         */
597        public static final String ATTACHMENT_LIST_URI = "attachmentListUri";
598        /**
599         * This long column is a bit field of flags defined in {@link MessageFlags}.
600         */
601        public static final String MESSAGE_FLAGS = "messageFlags";
602        /**
603         * This string column contains a specially formatted string representing all
604         * attachments that we added to a message that is being sent or saved.
605         */
606        public static final String JOINED_ATTACHMENT_INFOS = "joinedAttachmentInfos";
607        /**
608         * This string column contains the content provider URI for saving this
609         * message.
610         */
611        public static final String SAVE_MESSAGE_URI = "saveMessageUri";
612        /**
613         * This string column contains content provider URI for sending this
614         * message.
615         */
616        public static final String SEND_MESSAGE_URI = "sendMessageUri";
617
618        private MessageColumns() {}
619    }
620
621    // We define a "folder" as anything that contains a list of conversations.
622    public static final String ATTACHMENT_LIST_TYPE =
623            "vnd.android.cursor.dir/vnd.com.android.mail.attachment";
624    public static final String ATTACHMENT_TYPE =
625            "vnd.android.cursor.item/vnd.com.android.mail.attachment";
626
627    public static final String[] ATTACHMENT_PROJECTION = {
628        BaseColumns._ID,
629        AttachmentColumns.NAME,
630        AttachmentColumns.SIZE,
631        AttachmentColumns.URI,
632        AttachmentColumns.ORIGIN_EXTRAS,
633        AttachmentColumns.CONTENT_TYPE,
634        AttachmentColumns.SYNCED
635    };
636    private static final String EMAIL_SEPARATOR_PATTERN = "\n";
637    public static final int ATTACHMENT_ID_COLUMN = 0;
638    public static final int ATTACHMENT_NAME_COLUMN = 1;
639    public static final int ATTACHMENT_SIZE_COLUMN = 2;
640    public static final int ATTACHMENT_URI_COLUMN = 3;
641    public static final int ATTACHMENT_ORIGIN_EXTRAS_COLUMN = 4;
642    public static final int ATTACHMENT_CONTENT_TYPE_COLUMN = 5;
643    public static final int ATTACHMENT_SYNCED_COLUMN = 6;
644
645    public static final class AttachmentColumns {
646        public static final String NAME = "name";
647        public static final String SIZE = "size";
648        public static final String URI = "uri";
649        public static final String ORIGIN_EXTRAS = "originExtras";
650        public static final String CONTENT_TYPE = "contentType";
651        public static final String SYNCED = "synced";
652    }
653
654    public static int getMailMaxAttachmentSize(String account) {
655        // TODO: query the account to see what the max attachment size is?
656        return 5 * 1024 * 1024;
657    }
658
659    public static String getAttachmentTypeSetting() {
660        // TODO: query the account to see what kinds of attachments it supports?
661        return "com.google.android.gm.allowAddAnyAttachment";
662    }
663
664    public static void incrementRecipientsTimesContacted(Context context, String addressString) {
665        DataUsageStatUpdater statsUpdater = new DataUsageStatUpdater(context);
666        ArrayList<String> recipients = new ArrayList<String>();
667        String[] addresses = TextUtils.split(addressString, EMAIL_SEPARATOR_PATTERN);
668        for (String address : addresses) {
669            recipients.add(address);
670        }
671        statsUpdater.updateWithAddress(recipients);
672    }
673
674    public static final String[] UNDO_PROJECTION = {
675        ConversationColumns.MESSAGE_LIST_URI
676    };
677    public static final int UNDO_MESSAGE_LIST_COLUMN = 0;
678
679    // Parameter used to indicate the sequence number for an undoable operation
680    public static final String SEQUENCE_QUERY_PARAMETER = "seq";
681}
682