1ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hupackage com.android.emailcommon.provider;
2ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu
3ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Huimport android.content.ContentResolver;
4ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Huimport android.content.Context;
5ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Huimport android.database.Cursor;
6ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Huimport android.net.Uri;
7ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Huimport android.support.v4.util.LongSparseArray;
8ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu
9ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Huimport com.android.mail.utils.LogUtils;
10ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu
11ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Huimport java.util.ArrayList;
12ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Huimport java.util.List;
13ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu
14ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu/**
15ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu * {@link EmailContent}-like class for the MessageStateChange table.
16ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu */
17ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hupublic class MessageStateChange extends MessageChangeLogTable {
18ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu    /** Logging tag. */
19ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu    public static final String LOG_TAG = "MessageStateChange";
20ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu
21ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu    /** The name for this table in the database. */
22ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu    public static final String TABLE_NAME = "MessageStateChange";
23ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu
24ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu    /** The path for the URI for interacting with message moves. */
25ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu    public static final String PATH = "messageChange";
26ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu
27ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu    /** The URI for dealing with message move data. */
28ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu    public static Uri CONTENT_URI;
29ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu
30ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu    // DB columns.
31ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu    /** Column name for the old value of flagRead. */
32ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu    public static final String OLD_FLAG_READ = "oldFlagRead";
33ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu    /** Column name for the new value of flagRead. */
34ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu    public static final String NEW_FLAG_READ = "newFlagRead";
35ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu    /** Column name for the old value of flagFavorite. */
36ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu    public static final String OLD_FLAG_FAVORITE = "oldFlagFavorite";
37ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu    /** Column name for the new value of flagFavorite. */
38ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu    public static final String NEW_FLAG_FAVORITE = "newFlagFavorite";
39ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu
40ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu    /** Value stored in DB for "new" columns when an update did not touch this particular value. */
41ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu    public static final int VALUE_UNCHANGED = -1;
42ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu
43ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu    /**
44ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu     * Projection for a query to get all columns necessary for an actual change.
45ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu     */
46e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu    private interface ProjectionChangeQuery {
47ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu        public static final int COLUMN_ID = 0;
48ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu        public static final int COLUMN_MESSAGE_KEY = 1;
49ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu        public static final int COLUMN_SERVER_ID = 2;
50ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu        public static final int COLUMN_OLD_FLAG_READ = 3;
51ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu        public static final int COLUMN_NEW_FLAG_READ = 4;
52ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu        public static final int COLUMN_OLD_FLAG_FAVORITE = 5;
53ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu        public static final int COLUMN_NEW_FLAG_FAVORITE = 6;
54ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu
55ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu        public static final String[] PROJECTION = new String[] {
56ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu                ID, MESSAGE_KEY, SERVER_ID,
57ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu                OLD_FLAG_READ, NEW_FLAG_READ,
58ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu                OLD_FLAG_FAVORITE, NEW_FLAG_FAVORITE
59ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu        };
60ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu    }
61ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu
62ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu    // The actual fields.
63ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu    private final int mOldFlagRead;
64ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu    private int mNewFlagRead;
65ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu    private final int mOldFlagFavorite;
66ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu    private int mNewFlagFavorite;
67e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu    private final long mMailboxId;
68ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu
69ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu    private MessageStateChange(final long messageKey,final String serverId, final long id,
70ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu            final int oldFlagRead, final int newFlagRead,
71e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu            final int oldFlagFavorite, final int newFlagFavorite,
72e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu            final long mailboxId) {
73ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu        super(messageKey, serverId, id);
74ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu        mOldFlagRead = oldFlagRead;
75ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu        mNewFlagRead = newFlagRead;
76ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu        mOldFlagFavorite = oldFlagFavorite;
77ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu        mNewFlagFavorite = newFlagFavorite;
78e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu        mMailboxId = mailboxId;
79e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu    }
80e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu
81e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu    public final int getNewFlagRead() {
82e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu        if (mOldFlagRead == mNewFlagRead) {
83e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu            return VALUE_UNCHANGED;
84e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu        }
85e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu        return mNewFlagRead;
86e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu    }
87e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu
88e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu    public final int getNewFlagFavorite() {
89e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu        if (mOldFlagFavorite == mNewFlagFavorite) {
90e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu            return VALUE_UNCHANGED;
91e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu        }
92e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu        return mNewFlagFavorite;
93ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu    }
94ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu
95ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu    /**
96ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu     * Initialize static state for this class.
97ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu     */
98ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu    public static void init() {
99ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu        CONTENT_URI = EmailContent.CONTENT_URI.buildUpon().appendEncodedPath(PATH).build();
100ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu    }
101ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu
102e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu    /**
103e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu     * Gets final state changes to upsync to the server, setting the status in the DB for all rows
104e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu     * to {@link #STATUS_PROCESSING} that are being updated and to {@link #STATUS_FAILED} for any
105e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu     * old updates. Messages whose sequence of changes results in a no-op are cleared from the DB
106e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu     * without any upsync.
107e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu     * @param context A {@link Context}.
108e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu     * @param accountId The account we want to update.
109e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu     * @param ignoreFavorites Whether to ignore changes to the favorites flag.
110e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu     * @return The final chnages to send to the server, or null if there are none.
111e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu     */
112e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu    public static List<MessageStateChange> getChanges(final Context context, final long accountId,
113e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu            final boolean ignoreFavorites) {
114ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu        final ContentResolver cr = context.getContentResolver();
115ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu        final Cursor c = getCursor(cr, CONTENT_URI, ProjectionChangeQuery.PROJECTION, accountId);
116ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu        if (c == null) {
117ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu            return null;
118ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu        }
119ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu
120ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu        // Collapse rows acting on the same message.
121ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu        // TODO: Unify with MessageMove, move to base class as much as possible.
122ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu        LongSparseArray<MessageStateChange> changesMap = new LongSparseArray();
123ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu        try {
124ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu            while (c.moveToNext()) {
125ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu                final long id = c.getLong(ProjectionChangeQuery.COLUMN_ID);
126ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu                final long messageKey = c.getLong(ProjectionChangeQuery.COLUMN_MESSAGE_KEY);
127ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu                final String serverId = c.getString(ProjectionChangeQuery.COLUMN_SERVER_ID);
128ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu                final int oldFlagRead = c.getInt(ProjectionChangeQuery.COLUMN_OLD_FLAG_READ);
129ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu                final int newFlagReadTable =  c.getInt(ProjectionChangeQuery.COLUMN_NEW_FLAG_READ);
130ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu                final int newFlagRead = (newFlagReadTable == VALUE_UNCHANGED) ?
131ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu                        oldFlagRead : newFlagReadTable;
132ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu                final int oldFlagFavorite =
133ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu                        c.getInt(ProjectionChangeQuery.COLUMN_OLD_FLAG_FAVORITE);
134ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu                final int newFlagFavoriteTable =
135ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu                        c.getInt(ProjectionChangeQuery.COLUMN_NEW_FLAG_FAVORITE);
136e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu                final int newFlagFavorite =
137e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu                        (ignoreFavorites || newFlagFavoriteTable == VALUE_UNCHANGED) ?
138e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu                                oldFlagFavorite : newFlagFavoriteTable;
139ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu                final MessageStateChange existingChange = changesMap.get(messageKey);
140ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu                if (existingChange != null) {
141ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu                    if (existingChange.mLastId >= id) {
142ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu                        LogUtils.w(LOG_TAG, "DChanges were not in ascending id order");
143ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu                    }
144ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu                    if (existingChange.mNewFlagRead != oldFlagRead ||
145ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu                            existingChange.mNewFlagFavorite != oldFlagFavorite) {
146ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu                        LogUtils.w(LOG_TAG, "existing change inconsistent with new change");
147ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu                    }
148ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu                    existingChange.mNewFlagRead = newFlagRead;
149ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu                    existingChange.mNewFlagFavorite = newFlagFavorite;
150ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu                    existingChange.mLastId = id;
151ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu                } else {
152e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu                    final long mailboxId = MessageMove.getLastSyncedMailboxForMessage(cr,
153e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu                            messageKey);
154e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu                    if (mailboxId == Mailbox.NO_MAILBOX) {
155e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu                        LogUtils.e(LOG_TAG, "No mailbox id for message %d", messageKey);
156e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu                    } else {
157e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu                        changesMap.put(messageKey, new MessageStateChange(messageKey, serverId, id,
158e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu                                oldFlagRead, newFlagRead, oldFlagFavorite, newFlagFavorite,
159e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu                                mailboxId));
160e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu                    }
161ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu                }
162ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu            }
163ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu        } finally {
164ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu            c.close();
165ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu        }
166ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu
167ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu        // Prune no-ops.
168ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu        // TODO: Unify with MessageMove, move to base class as much as possible.
169ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu        final int count = changesMap.size();
170ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu        final long[] unchangedMessages = new long[count];
171ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu        int unchangedMessagesCount = 0;
172ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu        final ArrayList<MessageStateChange> changes = new ArrayList(count);
173ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu        for (int i = 0; i < changesMap.size(); ++i) {
174ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu            final MessageStateChange change = changesMap.valueAt(i);
175e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu            // We also treat changes without a server id as a no-op.
176e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu            if ((change.mServerId == null || change.mServerId.length() == 0) ||
177e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu                    (change.mOldFlagRead == change.mNewFlagRead &&
178e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu                            change.mOldFlagFavorite == change.mNewFlagFavorite)) {
179ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu                unchangedMessages[unchangedMessagesCount] = change.mMessageKey;
180ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu                ++unchangedMessagesCount;
181ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu            } else {
182ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu                changes.add(change);
183ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu            }
184ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu        }
185ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu        if (unchangedMessagesCount != 0) {
186ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu            deleteRowsForMessages(cr, CONTENT_URI, unchangedMessages, unchangedMessagesCount);
187ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu        }
188ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu        if (changes.isEmpty()) {
189ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu            return null;
190ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu        }
191ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu        return changes;
192ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu    }
193e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu
194e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu    /**
195e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu     * Rearrange the changes list to a map by mailbox id.
196e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu     * @return The final changes to send to the server, or null if there are none.
197e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu     */
198e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu    public static LongSparseArray<List<MessageStateChange>> convertToChangesMap(
199e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu            final List<MessageStateChange> changes) {
200e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu        if (changes == null) {
201e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu            return null;
202e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu        }
203e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu
204e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu        final LongSparseArray<List<MessageStateChange>> changesMap = new LongSparseArray();
205e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu        for (final MessageStateChange change : changes) {
206e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu            List<MessageStateChange> list = changesMap.get(change.mMailboxId);
207e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu            if (list == null) {
208e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu                list = new ArrayList();
209e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu                changesMap.put(change.mMailboxId, list);
210e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu            }
211e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu            list.add(change);
212e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu        }
213e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu        if (changesMap.size() == 0) {
214e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu            return null;
215e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu        }
216e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu        return changesMap;
217e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu    }
218e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu
219e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu    /**
220e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu     * Clean up the table to reflect a successful set of upsyncs.
221e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu     * @param cr A {@link ContentResolver}
222e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu     * @param messageKeys The messages to update.
223e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu     * @param count The number of messages.
224e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu     */
225e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu    public static void upsyncSuccessful(final ContentResolver cr, final long[] messageKeys,
226e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu            final int count) {
227e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu        deleteRowsForMessages(cr, CONTENT_URI, messageKeys, count);
228e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu    }
229e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu
230e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu    /**
231e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu     * Clean up the table to reflect upsyncs that need to be retried.
232e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu     * @param cr A {@link ContentResolver}
233e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu     * @param messageKeys The messages to update.
234e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu     * @param count The number of messages.
235e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu     */
236e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu    public static void upsyncRetry(final ContentResolver cr, final long[] messageKeys,
237e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu            final int count) {
238e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu        retryMessages(cr, CONTENT_URI, messageKeys, count);
239e9849404652f317c4fb3af822fd6fa9cd23ad881Yu Ping Hu    }
240ca79aba675d5282b6ba365184f3727b7b24a568fYu Ping Hu}
241