diff --git a/core/java/android/provider/Gmail.java b/core/java/android/provider/Gmail.java
deleted file mode 100644
index 8bb7adf..0000000
--- a/core/java/android/provider/Gmail.java
+++ /dev/null
@@ -1,2468 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.provider;
-
-import com.google.android.collect.Lists;
-import com.google.android.collect.Maps;
-import com.google.android.collect.Sets;
-
-import android.content.AsyncQueryHandler;
-import android.content.ContentQueryMap;
-import android.content.ContentResolver;
-import android.content.ContentUris;
-import android.content.ContentValues;
-import android.database.ContentObserver;
-import android.database.Cursor;
-import android.database.DataSetObserver;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Handler;
-import android.text.Html;
-import android.text.SpannableStringBuilder;
-import android.text.Spanned;
-import android.text.TextUtils;
-import android.text.TextUtils.SimpleStringSplitter;
-import android.text.style.CharacterStyle;
-import android.util.Log;
-
-import com.android.common.Patterns;
-
-import java.io.UnsupportedEncodingException;
-import java.net.URLEncoder;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Observable;
-import java.util.Observer;
-import java.util.Set;
-import java.util.SortedSet;
-import java.util.TreeSet;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * A thin wrapper over the content resolver for accessing the gmail provider.
- *
- * @hide
- */
-public final class Gmail {
-    // Set to true to enable extra debugging.
-    private static final boolean DEBUG = false;
-
-    public static final String GMAIL_AUTH_SERVICE = "mail";
-    // These constants come from google3/java/com/google/caribou/backend/MailLabel.java.
-    public static final String LABEL_SENT = "^f";
-    public static final String LABEL_INBOX = "^i";
-    public static final String LABEL_DRAFT = "^r";
-    public static final String LABEL_UNREAD = "^u";
-    public static final String LABEL_TRASH = "^k";
-    public static final String LABEL_SPAM = "^s";
-    public static final String LABEL_STARRED = "^t";
-    public static final String LABEL_CHAT = "^b"; // 'b' for 'buzz'
-    public static final String LABEL_VOICEMAIL = "^vm";
-    public static final String LABEL_IGNORED = "^g";
-    public static final String LABEL_ALL = "^all";
-    // These constants (starting with "^^") are only used locally and are not understood by the
-    // server.
-    public static final String LABEL_VOICEMAIL_INBOX = "^^vmi";
-    public static final String LABEL_CACHED = "^^cached";
-    public static final String LABEL_OUTBOX = "^^out";
-
-    public static final String AUTHORITY = "gmail-ls";
-    private static final String TAG = "Gmail";
-    private static final String AUTHORITY_PLUS_CONVERSATIONS =
-            "content://" + AUTHORITY + "/conversations/";
-    private static final String AUTHORITY_PLUS_LABELS =
-            "content://" + AUTHORITY + "/labels/";
-    private static final String AUTHORITY_PLUS_MESSAGES =
-            "content://" + AUTHORITY + "/messages/";
-    private static final String AUTHORITY_PLUS_SETTINGS =
-            "content://" + AUTHORITY + "/settings/";
-
-    public static final Uri BASE_URI = Uri.parse(
-            "content://" + AUTHORITY);
-    private static final Uri LABELS_URI =
-            Uri.parse(AUTHORITY_PLUS_LABELS);
-    private static final Uri CONVERSATIONS_URI =
-            Uri.parse(AUTHORITY_PLUS_CONVERSATIONS);
-    private static final Uri SETTINGS_URI =
-            Uri.parse(AUTHORITY_PLUS_SETTINGS);
-
-    /** Separates email addresses in strings in the database. */
-    public static final String EMAIL_SEPARATOR = "\n";
-    public static final Pattern EMAIL_SEPARATOR_PATTERN = Pattern.compile(EMAIL_SEPARATOR);
-
-    /**
-     * Space-separated lists have separators only between items.
-     */
-    private static final char SPACE_SEPARATOR = ' ';
-    public static final Pattern SPACE_SEPARATOR_PATTERN = Pattern.compile(" ");
-
-    /**
-     * Comma-separated lists have separators between each item, before the first and after the last
-     * item. The empty list is <tt>,</tt>.
-     *
-     * <p>This makes them easier to modify with SQL since it is not a special case to add or
-     * remove the last item. Having a separator on each side of each value also makes it safe to use
-     * SQL's REPLACE to remove an item from a string by using REPLACE(',value,', ',').
-     *
-     * <p>We could use the same separator for both lists but this makes it easier to remember which
-     * kind of list one is dealing with.
-     */
-    private static final char COMMA_SEPARATOR = ',';
-    public static final Pattern COMMA_SEPARATOR_PATTERN = Pattern.compile(",");
-
-    /** Separates attachment info parts in strings in the database. */
-    public static final String ATTACHMENT_INFO_SEPARATOR = "\n";
-    public static final Pattern ATTACHMENT_INFO_SEPARATOR_PATTERN =
-            Pattern.compile(ATTACHMENT_INFO_SEPARATOR);
-
-    public static final Character SENDER_LIST_SEPARATOR = '\n';
-    public static final String SENDER_LIST_TOKEN_ELIDED = "e";
-    public static final String SENDER_LIST_TOKEN_NUM_MESSAGES = "n";
-    public static final String SENDER_LIST_TOKEN_NUM_DRAFTS = "d";
-    public static final String SENDER_LIST_TOKEN_LITERAL = "l";
-    public static final String SENDER_LIST_TOKEN_SENDING = "s";
-    public static final String SENDER_LIST_TOKEN_SEND_FAILED = "f";
-
-    /** Used for finding status in a cursor's extras. */
-    public static final String EXTRA_STATUS = "status";
-
-    public static final String RESPOND_INPUT_COMMAND = "command";
-    public static final String COMMAND_RETRY = "retry";
-    public static final String COMMAND_ACTIVATE = "activate";
-    public static final String COMMAND_SET_VISIBLE = "setVisible";
-    public static final String SET_VISIBLE_PARAM_VISIBLE = "visible";
-    public static final String RESPOND_OUTPUT_COMMAND_RESPONSE = "commandResponse";
-    public static final String COMMAND_RESPONSE_OK =  "ok";
-    public static final String COMMAND_RESPONSE_UNKNOWN =  "unknownCommand";
-
-    public static final String INSERT_PARAM_ATTACHMENT_ORIGIN = "origin";
-    public static final String INSERT_PARAM_ATTACHMENT_ORIGIN_EXTRAS = "originExtras";
-
-    private static final Pattern NAME_ADDRESS_PATTERN = Pattern.compile("\"(.*)\"");
-    private static final Pattern UNNAMED_ADDRESS_PATTERN = Pattern.compile("([^<]+)@");
-
-    private static final Map<Integer, Integer> sPriorityToLength = Maps.newHashMap();
-    public static final SimpleStringSplitter sSenderListSplitter = 
-            new SimpleStringSplitter(SENDER_LIST_SEPARATOR);
-    public static String[] sSenderFragments = new String[8];
-
-    /**
-     * Returns the name in an address string
-     * @param addressString such as &quot;bobby&quot; &lt;bob@example.com&gt;
-     * @return returns the quoted name in the addressString, otherwise the username from the email
-     *   address
-     */
-    public static String getNameFromAddressString(String addressString) {
-        Matcher namedAddressMatch = NAME_ADDRESS_PATTERN.matcher(addressString);
-        if (namedAddressMatch.find()) {
-            String name = namedAddressMatch.group(1);
-            if (name.length() > 0) return name;
-            addressString =
-                    addressString.substring(namedAddressMatch.end(), addressString.length());
-        }
-
-        Matcher unnamedAddressMatch = UNNAMED_ADDRESS_PATTERN.matcher(addressString);
-        if (unnamedAddressMatch.find()) {
-            return unnamedAddressMatch.group(1);
-        }
-
-        return addressString;
-    }
-
-    /**
-     * Returns the email address in an address string
-     * @param addressString such as &quot;bobby&quot; &lt;bob@example.com&gt;
-     * @return returns the email address, such as bob@example.com from the example above
-     */
-    public static String getEmailFromAddressString(String addressString) {
-        String result = addressString;
-        Matcher match = Patterns.EMAIL_ADDRESS.matcher(addressString);
-        if (match.find()) {
-            result = addressString.substring(match.start(), match.end());
-        }
-
-        return result;
-    }
-
-    /**
-     * Returns whether the label is user-defined (versus system-defined labels such as inbox, whose
-     * names start with "^").
-     */
-    public static boolean isLabelUserDefined(String label) {
-        // TODO: label should never be empty so we should be able to say [label.charAt(0) != '^'].
-        // However, it's a release week and I'm too scared to make that change.
-        return !label.startsWith("^");
-    }
-
-    private static final Set<String> USER_SETTABLE_BUILTIN_LABELS = Sets.newHashSet(
-            Gmail.LABEL_INBOX,
-            Gmail.LABEL_UNREAD,
-            Gmail.LABEL_TRASH,
-            Gmail.LABEL_SPAM,
-            Gmail.LABEL_STARRED,
-            Gmail.LABEL_IGNORED);
-
-    /**
-     * Returns whether the label is user-settable. For example, labels such as LABEL_DRAFT should
-     * only be set internally.
-     */
-    public static boolean isLabelUserSettable(String label) {
-        return USER_SETTABLE_BUILTIN_LABELS.contains(label) || isLabelUserDefined(label);
-    }
-
-    /**
-     * Returns the set of labels using the raw labels from a previous getRawLabels()
-     * as input.
-     * @return a copy of the set of labels. To add or remove labels call
-     * MessageCursor.addOrRemoveLabel on each message in the conversation.
-     */
-    public static Set<Long> getLabelIdsFromLabelIdsString(
-            TextUtils.StringSplitter splitter) {
-        Set<Long> labelIds = Sets.newHashSet();
-        for (String labelIdString : splitter) {
-            labelIds.add(Long.valueOf(labelIdString));
-        }
-        return labelIds;
-    }
-
-    /**
-     * @deprecated remove when the activities stop using canonical names to identify labels
-     */
-    public static Set<String> getCanonicalNamesFromLabelIdsString(
-            LabelMap labelMap, TextUtils.StringSplitter splitter) {
-        Set<String> canonicalNames = Sets.newHashSet();
-        for (long labelId : getLabelIdsFromLabelIdsString(splitter)) {
-            final String canonicalName = labelMap.getCanonicalName(labelId);
-            // We will sometimes see labels that the label map does not yet know about or that
-            // do not have names yet.
-            if (!TextUtils.isEmpty(canonicalName)) {
-                canonicalNames.add(canonicalName);
-            } else {
-                Log.w(TAG, "getCanonicalNamesFromLabelIdsString skipping label id: " + labelId);
-            }
-        }
-        return canonicalNames;
-    }
-
-    /**
-     * @return a StringSplitter that is configured to split message label id strings
-     */
-    public static TextUtils.StringSplitter newMessageLabelIdsSplitter() {
-        return new TextUtils.SimpleStringSplitter(SPACE_SEPARATOR);
-    }
-
-    /**
-     * @return a StringSplitter that is configured to split conversation label id strings
-     */
-    public static TextUtils.StringSplitter newConversationLabelIdsSplitter() {
-        return new CommaStringSplitter();
-    }
-
-    /**
-     * A splitter for strings of the form described in the docs for COMMA_SEPARATOR.
-     */
-    private static class CommaStringSplitter extends TextUtils.SimpleStringSplitter {
-
-        public CommaStringSplitter() {
-            super(COMMA_SEPARATOR);
-        }
-
-        @Override
-        public void setString(String string) {
-            // The string should always be at least a single comma.
-            super.setString(string.substring(1));
-        }
-    }
-
-    /**
-     * Creates a single string of the form that getLabelIdsFromLabelIdsString can split.
-     */
-    public static String getLabelIdsStringFromLabelIds(Set<Long> labelIds) {
-        StringBuilder sb = new StringBuilder();
-        sb.append(COMMA_SEPARATOR);
-        for (Long labelId : labelIds) {
-            sb.append(labelId);
-            sb.append(COMMA_SEPARATOR);
-        }
-        return sb.toString();
-    }
-
-    public static final class ConversationColumns {
-        public static final String ID = "_id";
-        public static final String SUBJECT = "subject";
-        public static final String SNIPPET = "snippet";
-        public static final String FROM = "fromAddress";
-        public static final String DATE = "date";
-        public static final String PERSONAL_LEVEL = "personalLevel";
-        /** A list of label names with a space after each one (including the last one). This makes
-         * it easier remove individual labels from this list using SQL. */
-        public static final String LABEL_IDS = "labelIds";
-        public static final String NUM_MESSAGES = "numMessages";
-        public static final String MAX_MESSAGE_ID = "maxMessageId";
-        public static final String HAS_ATTACHMENTS = "hasAttachments";
-        public static final String HAS_MESSAGES_WITH_ERRORS = "hasMessagesWithErrors";
-        public static final String FORCE_ALL_UNREAD = "forceAllUnread";
-
-        private ConversationColumns() {}
-    }
-
-    public static final class MessageColumns {
-
-        public static final String ID = "_id";
-        public static final String MESSAGE_ID = "messageId";
-        public static final String CONVERSATION_ID = "conversation";
-        public static final String SUBJECT = "subject";
-        public static final String SNIPPET = "snippet";
-        public static final String FROM = "fromAddress";
-        public static final String TO = "toAddresses";
-        public static final String CC = "ccAddresses";
-        public static final String BCC = "bccAddresses";
-        public static final String REPLY_TO = "replyToAddresses";
-        public static final String DATE_SENT_MS = "dateSentMs";
-        public static final String DATE_RECEIVED_MS = "dateReceivedMs";
-        public static final String LIST_INFO = "listInfo";
-        public static final String PERSONAL_LEVEL = "personalLevel";
-        public static final String BODY = "body";
-        public static final String EMBEDS_EXTERNAL_RESOURCES = "bodyEmbedsExternalResources";
-        public static final String LABEL_IDS = "labelIds";
-        public static final String JOINED_ATTACHMENT_INFOS = "joinedAttachmentInfos";
-        public static final String ERROR = "error";
-        // TODO: add a method for accessing this
-        public static final String REF_MESSAGE_ID = "refMessageId";
-
-        // Fake columns used only for saving or sending messages.
-        public static final String FAKE_SAVE = "save";
-        public static final String FAKE_REF_MESSAGE_ID = "refMessageId";
-
-        private MessageColumns() {}
-    }
-
-    public static final class LabelColumns {
-        public static final String CANONICAL_NAME = "canonicalName";
-        public static final String NAME = "name";
-        public static final String NUM_CONVERSATIONS = "numConversations";
-        public static final String NUM_UNREAD_CONVERSATIONS =
-                "numUnreadConversations";
-
-        private LabelColumns() {}
-    }
-
-    public static final class SettingsColumns {
-        public static final String LABELS_INCLUDED = "labelsIncluded";
-        public static final String LABELS_PARTIAL = "labelsPartial";
-        public static final String CONVERSATION_AGE_DAYS =
-                "conversationAgeDays";
-        public static final String MAX_ATTACHMENET_SIZE_MB =
-                "maxAttachmentSize";
-    }
-
-    /**
-     * These flags can be included as Selection Arguments when
-     * querying the provider.
-     */
-    public static class SelectionArguments {
-        private SelectionArguments() {
-            // forbid instantiation
-        }
-
-        /**
-         * Specifies that you do NOT wish the returned cursor to
-         * become the Active Network Cursor.  If you do not include
-         * this flag as a selectionArg, the new cursor will become the
-         * Active Network Cursor by default.
-         */
-        public static final String DO_NOT_BECOME_ACTIVE_NETWORK_CURSOR =
-                "SELECTION_ARGUMENT_DO_NOT_BECOME_ACTIVE_NETWORK_CURSOR";
-    }
-
-    // These are the projections that we need when getting cursors from the
-    // content provider.
-    private static String[] CONVERSATION_PROJECTION = {
-            ConversationColumns.ID,
-            ConversationColumns.SUBJECT,
-            ConversationColumns.SNIPPET,
-            ConversationColumns.FROM,
-            ConversationColumns.DATE,
-            ConversationColumns.PERSONAL_LEVEL,
-            ConversationColumns.LABEL_IDS,
-            ConversationColumns.NUM_MESSAGES,
-            ConversationColumns.MAX_MESSAGE_ID,
-            ConversationColumns.HAS_ATTACHMENTS,
-            ConversationColumns.HAS_MESSAGES_WITH_ERRORS,
-            ConversationColumns.FORCE_ALL_UNREAD};
-    private static String[] MESSAGE_PROJECTION = {
-            MessageColumns.ID,
-            MessageColumns.MESSAGE_ID,
-            MessageColumns.CONVERSATION_ID,
-            MessageColumns.SUBJECT,
-            MessageColumns.SNIPPET,
-            MessageColumns.FROM,
-            MessageColumns.TO,
-            MessageColumns.CC,
-            MessageColumns.BCC,
-            MessageColumns.REPLY_TO,
-            MessageColumns.DATE_SENT_MS,
-            MessageColumns.DATE_RECEIVED_MS,
-            MessageColumns.LIST_INFO,
-            MessageColumns.PERSONAL_LEVEL,
-            MessageColumns.BODY,
-            MessageColumns.EMBEDS_EXTERNAL_RESOURCES,
-            MessageColumns.LABEL_IDS,
-            MessageColumns.JOINED_ATTACHMENT_INFOS,
-            MessageColumns.ERROR};
-    private static String[] LABEL_PROJECTION = {
-            BaseColumns._ID,
-            LabelColumns.CANONICAL_NAME,
-            LabelColumns.NAME,
-            LabelColumns.NUM_CONVERSATIONS,
-            LabelColumns.NUM_UNREAD_CONVERSATIONS};
-    private static String[] SETTINGS_PROJECTION = {
-            SettingsColumns.LABELS_INCLUDED,
-            SettingsColumns.LABELS_PARTIAL,
-            SettingsColumns.CONVERSATION_AGE_DAYS,
-            SettingsColumns.MAX_ATTACHMENET_SIZE_MB,
-    };
-
-    private ContentResolver mContentResolver;
-
-    public Gmail(ContentResolver contentResolver) {
-        mContentResolver = contentResolver;
-    }
-
-    /**
-     * Returns source if source is non-null. Returns the empty string otherwise.
-     */
-    private static String toNonnullString(String source) {
-        if (source == null) {
-            return "";
-        } else {
-            return source;
-        }
-    }
-
-    /**
-     * Behavior for a new cursor: should it become the Active Network
-     * Cursor?  This could potentially lead to bad behavior if someone
-     * else is using the Active Network Cursor, since theirs will stop
-     * being the Active Network Cursor.
-     */
-    public static enum BecomeActiveNetworkCursor {
-        /**
-         * The new cursor should become the one and only Active
-         * Network Cursor.  Any other cursor that might already be the
-         * Active Network Cursor will cease to be so.
-         */
-        YES,
-
-        /**
-         * The new cursor should not become the Active Network
-         * Cursor. Any other cursor that might already be the Active
-         * Network Cursor will continue to be so.
-         */
-        NO
-    }
-
-    /**
-     * Wraps a Cursor in a ConversationCursor
-     *
-     * @param account the account the cursor is associated with
-     * @param cursor The Cursor to wrap
-     * @return a new ConversationCursor
-     */
-    public ConversationCursor getConversationCursorForCursor(String account, Cursor cursor) {
-        if (TextUtils.isEmpty(account)) {
-            throw new IllegalArgumentException("account is empty");
-        }
-        return new ConversationCursor(this, account, cursor);
-    }
-
-    /**
-     * Creates an array of SelectionArguments suitable for passing to the provider's query.
-     * Currently this only handles one flag, but it could be expanded in the future.
-     */
-    private static String[] getSelectionArguments(
-            BecomeActiveNetworkCursor becomeActiveNetworkCursor) {
-        if (BecomeActiveNetworkCursor.NO == becomeActiveNetworkCursor) {
-            return new String[] {SelectionArguments.DO_NOT_BECOME_ACTIVE_NETWORK_CURSOR};
-        } else {
-            // Default behavior; no args required.
-            return null;
-        }
-    }
-
-    /**
-     * Asynchronously gets a cursor over all conversations matching a query. The
-     * query is in Gmail's query syntax. When the operation is complete the handler's
-     * onQueryComplete() method is called with the resulting Cursor.
-     *
-     * @param account run the query on this account
-     * @param handler An AsyncQueryHanlder that will be used to run the query
-     * @param token The token to pass to startQuery, which will be passed back to onQueryComplete
-     * @param query a query in Gmail's query syntax
-     * @param becomeActiveNetworkCursor whether or not the returned
-     * cursor should become the Active Network Cursor
-     */
-    public void runQueryForConversations(String account, AsyncQueryHandler handler, int token,
-            String query, BecomeActiveNetworkCursor becomeActiveNetworkCursor) {
-        if (TextUtils.isEmpty(account)) {
-            throw new IllegalArgumentException("account is empty");
-        }
-        String[] selectionArgs = getSelectionArguments(becomeActiveNetworkCursor);
-        handler.startQuery(token, null, Uri.withAppendedPath(CONVERSATIONS_URI, account),
-                CONVERSATION_PROJECTION, query, selectionArgs, null);
-    }
-
-    /**
-     * Synchronously gets a cursor over all conversations matching a query. The
-     * query is in Gmail's query syntax.
-     *
-     * @param account run the query on this account
-     * @param query a query in Gmail's query syntax
-     * @param becomeActiveNetworkCursor whether or not the returned
-     * cursor should become the Active Network Cursor
-     */
-    public ConversationCursor getConversationCursorForQuery(
-            String account, String query, BecomeActiveNetworkCursor becomeActiveNetworkCursor) {
-        String[] selectionArgs = getSelectionArguments(becomeActiveNetworkCursor);
-        Cursor cursor = mContentResolver.query(
-                Uri.withAppendedPath(CONVERSATIONS_URI, account), CONVERSATION_PROJECTION,
-                query, selectionArgs, null);
-        return new ConversationCursor(this, account, cursor);
-    }
-
-    /**
-     * Gets a message cursor over the single message with the given id.
-     *
-     * @param account get the cursor for messages in this account
-     * @param messageId the id of the message
-     * @return a cursor over the message
-     */
-    public MessageCursor getMessageCursorForMessageId(String account, long messageId) {
-        if (TextUtils.isEmpty(account)) {
-            throw new IllegalArgumentException("account is empty");
-        }
-        Uri uri = Uri.parse(AUTHORITY_PLUS_MESSAGES + account + "/" + messageId);
-        Cursor cursor = mContentResolver.query(uri, MESSAGE_PROJECTION, null, null, null);
-        return new MessageCursor(this, mContentResolver, account, cursor);
-    }
-
-    /**
-     * Gets a message cursor over the messages that match the query. Note that
-     * this simply finds all of the messages that match and returns them. It
-     * does not return all messages in conversations where any message matches.
-     *
-     * @param account get the cursor for messages in this account
-     * @param query a query in GMail's query syntax. Currently only queries of
-     *     the form [label:<label>] are supported
-     * @return a cursor over the messages
-     */
-    public MessageCursor getLocalMessageCursorForQuery(String account, String query) {
-        if (TextUtils.isEmpty(account)) {
-            throw new IllegalArgumentException("account is empty");
-        }
-        Uri uri = Uri.parse(AUTHORITY_PLUS_MESSAGES + account + "/");
-        Cursor cursor = mContentResolver.query(uri, MESSAGE_PROJECTION, query, null, null);
-        return new MessageCursor(this, mContentResolver, account, cursor);
-    }
-
-    /**
-     * Gets a cursor over all of the messages in a conversation.
-     *
-     * @param account get the cursor for messages in this account
-     * @param conversationId the id of the converstion to fetch messages for
-     * @return a cursor over messages in the conversation
-     */
-    public MessageCursor getMessageCursorForConversationId(String account, long conversationId) {
-        if (TextUtils.isEmpty(account)) {
-            throw new IllegalArgumentException("account is empty");
-        }
-        Uri uri = Uri.parse(
-                AUTHORITY_PLUS_CONVERSATIONS + account + "/" + conversationId + "/messages");
-        Cursor cursor = mContentResolver.query(
-                uri, MESSAGE_PROJECTION, null, null, null);
-        return new MessageCursor(this, mContentResolver, account, cursor);
-    }
-
-    /**
-     * Expunge the indicated message. One use of this is to discard drafts.
-     *
-     * @param account the account of the message id
-     * @param messageId the id of the message to expunge
-     */
-    public void expungeMessage(String account, long messageId) {
-        if (TextUtils.isEmpty(account)) {
-            throw new IllegalArgumentException("account is empty");
-        }
-        Uri uri = Uri.parse(AUTHORITY_PLUS_MESSAGES + account + "/" + messageId);
-        mContentResolver.delete(uri, null, null);
-    }
-
-    /**
-     * Adds or removes the label on the conversation.
-     *
-     * @param account the account of the conversation
-     * @param conversationId the conversation
-     * @param maxServerMessageId the highest message id to whose labels should be changed. Note that
-     *   everywhere else in this file messageId means local message id but here you need to use a
-     *   server message id.
-     * @param label the label to add or remove
-     * @param add true to add the label, false to remove it
-     */
-    public void addOrRemoveLabelOnConversation(
-            String account, long conversationId, long maxServerMessageId, String label,
-            boolean add) {
-        if (TextUtils.isEmpty(account)) {
-            throw new IllegalArgumentException("account is empty");
-        }
-        if (add) {
-            Uri uri = Uri.parse(
-                    AUTHORITY_PLUS_CONVERSATIONS + account + "/" + conversationId + "/labels");
-            ContentValues values = new ContentValues();
-            values.put(LabelColumns.CANONICAL_NAME, label);
-            values.put(ConversationColumns.MAX_MESSAGE_ID, maxServerMessageId);
-            mContentResolver.insert(uri, values);
-        } else {
-            String encodedLabel;
-            try {
-                encodedLabel = URLEncoder.encode(label, "utf-8");
-            } catch (UnsupportedEncodingException e) {
-                throw new RuntimeException(e);
-            }
-            Uri uri = Uri.parse(
-                    AUTHORITY_PLUS_CONVERSATIONS + account + "/"
-                            + conversationId + "/labels/" + encodedLabel);
-            mContentResolver.delete(
-                    uri, ConversationColumns.MAX_MESSAGE_ID, new String[]{"" + maxServerMessageId});
-        }
-    }
-
-    /**
-     * Adds or removes the label on the message.
-     *
-     * @param contentResolver the content resolver.
-     * @param account the account of the message
-     * @param conversationId the conversation containing the message
-     * @param messageId the id of the message to whose labels should be changed
-     * @param label the label to add or remove
-     * @param add true to add the label, false to remove it
-     */
-    public static void addOrRemoveLabelOnMessage(ContentResolver contentResolver, String account,
-            long conversationId, long messageId, String label, boolean add) {
-
-        // conversationId is unused but we want to start passing it whereever we pass a message id.
-        if (add) {
-            Uri uri = Uri.parse(
-                    AUTHORITY_PLUS_MESSAGES + account + "/" + messageId + "/labels");
-            ContentValues values = new ContentValues();
-            values.put(LabelColumns.CANONICAL_NAME, label);
-            contentResolver.insert(uri, values);
-        } else {
-            String encodedLabel;
-            try {
-                encodedLabel = URLEncoder.encode(label, "utf-8");
-            } catch (UnsupportedEncodingException e) {
-                throw new RuntimeException(e);
-            }
-            Uri uri = Uri.parse(
-                    AUTHORITY_PLUS_MESSAGES + account + "/" + messageId
-                    + "/labels/" + encodedLabel);
-            contentResolver.delete(uri, null, null);
-        }
-    }
-
-    /**
-     * The mail provider will send an intent when certain changes happen in certain labels.
-     * Currently those labels are inbox and voicemail.
-     *
-     * <p>The intent will have the action ACTION_PROVIDER_CHANGED and the extras mentioned below.
-     * The data for the intent will be content://gmail-ls/unread/<name of label>.
-     *
-     * <p>The goal is to support the following user experience:<ul>
-     *   <li>When present the new mail indicator reports the number of unread conversations in the
-     *   inbox (or some other label).</li>
-     *   <li>When the user views the inbox the indicator is removed immediately. They do not have to
-     *   read all of the conversations.</li>
-     *   <li>If more mail arrives the indicator reappears and shows the total number of unread
-     *   conversations in the inbox.</li>
-     *   <li>If the user reads the new conversations on the web the indicator disappears on the
-     *   phone since there is no unread mail in the inbox that the user hasn't seen.</li>
-     *   <li>The phone should vibrate/etc when it transitions from having no unseen unread inbox
-     *   mail to having some.</li>
-     */
-
-    /** The account in which the change occurred. */
-    static public final String PROVIDER_CHANGED_EXTRA_ACCOUNT = "account";
-
-    /** The number of unread conversations matching the label. */
-    static public final String PROVIDER_CHANGED_EXTRA_COUNT = "count";
-
-    /** Whether to get the user's attention, perhaps by vibrating. */
-    static public final String PROVIDER_CHANGED_EXTRA_GET_ATTENTION = "getAttention";
-
-    /**
-     * A label that is attached to all of the conversations being notified about. This enables the
-     * receiver of a notification to get a list of matching conversations.
-     */
-    static public final String PROVIDER_CHANGED_EXTRA_TAG_LABEL = "tagLabel";
-
-    /**
-     * Settings for which conversations should be synced to the phone.
-     * Conversations are synced if any message matches any of the following
-     * criteria:
-     *
-     * <ul>
-     *   <li>the message has a label in the include set</li>
-     *   <li>the message is no older than conversationAgeDays and has a label in the partial set.
-     *   </li>
-     *   <li>also, pending changes on the server: the message has no user-controllable labels.</li>
-     * </ul>
-     *
-     * <p>A user-controllable label is a user-defined label or star, inbox,
-     * trash, spam, etc. LABEL_UNREAD is not considered user-controllable.
-     */
-    public static class Settings {
-        public long conversationAgeDays;
-        public long maxAttachmentSizeMb;
-        public String[] labelsIncluded;
-        public String[] labelsPartial;
-    }
-
-    /**
-     * Returns the settings.
-     * @param account the account whose setting should be retrieved
-     */
-    public Settings getSettings(String account) {
-        if (TextUtils.isEmpty(account)) {
-            throw new IllegalArgumentException("account is empty");
-        }
-        Settings settings = new Settings();
-        Cursor cursor = mContentResolver.query(
-                Uri.withAppendedPath(SETTINGS_URI, account), SETTINGS_PROJECTION, null, null, null);
-        cursor.moveToNext();
-        settings.labelsIncluded = TextUtils.split(cursor.getString(0), SPACE_SEPARATOR_PATTERN);
-        settings.labelsPartial = TextUtils.split(cursor.getString(1), SPACE_SEPARATOR_PATTERN);
-        settings.conversationAgeDays = Long.parseLong(cursor.getString(2));
-        settings.maxAttachmentSizeMb = Long.parseLong(cursor.getString(3));
-        cursor.close();
-        return settings;
-    }
-
-    /**
-     * Sets the settings. A sync will be scheduled automatically.
-     */
-    public void setSettings(String account, Settings settings) {
-        if (TextUtils.isEmpty(account)) {
-            throw new IllegalArgumentException("account is empty");
-        }
-        ContentValues values = new ContentValues();
-        values.put(
-                SettingsColumns.LABELS_INCLUDED,
-                TextUtils.join(" ", settings.labelsIncluded));
-        values.put(
-                SettingsColumns.LABELS_PARTIAL,
-                TextUtils.join(" ", settings.labelsPartial));
-        values.put(
-                SettingsColumns.CONVERSATION_AGE_DAYS,
-                settings.conversationAgeDays);
-        values.put(
-                SettingsColumns.MAX_ATTACHMENET_SIZE_MB,
-                settings.maxAttachmentSizeMb);
-        mContentResolver.update(Uri.withAppendedPath(SETTINGS_URI, account), values, null, null);
-    }
-
-    /**
-     * Uses sender instructions to build a formatted string.
-     *
-     * <p>Sender list instructions contain compact information about the sender list. Most work that
-     * can be done without knowing how much room will be availble for the sender list is done when
-     * creating the instructions.
-     *
-     * <p>The instructions string consists of tokens separated by SENDER_LIST_SEPARATOR. Here are
-     * the tokens, one per line:<ul>
-     * <li><tt>n</tt></li>
-     * <li><em>int</em>, the number of non-draft messages in the conversation</li>
-     * <li><tt>d</tt</li>
-     * <li><em>int</em>, the number of drafts in the conversation</li>
-     * <li><tt>l</tt></li>
-     * <li><em>literal html to be included in the output</em></li>
-     * <li><tt>s</tt> indicates that the message is sending (in the outbox without errors)</li>
-     * <li><tt>f</tt> indicates that the message failed to send (in the outbox with errors)</li>
-     * <li><em>for each message</em><ul>
-     *   <li><em>int</em>, 0 for read, 1 for unread</li>
-     *   <li><em>int</em>, the priority of the message. Zero is the most important</li>
-     *   <li><em>text</em>, the sender text or blank for messages from 'me'</li>
-     * </ul></li>
-     * <li><tt>e</tt> to indicate that one or more messages have been elided</li>
-     *
-     * <p>The instructions indicate how many messages and drafts are in the conversation and then
-     * describe the most important messages in order, indicating the priority of each message and
-     * whether the message is unread.
-     *
-     * @param instructions instructions as described above
-     * @param sb the SpannableStringBuilder to append to
-     * @param maxChars the number of characters available to display the text
-     * @param unreadStyle the CharacterStyle for unread messages, or null
-     * @param draftsStyle the CharacterStyle for draft messages, or null
-     * @param sendingString the string to use when there are messages scheduled to be sent
-     * @param sendFailedString the string to use when there are messages that mailed to send
-     * @param meString the string to use for messages sent by this user
-     * @param draftString the string to use for "Draft"
-     * @param draftPluralString the string to use for "Drafts" 
-     */
-    public static void getSenderSnippet(
-            String instructions, SpannableStringBuilder sb, int maxChars,
-            CharacterStyle unreadStyle,
-            CharacterStyle draftsStyle,
-            CharSequence meString, CharSequence draftString, CharSequence draftPluralString,
-            CharSequence sendingString, CharSequence sendFailedString,
-            boolean forceAllUnread, boolean forceAllRead) {
-        assert !(forceAllUnread && forceAllRead);
-        boolean unreadStatusIsForced = forceAllUnread || forceAllRead;
-        boolean forcedUnreadStatus = forceAllUnread;
-
-        // Measure each fragment. It's ok to iterate over the entire set of fragments because it is
-        // never a long list, even if there are many senders.
-        final Map<Integer, Integer> priorityToLength = sPriorityToLength;
-        priorityToLength.clear();
-
-        int maxFoundPriority = Integer.MIN_VALUE;
-        int numMessages = 0;
-        int numDrafts = 0;
-        CharSequence draftsFragment = "";
-        CharSequence sendingFragment = "";
-        CharSequence sendFailedFragment = "";
-        
-        sSenderListSplitter.setString(instructions);
-        int numFragments = 0;
-        String[] fragments = sSenderFragments;
-        int currentSize = fragments.length;
-        while (sSenderListSplitter.hasNext()) {
-            fragments[numFragments++] = sSenderListSplitter.next();
-            if (numFragments == currentSize) {
-                sSenderFragments = new String[2 * currentSize];
-                System.arraycopy(fragments, 0, sSenderFragments, 0, currentSize);
-                currentSize *= 2;
-                fragments = sSenderFragments;
-            }
-        }
-        
-        for (int i = 0; i < numFragments;) {
-            String fragment0 = fragments[i++];
-            if ("".equals(fragment0)) {
-                // This should be the final fragment.
-            } else if (Gmail.SENDER_LIST_TOKEN_ELIDED.equals(fragment0)) {
-                // ignore
-            } else if (Gmail.SENDER_LIST_TOKEN_NUM_MESSAGES.equals(fragment0)) {
-                numMessages = Integer.valueOf(fragments[i++]);
-            } else if (Gmail.SENDER_LIST_TOKEN_NUM_DRAFTS.equals(fragment0)) {
-                String numDraftsString = fragments[i++];
-                numDrafts = Integer.parseInt(numDraftsString);
-                draftsFragment = numDrafts == 1 ? draftString :
-                        draftPluralString + " (" + numDraftsString + ")";
-            } else if (Gmail.SENDER_LIST_TOKEN_LITERAL.equals(fragment0)) {
-                sb.append(Html.fromHtml(fragments[i++]));
-                return;
-            } else if (Gmail.SENDER_LIST_TOKEN_SENDING.equals(fragment0)) {
-                sendingFragment = sendingString;
-            } else if (Gmail.SENDER_LIST_TOKEN_SEND_FAILED.equals(fragment0)) {
-                sendFailedFragment = sendFailedString;
-            } else {
-                String priorityString = fragments[i++];
-                CharSequence nameString = fragments[i++];
-                if (nameString.length() == 0) nameString = meString;
-                int priority = Integer.parseInt(priorityString);
-                priorityToLength.put(priority, nameString.length());
-                maxFoundPriority = Math.max(maxFoundPriority, priority);
-            }
-        }
-        String numMessagesFragment =
-                (numMessages != 0) ? " (" + Integer.toString(numMessages + numDrafts) + ")" : "";
-
-        // Don't allocate fixedFragment unless we need it
-        SpannableStringBuilder fixedFragment = null;
-        int fixedFragmentLength = 0;
-        if (draftsFragment.length() != 0) {
-            if (fixedFragment == null) {
-                fixedFragment = new SpannableStringBuilder();
-            }
-            fixedFragment.append(draftsFragment);
-            if (draftsStyle != null) {
-                fixedFragment.setSpan(
-                        CharacterStyle.wrap(draftsStyle),
-                        0, fixedFragment.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
-            }
-        }
-        if (sendingFragment.length() != 0) {
-            if (fixedFragment == null) {
-                fixedFragment = new SpannableStringBuilder();
-            }
-            if (fixedFragment.length() != 0) fixedFragment.append(", ");
-            fixedFragment.append(sendingFragment);
-        }
-        if (sendFailedFragment.length() != 0) {
-            if (fixedFragment == null) {
-                fixedFragment = new SpannableStringBuilder();
-            }
-            if (fixedFragment.length() != 0) fixedFragment.append(", ");
-            fixedFragment.append(sendFailedFragment);
-        }
-
-        if (fixedFragment != null) {
-            fixedFragmentLength = fixedFragment.length();
-        }
-
-        final boolean normalMessagesExist =
-                numMessagesFragment.length() != 0 || maxFoundPriority != Integer.MIN_VALUE;
-        String preFixedFragement = "";
-        if (normalMessagesExist && fixedFragmentLength != 0) {
-            preFixedFragement = ", ";
-        }
-        int maxPriorityToInclude = -1; // inclusive
-        int numCharsUsed =
-                numMessagesFragment.length() + preFixedFragement.length() + fixedFragmentLength;
-        int numSendersUsed = 0;
-        while (maxPriorityToInclude < maxFoundPriority) {
-            if (priorityToLength.containsKey(maxPriorityToInclude + 1)) {
-                int length = numCharsUsed + priorityToLength.get(maxPriorityToInclude + 1);
-                if (numCharsUsed > 0) length += 2;
-                // We must show at least two senders if they exist. If we don't have space for both
-                // then we will truncate names.
-                if (length > maxChars && numSendersUsed >= 2) {
-                    break;
-                }
-                numCharsUsed = length;
-                numSendersUsed++;
-            }
-            maxPriorityToInclude++;
-        }
-
-        int numCharsToRemovePerWord = 0;
-        if (numCharsUsed > maxChars) {
-            numCharsToRemovePerWord = (numCharsUsed - maxChars) / numSendersUsed;
-        }
-
-        boolean elided = false;
-        for (int i = 0; i < numFragments;) {
-            String fragment0 = fragments[i++];
-            if ("".equals(fragment0)) {
-                // This should be the final fragment.
-            } else if (SENDER_LIST_TOKEN_ELIDED.equals(fragment0)) {
-                elided = true;
-            } else if (SENDER_LIST_TOKEN_NUM_MESSAGES.equals(fragment0)) {
-                i++;
-            } else if (SENDER_LIST_TOKEN_NUM_DRAFTS.equals(fragment0)) {
-                i++;
-            } else if (SENDER_LIST_TOKEN_SENDING.equals(fragment0)) {
-            } else if (SENDER_LIST_TOKEN_SEND_FAILED.equals(fragment0)) {
-            } else {
-                final String unreadString = fragment0;
-                final String priorityString = fragments[i++];
-                String nameString = fragments[i++];
-                if (nameString.length() == 0) nameString = meString.toString();
-                if (numCharsToRemovePerWord != 0) {
-                    nameString = nameString.substring(
-                            0, Math.max(nameString.length() - numCharsToRemovePerWord, 0));
-                }
-                final boolean unread = unreadStatusIsForced
-                        ? forcedUnreadStatus : Integer.parseInt(unreadString) != 0;
-                final int priority = Integer.parseInt(priorityString);
-                if (priority <= maxPriorityToInclude) {
-                    if (sb.length() != 0) {
-                        sb.append(elided ? " .. " : ", ");
-                    }
-                    elided = false;
-                    int pos = sb.length();
-                    sb.append(nameString);
-                    if (unread && unreadStyle != null) {
-                        sb.setSpan(CharacterStyle.wrap(unreadStyle),
-                                pos, sb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
-                    }
-                } else {
-                    elided = true;
-                }
-            }
-        }
-        sb.append(numMessagesFragment);
-        if (fixedFragmentLength != 0) {
-            sb.append(preFixedFragement);
-            sb.append(fixedFragment);
-        }
-    }
-
-    /**
-     * This is a cursor that only defines methods to move throught the results
-     * and register to hear about changes. All access to the data is left to
-     * subinterfaces.
-     */
-    public static class MailCursor extends ContentObserver {
-
-        // A list of observers of this cursor.
-        private Set<MailCursorObserver> mObservers;
-
-        // Updated values are accumulated here before being written out if the
-        // cursor is asked to persist the changes.
-        private ContentValues mUpdateValues;
-
-        protected Cursor mCursor;
-        protected String mAccount;
-
-        public Cursor getCursor() {
-            return mCursor;
-        }
-
-        /**
-         * Constructs the MailCursor given a regular cursor, registering as a
-         * change observer of the cursor.
-         * @param account the account the cursor is associated with
-         * @param cursor the underlying cursor
-         */
-        protected MailCursor(String account, Cursor cursor) {
-            super(new Handler());
-            mObservers = new HashSet<MailCursorObserver>();
-            mCursor = cursor;
-            mAccount = account;
-            if (mCursor != null) mCursor.registerContentObserver(this);
-        }
-
-        /**
-         * Gets the account associated with this cursor.
-         * @return the account.
-         */
-        public String getAccount() {
-            return mAccount;
-        }
-
-        protected void checkThread() {
-            // Turn this on when activity code no longer runs in the sync thread
-            // after notifications of changes.
-//            Thread currentThread = Thread.currentThread();
-//            if (currentThread != mThread) {
-//                throw new RuntimeException("Accessed from the wrong thread");
-//            }
-        }
-
-        /**
-         * Lazily constructs a map of update values to apply to the database
-         * if requested. This map is cleared out when we move to a different
-         * item in the result set.
-         *
-         * @return a map of values to be applied by an update.
-         */
-        protected ContentValues getUpdateValues() {
-            if (mUpdateValues == null) {
-                mUpdateValues = new ContentValues();
-            }
-            return mUpdateValues;
-        }
-
-        /**
-         * Called whenever mCursor is changed to point to a different row.
-         * Subclasses should override this if they need to clear out state
-         * when this happens.
-         *
-         * Subclasses must call the inherited version if they override this.
-         */
-        protected void onCursorPositionChanged() {
-            mUpdateValues = null;
-        }
-
-        // ********* MailCursor
-
-        /**
-         * Returns the numbers of rows in the cursor.
-         *
-         * @return the number of rows in the cursor.
-         */
-        final public int count() {
-            if (mCursor != null) {
-                return mCursor.getCount();
-            } else {
-                return 0;
-            }
-        }
-
-        /**
-         * @return the current position of this cursor, or -1 if this cursor
-         * has not been initialized.
-         */
-        final public int position() {
-            if (mCursor != null) {
-                return mCursor.getPosition();
-            } else {
-                return -1;
-            }
-        }
-
-        /**
-         * Move the cursor to an absolute position. The valid
-         * range of vaues is -1 &lt;= position &lt;= count.
-         *
-         * <p>This method will return true if the request destination was
-         * reachable, otherwise it returns false.
-         *
-         * @param position the zero-based position to move to.
-         * @return whether the requested move fully succeeded.
-         */
-        final public boolean moveTo(int position) {
-            checkCursor();
-            checkThread();
-            boolean moved = mCursor.moveToPosition(position);
-            if (moved) onCursorPositionChanged();
-            return moved;
-        }
-
-        /**
-         * Move the cursor to the next row.
-         *
-         * <p>This method will return false if the cursor is already past the
-         * last entry in the result set.
-         *
-         * @return whether the move succeeded.
-         */
-        final public boolean next() {
-            checkCursor();
-            checkThread();
-            boolean moved = mCursor.moveToNext();
-            if (moved) onCursorPositionChanged();
-            return moved;
-        }
-
-        /**
-         * Release all resources and locks associated with the cursor. The
-         * cursor will not be valid after this function is called.
-         */
-        final public void release() {
-            if (mCursor != null) {
-                mCursor.unregisterContentObserver(this);
-                mCursor.deactivate();
-            }
-        }
-
-        final public void registerContentObserver(ContentObserver observer) {
-            mCursor.registerContentObserver(observer);
-        }
-
-        final public void unregisterContentObserver(ContentObserver observer) {
-            mCursor.unregisterContentObserver(observer);
-        }
-
-        final public void registerDataSetObserver(DataSetObserver observer) {
-            mCursor.registerDataSetObserver(observer);
-        }
-
-        final public void unregisterDataSetObserver(DataSetObserver observer) {
-            mCursor.unregisterDataSetObserver(observer);
-        }
-
-        /**
-         * Register an observer to hear about changes to the cursor.
-         *
-         * @param observer the observer to register
-         */
-        final public void registerObserver(MailCursorObserver observer) {
-            mObservers.add(observer);
-        }
-
-        /**
-         * Unregister an observer.
-         *
-         * @param observer the observer to unregister
-         */
-        final public void unregisterObserver(MailCursorObserver observer) {
-            mObservers.remove(observer);
-        }
-
-        // ********* ContentObserver
-
-        @Override
-        final public boolean deliverSelfNotifications() {
-            return false;
-        }
-
-        @Override
-        public void onChange(boolean selfChange) {
-            if (DEBUG) {
-                Log.d(TAG, "MailCursor is notifying " + mObservers.size() + " observers");
-            }
-            for (MailCursorObserver o: mObservers) {
-                o.onCursorChanged(this);
-            }
-        }
-
-        protected void checkCursor() {
-            if (mCursor == null) {
-                throw new IllegalStateException(
-                        "cannot read from an insertion cursor");
-            }
-        }
-
-        /**
-         * Returns the string value of the column, or "" if the value is null.
-         */
-        protected String getStringInColumn(int columnIndex) {
-            checkCursor();
-            return toNonnullString(mCursor.getString(columnIndex));
-        }
-    }
-
-    /**
-     * A MailCursor observer is notified of changes to the result set of a
-     * cursor.
-     */
-    public interface MailCursorObserver {
-
-        /**
-         * Called when the result set of a cursor has changed.
-         *
-         * @param cursor the cursor whose result set has changed.
-         */
-        void onCursorChanged(MailCursor cursor);
-    }
-
-    /**
-     * A cursor over labels.
-     */
-    public final class LabelCursor extends MailCursor {
-
-        private int mNameIndex;
-        private int mNumConversationsIndex;
-        private int mNumUnreadConversationsIndex;
-
-        private LabelCursor(String account, Cursor cursor) {
-            super(account, cursor);
-
-            mNameIndex = mCursor.getColumnIndexOrThrow(LabelColumns.CANONICAL_NAME);
-            mNumConversationsIndex =
-                    mCursor.getColumnIndexOrThrow(LabelColumns.NUM_CONVERSATIONS);
-            mNumUnreadConversationsIndex = mCursor.getColumnIndexOrThrow(
-                    LabelColumns.NUM_UNREAD_CONVERSATIONS);
-        }
-
-        /**
-         * Gets the canonical name of the current label.
-         *
-         * @return the current label's name.
-         */
-        public String getName() {
-            return getStringInColumn(mNameIndex);
-        }
-
-        /**
-         * Gets the number of conversations with this label.
-         *
-         * @return the number of conversations with this label.
-         */
-        public int getNumConversations() {
-            return mCursor.getInt(mNumConversationsIndex);
-        }
-
-        /**
-         * Gets the number of unread conversations with this label.
-         *
-         * @return the number of unread conversations with this label.
-         */
-        public int getNumUnreadConversations() {
-            return mCursor.getInt(mNumUnreadConversationsIndex);
-        }
-    }
-
-    /**
-     * This is a map of labels. TODO: make it observable.
-     */
-    public static final class LabelMap extends Observable {
-        private final static ContentValues EMPTY_CONTENT_VALUES = new ContentValues();
-
-        private ContentQueryMap mQueryMap;
-        private SortedSet<String> mSortedUserLabels;
-        private Map<String, Long> mCanonicalNameToId;
-
-        private long mLabelIdSent;
-        private long mLabelIdInbox;
-        private long mLabelIdDraft;
-        private long mLabelIdUnread;
-        private long mLabelIdTrash;
-        private long mLabelIdSpam;
-        private long mLabelIdStarred;
-        private long mLabelIdChat;
-        private long mLabelIdVoicemail;
-        private long mLabelIdIgnored;
-        private long mLabelIdVoicemailInbox;
-        private long mLabelIdCached;
-        private long mLabelIdOutbox;
-
-        private boolean mLabelsSynced = false;
-
-        public LabelMap(ContentResolver contentResolver, String account, boolean keepUpdated) {
-            if (TextUtils.isEmpty(account)) {
-                throw new IllegalArgumentException("account is empty");
-            }
-            Cursor cursor = contentResolver.query(
-                    Uri.withAppendedPath(LABELS_URI, account), LABEL_PROJECTION, null, null, null);
-            init(cursor, keepUpdated);
-        }
-
-        public LabelMap(Cursor cursor, boolean keepUpdated) {
-            init(cursor, keepUpdated);
-        }
-
-        private void init(Cursor cursor, boolean keepUpdated) {
-            mQueryMap = new ContentQueryMap(cursor, BaseColumns._ID, keepUpdated, null);
-            mSortedUserLabels = new TreeSet<String>(java.text.Collator.getInstance());
-            mCanonicalNameToId = Maps.newHashMap();
-            updateDataStructures();
-            mQueryMap.addObserver(new Observer() {
-                public void update(Observable observable, Object data) {
-                    updateDataStructures();
-                    setChanged();
-                    notifyObservers();
-                }
-            });
-        }
-
-        /**
-         * @return whether at least some labels have been synced.
-         */
-        public boolean labelsSynced() {
-            return mLabelsSynced;
-        }
-
-        /**
-         * Updates the data structures that are maintained separately from mQueryMap after the query
-         * map has changed.
-         */
-        private void updateDataStructures() {
-            mSortedUserLabels.clear();
-            mCanonicalNameToId.clear();
-            for (Map.Entry<String, ContentValues> row : mQueryMap.getRows().entrySet()) {
-                long labelId = Long.valueOf(row.getKey());
-                String canonicalName = row.getValue().getAsString(LabelColumns.CANONICAL_NAME);
-                if (isLabelUserDefined(canonicalName)) {
-                    mSortedUserLabels.add(canonicalName);
-                }
-                mCanonicalNameToId.put(canonicalName, labelId);
-
-                if (LABEL_SENT.equals(canonicalName)) {
-                    mLabelIdSent = labelId;
-                } else if (LABEL_INBOX.equals(canonicalName)) {
-                    mLabelIdInbox = labelId;
-                } else if (LABEL_DRAFT.equals(canonicalName)) {
-                    mLabelIdDraft = labelId;
-                } else if (LABEL_UNREAD.equals(canonicalName)) {
-                    mLabelIdUnread = labelId;
-                } else if (LABEL_TRASH.equals(canonicalName)) {
-                    mLabelIdTrash = labelId;
-                } else if (LABEL_SPAM.equals(canonicalName)) {
-                    mLabelIdSpam = labelId;
-                } else if (LABEL_STARRED.equals(canonicalName)) {
-                    mLabelIdStarred = labelId;
-                } else if (LABEL_CHAT.equals(canonicalName)) {
-                    mLabelIdChat = labelId;
-                } else if (LABEL_IGNORED.equals(canonicalName)) {
-                    mLabelIdIgnored = labelId;
-                } else if (LABEL_VOICEMAIL.equals(canonicalName)) {
-                    mLabelIdVoicemail = labelId;
-                } else if (LABEL_VOICEMAIL_INBOX.equals(canonicalName)) {
-                    mLabelIdVoicemailInbox = labelId;
-                } else if (LABEL_CACHED.equals(canonicalName)) {
-                    mLabelIdCached = labelId;
-                } else if (LABEL_OUTBOX.equals(canonicalName)) {
-                    mLabelIdOutbox = labelId;
-                }
-                mLabelsSynced = mLabelIdSent != 0
-                    && mLabelIdInbox != 0
-                    && mLabelIdDraft != 0
-                    && mLabelIdUnread != 0
-                    && mLabelIdTrash != 0
-                    && mLabelIdSpam != 0
-                    && mLabelIdStarred != 0
-                    && mLabelIdChat != 0
-                    && mLabelIdIgnored != 0
-                    && mLabelIdVoicemail != 0;
-            }
-        }
-
-        public long getLabelIdSent() {
-            checkLabelsSynced();
-            return mLabelIdSent;
-        }
-
-        public long getLabelIdInbox() {
-            checkLabelsSynced();
-            return mLabelIdInbox;
-        }
-
-        public long getLabelIdDraft() {
-            checkLabelsSynced();
-            return mLabelIdDraft;
-        }
-
-        public long getLabelIdUnread() {
-            checkLabelsSynced();
-            return mLabelIdUnread;
-        }
-
-        public long getLabelIdTrash() {
-            checkLabelsSynced();
-            return mLabelIdTrash;
-        }
-
-        public long getLabelIdSpam() {
-            checkLabelsSynced();
-            return mLabelIdSpam;
-        }
-
-        public long getLabelIdStarred() {
-            checkLabelsSynced();
-            return mLabelIdStarred;
-        }
-
-        public long getLabelIdChat() {
-            checkLabelsSynced();
-            return mLabelIdChat;
-        }
-
-        public long getLabelIdIgnored() {
-            checkLabelsSynced();
-            return mLabelIdIgnored;
-        }
-
-        public long getLabelIdVoicemail() {
-            checkLabelsSynced();
-            return mLabelIdVoicemail;
-        }
-
-        public long getLabelIdVoicemailInbox() {
-            checkLabelsSynced();
-            return mLabelIdVoicemailInbox;
-        }
-
-        public long getLabelIdCached() {
-            checkLabelsSynced();
-            return mLabelIdCached;
-        }
-
-        public long getLabelIdOutbox() {
-            checkLabelsSynced();
-            return mLabelIdOutbox;
-        }
-
-        private void checkLabelsSynced() {
-            if (!labelsSynced()) {
-                throw new IllegalStateException("LabelMap not initalized");
-            }
-        }
-
-        /** Returns the list of user-defined labels in alphabetical order. */
-        public SortedSet<String> getSortedUserLabels() {
-            return mSortedUserLabels;
-        }
-
-        private static final List<String> SORTED_USER_MEANINGFUL_SYSTEM_LABELS =
-                Lists.newArrayList(
-                        LABEL_INBOX, LABEL_STARRED, LABEL_CHAT, LABEL_SENT,
-                        LABEL_OUTBOX, LABEL_DRAFT, LABEL_ALL,
-                        LABEL_SPAM, LABEL_TRASH);
-
-
-        private static final Set<String> USER_MEANINGFUL_SYSTEM_LABELS_SET =
-                Sets.newHashSet(
-                        SORTED_USER_MEANINGFUL_SYSTEM_LABELS.toArray(
-                                new String[]{}));
-
-        public static List<String> getSortedUserMeaningfulSystemLabels() {
-            return SORTED_USER_MEANINGFUL_SYSTEM_LABELS;
-        }
-
-        public static Set<String> getUserMeaningfulSystemLabelsSet() {
-            return USER_MEANINGFUL_SYSTEM_LABELS_SET;
-        }
-
-        /**
-         * If you are ever tempted to remove outbox or draft from this set make sure you have a
-         * way to stop draft and outbox messages from getting purged before they are sent to the
-         * server.
-         */
-        private static final Set<String> FORCED_INCLUDED_LABELS =
-                Sets.newHashSet(LABEL_OUTBOX, LABEL_DRAFT);
-
-        public static Set<String> getForcedIncludedLabels() {
-            return FORCED_INCLUDED_LABELS;
-        }
-
-        private static final Set<String> FORCED_INCLUDED_OR_PARTIAL_LABELS =
-                Sets.newHashSet(LABEL_INBOX);
-
-        public static Set<String> getForcedIncludedOrPartialLabels() {
-            return FORCED_INCLUDED_OR_PARTIAL_LABELS;
-        }
-
-        private static final Set<String> FORCED_UNSYNCED_LABELS =
-                Sets.newHashSet(LABEL_ALL, LABEL_CHAT, LABEL_SPAM, LABEL_TRASH);
-
-        public static Set<String> getForcedUnsyncedLabels() {
-            return FORCED_UNSYNCED_LABELS;
-        }
-
-        /**
-         * Returns the number of conversation with a given label.
-         * @deprecated Use {@link #getLabelId} instead.
-         */
-        @Deprecated
-        public int getNumConversations(String label) {
-            return getNumConversations(getLabelId(label));
-        }
-
-        /** Returns the number of conversation with a given label. */
-        public int getNumConversations(long labelId) {
-            return getLabelIdValues(labelId).getAsInteger(LabelColumns.NUM_CONVERSATIONS);
-        }
-
-        /**
-         * Returns the number of unread conversation with a given label.
-         * @deprecated Use {@link #getLabelId} instead.
-         */
-        @Deprecated
-        public int getNumUnreadConversations(String label) {
-            return getNumUnreadConversations(getLabelId(label));
-        }
-
-        /** Returns the number of unread conversation with a given label. */
-        public int getNumUnreadConversations(long labelId) {
-            Integer unreadConversations =
-                    getLabelIdValues(labelId).getAsInteger(LabelColumns.NUM_UNREAD_CONVERSATIONS);
-            // There seems to be a race condition here that can get the label maps into a bad
-            // state and lose state on a particular label.
-            int result = 0;
-            if (unreadConversations != null) {
-                result = unreadConversations < 0 ? 0 : unreadConversations;
-            }
-
-            return result;
-        }
-
-        /**
-         * @return the canonical name for a label
-         */
-        public String getCanonicalName(long labelId) {
-            return getLabelIdValues(labelId).getAsString(LabelColumns.CANONICAL_NAME);
-        }
-
-        /**
-         * @return the human name for a label
-         */
-        public String getName(long labelId) {
-            return getLabelIdValues(labelId).getAsString(LabelColumns.NAME);
-        }
-
-        /**
-         * @return whether a given label is known
-         */
-        public boolean hasLabel(long labelId) {
-            return mQueryMap.getRows().containsKey(Long.toString(labelId));
-        }
-
-        /**
-         * @return returns the id of a label given the canonical name
-         * @deprecated this is only needed because most of the UI uses label names instead of ids
-         */
-        public long getLabelId(String canonicalName) {
-            if (mCanonicalNameToId.containsKey(canonicalName)) {
-                return mCanonicalNameToId.get(canonicalName);
-            } else {
-                throw new IllegalArgumentException("Unknown canonical name: " + canonicalName);
-            }
-        }
-
-        private ContentValues getLabelIdValues(long labelId) {
-            final ContentValues values = mQueryMap.getValues(Long.toString(labelId));
-            if (values != null) {
-                return values;
-            } else {
-                return EMPTY_CONTENT_VALUES;
-            }
-        }
-
-        /** Force the map to requery. This should not be necessary outside tests. */
-        public void requery() {
-            mQueryMap.requery();
-        }
-
-        public void close() {
-            mQueryMap.close();
-        }
-    }
-
-    private Map<String, Gmail.LabelMap> mLabelMaps = Maps.newHashMap();
-
-    public LabelMap getLabelMap(String account) {
-        Gmail.LabelMap labelMap = mLabelMaps.get(account);
-        if (labelMap == null) {
-            labelMap = new Gmail.LabelMap(mContentResolver, account, true /* keepUpdated */);
-            mLabelMaps.put(account, labelMap);
-        }
-        return labelMap;
-    }
-
-    public enum PersonalLevel {
-        NOT_TO_ME(0),
-        TO_ME_AND_OTHERS(1),
-        ONLY_TO_ME(2);
-
-        private int mLevel;
-
-        PersonalLevel(int level) {
-            mLevel = level;
-        }
-
-        public int toInt() {
-            return mLevel;
-        }
-
-        public static PersonalLevel fromInt(int level) {
-            switch (level) {
-                case 0: return NOT_TO_ME;
-                case 1: return TO_ME_AND_OTHERS;
-                case 2: return ONLY_TO_ME;
-                default:
-                    throw new IllegalArgumentException(
-                            level + " is not a personal level");
-            }
-        }
-    }
-
-    /**
-     * Indicates a version of an attachment.
-     */
-    public enum AttachmentRendition {
-        /**
-         * The full version of an attachment if it can be handled on the device, otherwise the
-         * preview.
-         */
-        BEST,
-
-        /** A smaller or simpler version of the attachment, such as a scaled-down image or an HTML
-         * version of a document. Not always available.
-         */
-        SIMPLE,
-    }
-
-    /**
-     * The columns that can be requested when querying an attachment's download URI. See
-     * getAttachmentDownloadUri.
-     */
-    public static final class AttachmentColumns implements BaseColumns {
-
-        /** Contains a STATUS value from {@link android.provider.Downloads} */
-        public static final String STATUS = "status";
-
-        /**
-         * The name of the file to open (with ContentProvider.open). If this is empty then continue
-         * to use the attachment's URI.
-         *
-         * TODO: I'm not sure that we need this. See the note in CL 66853-p9.
-         */
-        public static final String FILENAME = "filename";
-    }
-
-    /**
-     * We track where an attachment came from so that we know how to download it and include it
-     * in new messages.
-     */
-    public enum AttachmentOrigin {
-        /** Extras are "<conversationId>-<messageId>-<partId>". */
-        SERVER_ATTACHMENT,
-        /** Extras are "<path>". */
-        LOCAL_FILE;
-
-        private static final String SERVER_EXTRAS_SEPARATOR = "_";
-
-        public static String serverExtras(
-                long conversationId, long messageId, String partId) {
-            return conversationId + SERVER_EXTRAS_SEPARATOR
-                    + messageId + SERVER_EXTRAS_SEPARATOR + partId;
-        }
-
-        /**
-         * @param extras extras as returned by serverExtras
-         * @return an array of conversationId, messageId, partId (all as strings)
-         */
-        public static String[] splitServerExtras(String extras) {
-            return TextUtils.split(extras, SERVER_EXTRAS_SEPARATOR);
-        }
-
-        public static String localFileExtras(Uri path) {
-            return path.toString();
-        }
-    }
-
-    public static final class Attachment {
-        /** Identifies the attachment uniquely when combined wih a message id.*/
-        public String partId;
-
-        /** The intended filename of the attachment.*/
-        public String name;
-
-        /** The native content type.*/
-        public String contentType;
-
-        /** The size of the attachment in its native form.*/
-        public int size;
-
-        /**
-         * The content type of the simple version of the attachment. Blank if no simple version is
-         * available.
-         */
-        public String simpleContentType;
-
-        public AttachmentOrigin origin;
-
-        public String originExtras;
-
-        public String toJoinedString() {
-            return TextUtils.join(
-                "|", Lists.newArrayList(partId == null ? "" : partId,
-                                        name.replace("|", ""), contentType,
-                                        size, simpleContentType,
-                                        origin.toString(), originExtras));
-        }
-
-        public static Attachment parseJoinedString(String joinedString) {
-            String[] fragments = TextUtils.split(joinedString, "\\|");
-            int i = 0;
-            Attachment attachment = new Attachment();
-            attachment.partId = fragments[i++];
-            if (TextUtils.isEmpty(attachment.partId)) {
-                attachment.partId = null;
-            }
-            attachment.name = fragments[i++];
-            attachment.contentType = fragments[i++];
-            attachment.size = Integer.parseInt(fragments[i++]);
-            attachment.simpleContentType = fragments[i++];
-            attachment.origin = AttachmentOrigin.valueOf(fragments[i++]);
-            attachment.originExtras = fragments[i++];
-            return attachment;
-        }
-    }
-
-    /**
-     * Any given attachment can come in two different renditions (see
-     * {@link android.provider.Gmail.AttachmentRendition}) and can be saved to the sd card or to a
-     * cache. The gmail provider automatically syncs some attachments to the cache. Other
-     * attachments can be downloaded on demand. Attachments in the cache will be purged as needed to
-     * save space. Attachments on the SD card must be managed by the user or other software.
-     *
-     * @param account which account to use
-     * @param messageId the id of the mesage with the attachment
-     * @param attachment the attachment
-     * @param rendition the desired rendition
-     * @param saveToSd whether the attachment should be saved to (or loaded from) the sd card or
-     * @return the URI to ask the content provider to open in order to open an attachment.
-     */
-    public static Uri getAttachmentUri(
-            String account, long messageId, Attachment attachment,
-            AttachmentRendition rendition, boolean saveToSd) {
-        if (TextUtils.isEmpty(account)) {
-            throw new IllegalArgumentException("account is empty");
-        }
-        if (attachment.origin == AttachmentOrigin.LOCAL_FILE) {
-            return Uri.parse(attachment.originExtras);
-        } else {
-            return Uri.parse(
-                    AUTHORITY_PLUS_MESSAGES).buildUpon()
-                    .appendPath(account).appendPath(Long.toString(messageId))
-                    .appendPath("attachments").appendPath(attachment.partId)
-                    .appendPath(rendition.toString())
-                    .appendPath(Boolean.toString(saveToSd))
-                    .build();
-        }
-    }
-
-    /**
-     * Return the URI to query in order to find out whether an attachment is downloaded.
-     *
-     * <p>Querying this will also start a download if necessary. The cursor returned by querying
-     * this URI can contain the columns in {@link android.provider.Gmail.AttachmentColumns}.
-     *
-     * <p>Deleting this URI will cancel the download if it was not started automatically by the
-     * provider. It will also remove bookkeeping for saveToSd downloads.
-     *
-     * @param attachmentUri the attachment URI as returned by getAttachmentUri. The URI's authority
-     *   Gmail.AUTHORITY. If it is not then you should open the file directly.
-     */
-    public static Uri getAttachmentDownloadUri(Uri attachmentUri) {
-        if (!"content".equals(attachmentUri.getScheme())) {
-            throw new IllegalArgumentException("Uri's scheme must be 'content': " + attachmentUri);
-        }
-        return attachmentUri.buildUpon().appendPath("download").build();
-    }
-
-    public enum CursorStatus {
-        LOADED,
-        LOADING,
-        ERROR, // A network error occurred.
-    }
-
-    /**
-     * A cursor over messages.
-     */
-    public static final class MessageCursor extends MailCursor {
-
-        private LabelMap mLabelMap;
-
-        private ContentResolver mContentResolver;
-
-        /**
-         * Only valid if mCursor == null, in which case we are inserting a new
-         * message.
-         */
-        long mInReplyToLocalMessageId;
-        boolean mPreserveAttachments;
-
-        private int mIdIndex;
-        private int mConversationIdIndex;
-        private int mSubjectIndex;
-        private int mSnippetIndex;
-        private int mFromIndex;
-        private int mToIndex;
-        private int mCcIndex;
-        private int mBccIndex;
-        private int mReplyToIndex;
-        private int mDateSentMsIndex;
-        private int mDateReceivedMsIndex;
-        private int mListInfoIndex;
-        private int mPersonalLevelIndex;
-        private int mBodyIndex;
-        private int mBodyEmbedsExternalResourcesIndex;
-        private int mLabelIdsIndex;
-        private int mJoinedAttachmentInfosIndex;
-        private int mErrorIndex;
-
-        private TextUtils.StringSplitter mLabelIdsSplitter = newMessageLabelIdsSplitter();
-
-        public MessageCursor(Gmail gmail, ContentResolver cr, String account, Cursor cursor) {
-            super(account, cursor);
-            mLabelMap = gmail.getLabelMap(account);
-            if (cursor == null) {
-                throw new IllegalArgumentException(
-                        "null cursor passed to MessageCursor()");
-            }
-
-            mContentResolver = cr;
-
-            mIdIndex = mCursor.getColumnIndexOrThrow(MessageColumns.ID);
-            mConversationIdIndex =
-                    mCursor.getColumnIndexOrThrow(MessageColumns.CONVERSATION_ID);
-            mSubjectIndex = mCursor.getColumnIndexOrThrow(MessageColumns.SUBJECT);
-            mSnippetIndex = mCursor.getColumnIndexOrThrow(MessageColumns.SNIPPET);
-            mFromIndex = mCursor.getColumnIndexOrThrow(MessageColumns.FROM);
-            mToIndex = mCursor.getColumnIndexOrThrow(MessageColumns.TO);
-            mCcIndex = mCursor.getColumnIndexOrThrow(MessageColumns.CC);
-            mBccIndex = mCursor.getColumnIndexOrThrow(MessageColumns.BCC);
-            mReplyToIndex = mCursor.getColumnIndexOrThrow(MessageColumns.REPLY_TO);
-            mDateSentMsIndex =
-                    mCursor.getColumnIndexOrThrow(MessageColumns.DATE_SENT_MS);
-            mDateReceivedMsIndex =
-                    mCursor.getColumnIndexOrThrow(MessageColumns.DATE_RECEIVED_MS);
-            mListInfoIndex = mCursor.getColumnIndexOrThrow(MessageColumns.LIST_INFO);
-            mPersonalLevelIndex =
-                    mCursor.getColumnIndexOrThrow(MessageColumns.PERSONAL_LEVEL);
-            mBodyIndex = mCursor.getColumnIndexOrThrow(MessageColumns.BODY);
-            mBodyEmbedsExternalResourcesIndex =
-                    mCursor.getColumnIndexOrThrow(MessageColumns.EMBEDS_EXTERNAL_RESOURCES);
-            mLabelIdsIndex = mCursor.getColumnIndexOrThrow(MessageColumns.LABEL_IDS);
-            mJoinedAttachmentInfosIndex =
-                    mCursor.getColumnIndexOrThrow(MessageColumns.JOINED_ATTACHMENT_INFOS);
-            mErrorIndex = mCursor.getColumnIndexOrThrow(MessageColumns.ERROR);
-
-            mInReplyToLocalMessageId = 0;
-            mPreserveAttachments = false;
-        }
-
-        protected MessageCursor(ContentResolver cr, String account, long inReplyToMessageId,
-                boolean preserveAttachments) {
-            super(account, null);
-            mContentResolver = cr;
-            mInReplyToLocalMessageId = inReplyToMessageId;
-            mPreserveAttachments = preserveAttachments;
-        }
-
-        @Override
-        protected void onCursorPositionChanged() {
-            super.onCursorPositionChanged();
-        }
-
-        public CursorStatus getStatus() {
-            Bundle extras = mCursor.getExtras();
-            String stringStatus = extras.getString(EXTRA_STATUS);
-            return CursorStatus.valueOf(stringStatus);
-        }
-
-        /** Retry a network request after errors. */
-        public void retry() {
-            Bundle input = new Bundle();
-            input.putString(RESPOND_INPUT_COMMAND, COMMAND_RETRY);
-            Bundle output = mCursor.respond(input);
-            String response = output.getString(RESPOND_OUTPUT_COMMAND_RESPONSE);
-            assert COMMAND_RESPONSE_OK.equals(response);
-        }
-
-        /**
-         * Gets the message id of the current message. Note that this is an
-         * immutable local message (not, for example, GMail's message id, which
-         * is immutable).
-         *
-         * @return the message's id
-         */
-        public long getMessageId() {
-            checkCursor();
-            return mCursor.getLong(mIdIndex);
-        }
-
-        /**
-         * Gets the message's conversation id. This must be immutable. (For
-         * example, with GMail this should be the original conversation id
-         * rather than the default notion of converation id.)
-         *
-         * @return the message's conversation id
-         */
-        public long getConversationId() {
-            checkCursor();
-            return mCursor.getLong(mConversationIdIndex);
-        }
-
-        /**
-         * Gets the message's subject.
-         *
-         * @return the message's subject
-         */
-        public String getSubject() {
-            return getStringInColumn(mSubjectIndex);
-        }
-
-        /**
-         * Gets the message's snippet (the short piece of the body). The snippet
-         * is generated from the body and cannot be set directly.
-         *
-         * @return the message's snippet
-         */
-        public String getSnippet() {
-            return getStringInColumn(mSnippetIndex);
-        }
-
-        /**
-         * Gets the message's from address.
-         *
-         * @return the message's from address
-         */
-        public String getFromAddress() {
-            return getStringInColumn(mFromIndex);
-        }
-
-        /**
-         * Returns the addresses for the key, if it has been updated, or index otherwise.
-         */
-        private String[] getAddresses(String key, int index) {
-            ContentValues updated = getUpdateValues();
-            String addresses;
-            if (updated.containsKey(key)) {
-                addresses = (String)getUpdateValues().get(key);
-            } else {
-                addresses = getStringInColumn(index);
-            }
-
-            return TextUtils.split(addresses, EMAIL_SEPARATOR_PATTERN);
-        }
-
-        /**
-         * Gets the message's to addresses.
-         * @return the message's to addresses
-         */
-        public String[] getToAddresses() {
-           return getAddresses(MessageColumns.TO, mToIndex);
-        }
-
-        /**
-         * Gets the message's cc addresses.
-         * @return the message's cc addresses
-         */
-        public String[] getCcAddresses() {
-            return getAddresses(MessageColumns.CC, mCcIndex);
-        }
-
-        /**
-         * Gets the message's bcc addresses.
-         * @return the message's bcc addresses
-         */
-        public String[] getBccAddresses() {
-            return getAddresses(MessageColumns.BCC, mBccIndex);
-        }
-
-        /**
-         * Gets the message's replyTo address.
-         *
-         * @return the message's replyTo address
-         */
-        public String[] getReplyToAddress() {
-            return TextUtils.split(getStringInColumn(mReplyToIndex), EMAIL_SEPARATOR_PATTERN);
-        }
-
-        public long getDateSentMs() {
-            checkCursor();
-            return mCursor.getLong(mDateSentMsIndex);
-        }
-
-        public long getDateReceivedMs() {
-            checkCursor();
-            return mCursor.getLong(mDateReceivedMsIndex);
-        }
-
-        public String getListInfo() {
-            return getStringInColumn(mListInfoIndex);
-        }
-
-        public PersonalLevel getPersonalLevel() {
-            checkCursor();
-            int personalLevelInt = mCursor.getInt(mPersonalLevelIndex);
-            return PersonalLevel.fromInt(personalLevelInt);
-        }
-
-        /**
-         * @deprecated Always returns true.
-         */
-        @Deprecated
-        public boolean getExpanded() {
-            return true;
-        }
-
-        /**
-         * Gets the message's body.
-         *
-         * @return the message's body
-         */
-        public String getBody() {
-            return getStringInColumn(mBodyIndex);
-        }
-
-        /**
-         * @return whether the message's body contains embedded references to external resources. In
-         * that case the resources should only be displayed if the user explicitly asks for them to
-         * be
-         */
-        public boolean getBodyEmbedsExternalResources() {
-            checkCursor();
-            return mCursor.getInt(mBodyEmbedsExternalResourcesIndex) != 0;
-        }
-
-        /**
-         * @return a copy of the set of label ids
-         */
-        public Set<Long> getLabelIds() {
-            String labelNames = mCursor.getString(mLabelIdsIndex);
-            mLabelIdsSplitter.setString(labelNames);
-            return getLabelIdsFromLabelIdsString(mLabelIdsSplitter);
-        }
-
-        /**
-         * @return a joined string of labels separated by spaces.
-         */
-        public String getRawLabelIds() {
-            return mCursor.getString(mLabelIdsIndex);
-        }
-
-        /**
-         * Adds a label to a message (if add is true) or removes it (if add is
-         * false).
-         *
-         * @param label the label to add or remove
-         * @param add whether to add or remove the label
-         */
-        public void addOrRemoveLabel(String label, boolean add) {
-            addOrRemoveLabelOnMessage(mContentResolver, mAccount, getConversationId(),
-                    getMessageId(), label, add);
-        }
-
-        public ArrayList<Attachment> getAttachmentInfos() {
-            ArrayList<Attachment> attachments = Lists.newArrayList();
-
-            String joinedAttachmentInfos = mCursor.getString(mJoinedAttachmentInfosIndex);
-            if (joinedAttachmentInfos != null) {
-                for (String joinedAttachmentInfo :
-                        TextUtils.split(joinedAttachmentInfos, ATTACHMENT_INFO_SEPARATOR_PATTERN)) {
-
-                    Attachment attachment = Attachment.parseJoinedString(joinedAttachmentInfo);
-                    attachments.add(attachment);
-                }
-            }
-            return attachments;
-        }
-
-        /**
-         * @return the error text for the message. Error text gets set if the server rejects a
-         * message that we try to save or send. If there is error text then the message is no longer
-         * scheduled to be saved or sent. Calling save() or send() will clear any error as well as
-         * scheduling another atempt to save or send the message.
-         */
-        public String getErrorText() {
-            return mCursor.getString(mErrorIndex);
-        }
-    }
-
-    /**
-     * A helper class for creating or updating messags. Use the putXxx methods to provide initial or
-     * new values for the message. Then save or send the message. To save or send an existing
-     * message without making other changes to it simply provide an emty ContentValues.
-     */
-    public static class MessageModification {
-
-        /**
-         * Sets the message's subject. Only valid for drafts.
-         *
-         * @param values the ContentValues that will be used to create or update the message
-         * @param subject the new subject
-         */
-        public static void putSubject(ContentValues values, String subject) {
-            values.put(MessageColumns.SUBJECT, subject);
-        }
-
-        /**
-         * Sets the message's to address. Only valid for drafts.
-         *
-         * @param values the ContentValues that will be used to create or update the message
-         * @param toAddresses the new to addresses
-         */
-        public static void putToAddresses(ContentValues values, String[] toAddresses) {
-            values.put(MessageColumns.TO, TextUtils.join(EMAIL_SEPARATOR, toAddresses));
-        }
-
-        /**
-         * Sets the message's cc address. Only valid for drafts.
-         *
-         * @param values the ContentValues that will be used to create or update the message
-         * @param ccAddresses the new cc addresses
-         */
-        public static void putCcAddresses(ContentValues values, String[] ccAddresses) {
-            values.put(MessageColumns.CC, TextUtils.join(EMAIL_SEPARATOR, ccAddresses));
-        }
-
-        /**
-         * Sets the message's bcc address. Only valid for drafts.
-         *
-         * @param values the ContentValues that will be used to create or update the message
-         * @param bccAddresses the new bcc addresses
-         */
-        public static void putBccAddresses(ContentValues values, String[] bccAddresses) {
-            values.put(MessageColumns.BCC, TextUtils.join(EMAIL_SEPARATOR, bccAddresses));
-        }
-
-        /**
-         * Saves a new body for the message. Only valid for drafts.
-         *
-         * @param values the ContentValues that will be used to create or update the message
-         * @param body the new body of the message
-         */
-        public static void putBody(ContentValues values, String body) {
-            values.put(MessageColumns.BODY, body);
-        }
-
-        /**
-         * Sets the attachments on a message. Only valid for drafts.
-         *
-         * @param values the ContentValues that will be used to create or update the message
-         * @param attachments
-         */
-        public static void putAttachments(ContentValues values, List<Attachment> attachments) {
-            values.put(
-                    MessageColumns.JOINED_ATTACHMENT_INFOS, joinedAttachmentsString(attachments));
-        }
-
-        /**
-         * Create a new message and save it as a draft or send it.
-         *
-         * @param contentResolver the content resolver to use
-         * @param account the account to use
-         * @param values the values for the new message
-         * @param refMessageId the message that is being replied to or forwarded
-         * @param save whether to save or send the message
-         * @return the id of the new message
-         */
-        public static long sendOrSaveNewMessage(
-                ContentResolver contentResolver, String account,
-                ContentValues values, long refMessageId, boolean save) {
-            values.put(MessageColumns.FAKE_SAVE, save);
-            values.put(MessageColumns.FAKE_REF_MESSAGE_ID, refMessageId);
-            Uri uri = Uri.parse(AUTHORITY_PLUS_MESSAGES + account + "/");
-            Uri result = contentResolver.insert(uri, values);
-            return ContentUris.parseId(result);
-        }
-
-        /**
-         * Update an existing draft and save it as a new draft or send it.
-         *
-         * @param contentResolver the content resolver to use
-         * @param account the account to use
-         * @param messageId the id of the message to update
-         * @param updateValues the values to change. Unspecified fields will not be altered
-         * @param save whether to resave the message as a draft or send it
-         */
-        public static void sendOrSaveExistingMessage(
-                ContentResolver contentResolver, String account, long messageId,
-                ContentValues updateValues, boolean save) {
-            updateValues.put(MessageColumns.FAKE_SAVE, save);
-            updateValues.put(MessageColumns.FAKE_REF_MESSAGE_ID, 0);
-            Uri uri = Uri.parse(
-                    AUTHORITY_PLUS_MESSAGES + account + "/" + messageId);
-            contentResolver.update(uri, updateValues, null, null);
-        }
-
-        /**
-         * The string produced here is parsed by Gmail.MessageCursor#getAttachmentInfos.
-         */
-        public static String joinedAttachmentsString(List<Gmail.Attachment> attachments) {
-            StringBuilder attachmentsSb = new StringBuilder();
-            for (Gmail.Attachment attachment : attachments) {
-                if (attachmentsSb.length() != 0) {
-                    attachmentsSb.append(Gmail.ATTACHMENT_INFO_SEPARATOR);
-                }
-                attachmentsSb.append(attachment.toJoinedString());
-            }
-            return attachmentsSb.toString();
-        }
-
-    }
-
-    /**
-     * A cursor over conversations.
-     *
-     * "Conversation" refers to the information needed to populate a list of
-     * conversations, not all of the messages in a conversation.
-     */
-    public static final class ConversationCursor extends MailCursor {
-
-        private LabelMap mLabelMap;
-
-        private int mConversationIdIndex;
-        private int mSubjectIndex;
-        private int mSnippetIndex;
-        private int mFromIndex;
-        private int mDateIndex;
-        private int mPersonalLevelIndex;
-        private int mLabelIdsIndex;
-        private int mNumMessagesIndex;
-        private int mMaxMessageIdIndex;
-        private int mHasAttachmentsIndex;
-        private int mHasMessagesWithErrorsIndex;
-        private int mForceAllUnreadIndex;
-
-        private TextUtils.StringSplitter mLabelIdsSplitter = newConversationLabelIdsSplitter();
-
-        private ConversationCursor(Gmail gmail, String account, Cursor cursor) {
-            super(account, cursor);
-            mLabelMap = gmail.getLabelMap(account);
-
-            mConversationIdIndex =
-                    mCursor.getColumnIndexOrThrow(ConversationColumns.ID);
-            mSubjectIndex = mCursor.getColumnIndexOrThrow(ConversationColumns.SUBJECT);
-            mSnippetIndex = mCursor.getColumnIndexOrThrow(ConversationColumns.SNIPPET);
-            mFromIndex = mCursor.getColumnIndexOrThrow(ConversationColumns.FROM);
-            mDateIndex = mCursor.getColumnIndexOrThrow(ConversationColumns.DATE);
-            mPersonalLevelIndex =
-                    mCursor.getColumnIndexOrThrow(ConversationColumns.PERSONAL_LEVEL);
-            mLabelIdsIndex =
-                    mCursor.getColumnIndexOrThrow(ConversationColumns.LABEL_IDS);
-            mNumMessagesIndex = mCursor.getColumnIndexOrThrow(ConversationColumns.NUM_MESSAGES);
-            mMaxMessageIdIndex = mCursor.getColumnIndexOrThrow(ConversationColumns.MAX_MESSAGE_ID);
-            mHasAttachmentsIndex =
-                    mCursor.getColumnIndexOrThrow(ConversationColumns.HAS_ATTACHMENTS);
-            mHasMessagesWithErrorsIndex =
-                    mCursor.getColumnIndexOrThrow(ConversationColumns.HAS_MESSAGES_WITH_ERRORS);
-            mForceAllUnreadIndex =
-                    mCursor.getColumnIndexOrThrow(ConversationColumns.FORCE_ALL_UNREAD);
-        }
-
-        @Override
-        protected void onCursorPositionChanged() {
-            super.onCursorPositionChanged();
-        }
-
-        public CursorStatus getStatus() {
-            Bundle extras = mCursor.getExtras();
-            String stringStatus = extras.getString(EXTRA_STATUS);
-            return CursorStatus.valueOf(stringStatus);
-        }
-
-        /** Retry a network request after errors. */
-        public void retry() {
-            Bundle input = new Bundle();
-            input.putString(RESPOND_INPUT_COMMAND, COMMAND_RETRY);
-            Bundle output = mCursor.respond(input);
-            String response = output.getString(RESPOND_OUTPUT_COMMAND_RESPONSE);
-            assert COMMAND_RESPONSE_OK.equals(response);
-        }
-
-        /**
-         * When a conversation cursor is created it becomes the active network cursor, which means
-         * that it will fetch results from the network if it needs to in order to show all mail that
-         * matches its query. If you later want to requery an older cursor and would like that
-         * cursor to be the active cursor you need to call this method before requerying.
-         */
-        public void becomeActiveNetworkCursor() {
-            Bundle input = new Bundle();
-            input.putString(RESPOND_INPUT_COMMAND, COMMAND_ACTIVATE);
-            Bundle output = mCursor.respond(input);
-            String response = output.getString(RESPOND_OUTPUT_COMMAND_RESPONSE);
-            assert COMMAND_RESPONSE_OK.equals(response);
-        }
-
-        /**
-         * Tells the cursor whether its contents are visible to the user. The cursor will
-         * automatically broadcast intents to remove any matching new-mail notifications when this
-         * cursor's results become visible and, if they are visible, when the cursor is requeried.
-         *
-         * Note that contents shown in an activity that is resumed but not focused
-         * (onWindowFocusChanged/hasWindowFocus) then results shown in that activity do not count
-         * as visible. (This happens when the activity is behind the lock screen or a dialog.)
-         *
-         * @param visible whether the contents of this cursor are visible to the user.
-         */
-        public void setContentsVisibleToUser(boolean visible) {
-            Bundle input = new Bundle();
-            input.putString(RESPOND_INPUT_COMMAND, COMMAND_SET_VISIBLE);
-            input.putBoolean(SET_VISIBLE_PARAM_VISIBLE, visible);
-            Bundle output = mCursor.respond(input);
-            String response = output.getString(RESPOND_OUTPUT_COMMAND_RESPONSE);
-            assert COMMAND_RESPONSE_OK.equals(response);
-        }
-
-        /**
-         * Gets the conversation id. This is immutable. (The server calls it the original
-         * conversation id.)
-         *
-         * @return the conversation id
-         */
-        public long getConversationId() {
-            return mCursor.getLong(mConversationIdIndex);
-        }
-
-        /**
-         * Returns the instructions for building from snippets. Pass this to getFromSnippetHtml
-         * in order to actually build the snippets.
-         * @return snippet instructions for use by getFromSnippetHtml()
-         */
-        public String getFromSnippetInstructions() {
-            return getStringInColumn(mFromIndex);
-        }
-
-        /**
-         * Gets the conversation's subject.
-         *
-         * @return the subject
-         */
-        public String getSubject() {
-            return getStringInColumn(mSubjectIndex);
-        }
-
-        /**
-         * Gets the conversation's snippet.
-         *
-         * @return the snippet
-         */
-        public String getSnippet() {
-            return getStringInColumn(mSnippetIndex);
-        }
-
-        /**
-         * Get's the conversation's personal level.
-         *
-         * @return the personal level.
-         */
-        public PersonalLevel getPersonalLevel() {
-            int personalLevelInt = mCursor.getInt(mPersonalLevelIndex);
-            return PersonalLevel.fromInt(personalLevelInt);
-        }
-
-        /**
-         * @return a copy of the set of labels. To add or remove labels call
-         *         MessageCursor.addOrRemoveLabel on each message in the conversation.
-         * @deprecated use getLabelIds
-         */
-        public Set<String> getLabels() {
-            return getLabels(getRawLabelIds(), mLabelMap);
-        }
-
-        /**
-         * @return a copy of the set of labels. To add or remove labels call
-         *         MessageCursor.addOrRemoveLabel on each message in the conversation.
-         */
-        public Set<Long> getLabelIds() {
-            mLabelIdsSplitter.setString(getRawLabelIds());
-            return getLabelIdsFromLabelIdsString(mLabelIdsSplitter);
-        }
-
-        /**
-         * Returns the set of labels using the raw labels from a previous getRawLabels()
-         * as input.
-         * @return a copy of the set of labels. To add or remove labels call
-         * MessageCursor.addOrRemoveLabel on each message in the conversation.
-         */
-        public Set<String> getLabels(String rawLabelIds, LabelMap labelMap) {
-            mLabelIdsSplitter.setString(rawLabelIds);
-            return getCanonicalNamesFromLabelIdsString(labelMap, mLabelIdsSplitter);
-        }
-
-        /**
-         * @return a joined string of labels separated by spaces. Use
-         * getLabels(rawLabels) to convert this to a Set of labels.
-         */
-        public String getRawLabelIds() {
-            return mCursor.getString(mLabelIdsIndex);
-        }
-
-        /**
-         * @return the number of messages in the conversation
-         */
-        public int getNumMessages() {
-            return mCursor.getInt(mNumMessagesIndex);
-        }
-
-        /**
-         * @return the max message id in the conversation
-         */
-        public long getMaxServerMessageId() {
-            return mCursor.getLong(mMaxMessageIdIndex);
-        }
-
-        public long getDateMs() {
-            return mCursor.getLong(mDateIndex);
-        }
-
-        public boolean hasAttachments() {
-            return mCursor.getInt(mHasAttachmentsIndex) != 0;
-        }
-
-        public boolean hasMessagesWithErrors() {
-            return mCursor.getInt(mHasMessagesWithErrorsIndex) != 0;
-        }
-
-        public boolean getForceAllUnread() {
-            return !mCursor.isNull(mForceAllUnreadIndex)
-                    && mCursor.getInt(mForceAllUnreadIndex) != 0;
-        }
-    }
-}
diff --git a/preloaded-classes b/preloaded-classes
index dc5327e..f8d14fd 100644
--- a/preloaded-classes
+++ b/preloaded-classes
@@ -600,16 +600,6 @@
 android.provider.ContactsContract$RawContacts
 android.provider.Downloads
 android.provider.DrmStore$Audio
-android.provider.Gmail
-android.provider.Gmail$AttachmentOrigin
-android.provider.Gmail$AttachmentRendition
-android.provider.Gmail$BecomeActiveNetworkCursor
-android.provider.Gmail$ConversationCursor
-android.provider.Gmail$CursorStatus
-android.provider.Gmail$LabelMap
-android.provider.Gmail$MailCursor
-android.provider.Gmail$MessageCursor
-android.provider.Gmail$PersonalLevel
 android.provider.Im$Account
 android.provider.Im$Avatars
 android.provider.Im$Chats
