17a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal/*******************************************************************************
27a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal *      Copyright (C) 2012 Google Inc.
37a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal *      Licensed to The Android Open Source Project.
47a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal *
57a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal *      Licensed under the Apache License, Version 2.0 (the "License");
67a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal *      you may not use this file except in compliance with the License.
77a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal *      You may obtain a copy of the License at
87a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal *
97a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal *           http://www.apache.org/licenses/LICENSE-2.0
107a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal *
117a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal *      Unless required by applicable law or agreed to in writing, software
127a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal *      distributed under the License is distributed on an "AS IS" BASIS,
137a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal *      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
147a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal *      See the License for the specific language governing permissions and
157a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal *      limitations under the License.
167a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal *******************************************************************************/
177a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal
187a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwalpackage com.android.mail.providers;
197a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal
207a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwalimport android.app.LoaderManager;
217a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwalimport android.content.Loader;
227a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwalimport android.net.Uri;
237a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwalimport android.os.Bundle;
2416027b7fabaf488f10fe90a41af4ece25cf1ef10Andrew Sappersteinimport android.support.annotation.NonNull;
257a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal
2677ee0ceaefaa9be699a20bfbe162f4c0ef83c6e1Vikram Aggarwalimport com.android.mail.content.ObjectCursor;
2777ee0ceaefaa9be699a20bfbe162f4c0ef83c6e1Vikram Aggarwalimport com.android.mail.content.ObjectCursorLoader;
287a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwalimport com.android.mail.ui.AbstractActivityController;
297a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwalimport com.android.mail.ui.RestrictedActivity;
307a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwalimport com.android.mail.utils.LogUtils;
316bfae1c9b0623156265cb39d3c097a7cbeacb431Paul Westbrookimport com.google.common.collect.Lists;
327a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal
337a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwalimport java.util.ArrayList;
346bfae1c9b0623156265cb39d3c097a7cbeacb431Paul Westbrookimport java.util.Collections;
357a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwalimport java.util.HashMap;
367a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwalimport java.util.List;
377a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwalimport java.util.Map;
387a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal
397a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal/**
407a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal * A container to keep a list of Folder objects, with the ability to automatically keep in sync with
417a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal * the folders in the providers.
427a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal */
43d8fa038aa7235468ecdcf2cda4e4d70eb97ba520Vikram Aggarwalpublic class FolderWatcher {
44de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal    public static final String FOLDER_URI = "FOLDER-URI";
457a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal    /** List of URIs that are watched. */
462b1c821c993676af1e295a247fe2843ecd26ecf3Vikram Aggarwal    private final List<Uri> mUris = new ArrayList<Uri>();
4777ee0ceaefaa9be699a20bfbe162f4c0ef83c6e1Vikram Aggarwal    /** Map returning the default inbox folder for each URI */
484c14ec6b03449a7d7e4ca0f91ee9fa3491cef29dTony Mantler    private final Map<Uri, Folder> mInboxMap = new HashMap<Uri, Folder>();
497a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal    private final RestrictedActivity mActivity;
50d8fa038aa7235468ecdcf2cda4e4d70eb97ba520Vikram Aggarwal    /** Handles folder callbacks and reads unread counts. */
51d8fa038aa7235468ecdcf2cda4e4d70eb97ba520Vikram Aggarwal    private final UnreadLoads mUnreadCallback = new UnreadLoads();
52d8fa038aa7235468ecdcf2cda4e4d70eb97ba520Vikram Aggarwal
531dd77c96938f9a96724f9c0112e6e2f1897faf49Vikram Aggarwal    /**
541dd77c96938f9a96724f9c0112e6e2f1897faf49Vikram Aggarwal     * The adapter that consumes this data. We use this only to notify the consumer that new data
551dd77c96938f9a96724f9c0112e6e2f1897faf49Vikram Aggarwal     * is available.
561dd77c96938f9a96724f9c0112e6e2f1897faf49Vikram Aggarwal     */
5716027b7fabaf488f10fe90a41af4ece25cf1ef10Andrew Sapperstein    private UnreadCountChangedListener mConsumer;
587a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal
597a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal    private final static String LOG_TAG = LogUtils.TAG;
607a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal
6116027b7fabaf488f10fe90a41af4ece25cf1ef10Andrew Sapperstein    public static interface UnreadCountChangedListener {
6216027b7fabaf488f10fe90a41af4ece25cf1ef10Andrew Sapperstein        void onUnreadCountChange();
6316027b7fabaf488f10fe90a41af4ece25cf1ef10Andrew Sapperstein    }
6416027b7fabaf488f10fe90a41af4ece25cf1ef10Andrew Sapperstein
657a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal    /**
667a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal     * Create a {@link FolderWatcher}.
67de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal     * @param activity Upstream activity
6816027b7fabaf488f10fe90a41af4ece25cf1ef10Andrew Sapperstein     * @param listener A listener to be notified when the unread count changes
697a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal     */
7016027b7fabaf488f10fe90a41af4ece25cf1ef10Andrew Sapperstein    public FolderWatcher(
7116027b7fabaf488f10fe90a41af4ece25cf1ef10Andrew Sapperstein            RestrictedActivity activity, @NonNull UnreadCountChangedListener listener) {
727a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal        mActivity = activity;
7316027b7fabaf488f10fe90a41af4ece25cf1ef10Andrew Sapperstein        mConsumer = listener;
747a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal    }
757a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal
767a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal    /**
77de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal     * Start watching all the accounts in this list and stop watching accounts NOT on this list.
78de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal     * Does nothing if the list of all accounts is null.
79de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal     * @param allAccounts all the current accounts on the device.
807a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal     */
81de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal    public void updateAccountList(Account[] allAccounts) {
82de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal        if (allAccounts == null) {
837a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal            return;
847a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal        }
85de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal        // Create list of Inbox URIs from the array of accounts.
86de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal        final List<Uri> newAccounts = new ArrayList<Uri>(allAccounts.length);
87de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal        for (final Account account : allAccounts) {
88de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal            newAccounts.add(account.settings.defaultInbox);
89de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal        }
90de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal        // Stop watching accounts not in the new list.
916bfae1c9b0623156265cb39d3c097a7cbeacb431Paul Westbrook        final List<Uri> uriCopy = Collections.unmodifiableList(Lists.newArrayList(mUris));
926bfae1c9b0623156265cb39d3c097a7cbeacb431Paul Westbrook        for (final Uri previous : uriCopy) {
93de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal            if (!newAccounts.contains(previous)) {
94de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal                stopWatching(previous);
95de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal            }
96de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal        }
97de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal        // Add accounts in the new list, that are not already watched.
98de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal        for (final Uri fresh : newAccounts) {
992b1c821c993676af1e295a247fe2843ecd26ecf3Vikram Aggarwal            if (!mUris.contains(fresh)) {
100de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal                startWatching(fresh);
101de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal            }
102de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal        }
103de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal    }
104de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal
105de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal    /**
106de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal     * Starts watching the given URI for changes. It is NOT safe to call this method repeatedly
107de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal     * for the same URI.
108de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal     * @param uri the URI for an inbox whose unread count is to be watched
109de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal     */
110de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal    private void startWatching(Uri uri) {
111de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal        final int location = insertAtNextEmptyLocation(uri);
112de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal        LogUtils.d(LOG_TAG, "Watching %s, at position %d.", uri, location);
11377ee0ceaefaa9be699a20bfbe162f4c0ef83c6e1Vikram Aggarwal        // No inbox folder yet, put a safe placeholder for now.
1144c14ec6b03449a7d7e4ca0f91ee9fa3491cef29dTony Mantler        mInboxMap.put(uri, null);
1157a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal        final LoaderManager lm = mActivity.getLoaderManager();
116de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal        final Bundle args = new Bundle();
117de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal        args.putString(FOLDER_URI, uri.toString());
118de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal        lm.initLoader(getLoaderFromPosition(location), args, mUnreadCallback);
1197a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal    }
1207a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal
1217a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal    /**
1222b1c821c993676af1e295a247fe2843ecd26ecf3Vikram Aggarwal     * Locates the next empty position in {@link #mUris} and inserts the URI there, returning the
123de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal     * location.
124de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal     * @return location where the URI was inserted.
1257a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal     */
126de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal    private int insertAtNextEmptyLocation(Uri newElement) {
127de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal        Uri uri;
128de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal        int location = -1;
1292b1c821c993676af1e295a247fe2843ecd26ecf3Vikram Aggarwal        for (int size = mUris.size(), i = 0; i < size; i++) {
1302b1c821c993676af1e295a247fe2843ecd26ecf3Vikram Aggarwal            uri = mUris.get(i);
131de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal            // Hole in the list, use this position
132de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal            if (uri == null) {
133de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal                location = i;
134de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal                break;
135de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal            }
136de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal        }
1370848874dababf76873290985168e9bf3d51d9c5dScott Kennedy
138de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal        if (location < 0) {
1390848874dababf76873290985168e9bf3d51d9c5dScott Kennedy            // No hole found, return the current size;
1402b1c821c993676af1e295a247fe2843ecd26ecf3Vikram Aggarwal            location = mUris.size();
1410848874dababf76873290985168e9bf3d51d9c5dScott Kennedy            mUris.add(location, newElement);
1420848874dababf76873290985168e9bf3d51d9c5dScott Kennedy        } else {
1430848874dababf76873290985168e9bf3d51d9c5dScott Kennedy            mUris.set(location, newElement);
144de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal        }
145de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal        return location;
1467a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal    }
1477a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal
1487a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal    /**
1492b1c821c993676af1e295a247fe2843ecd26ecf3Vikram Aggarwal     * Returns the loader ID for a position inside the {@link #mUris} table.
1502b1c821c993676af1e295a247fe2843ecd26ecf3Vikram Aggarwal     * @param position position in the {@link #mUris} list
151de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal     * @return a loader id
1527a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal     */
153de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal    private static int getLoaderFromPosition(int position) {
154de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal        return position + AbstractActivityController.LAST_LOADER_ID;
1557a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal    }
1567a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal
1577a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal    /**
158d8fa038aa7235468ecdcf2cda4e4d70eb97ba520Vikram Aggarwal     * Stops watching the given URI for folder changes. Subsequent calls to
159de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal     * {@link #getUnreadCount(Account)} for this uri will return null.
160de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal     * @param uri the URI for a folder
1617a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal     */
162de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal    private void stopWatching(Uri uri) {
1630848874dababf76873290985168e9bf3d51d9c5dScott Kennedy        if (uri == null) {
1640848874dababf76873290985168e9bf3d51d9c5dScott Kennedy            return;
1650848874dababf76873290985168e9bf3d51d9c5dScott Kennedy        }
1660848874dababf76873290985168e9bf3d51d9c5dScott Kennedy
1672b1c821c993676af1e295a247fe2843ecd26ecf3Vikram Aggarwal        final int id = mUris.indexOf(uri);
168de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal        // Does not exist in the list, we have stopped watching it already.
1697a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal        if (id < 0) {
1707a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal            return;
1717a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal        }
1727a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal        // Destroy the loader before removing references to the object.
1737a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal        final LoaderManager lm = mActivity.getLoaderManager();
1747a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal        lm.destroyLoader(getLoaderFromPosition(id));
1754c14ec6b03449a7d7e4ca0f91ee9fa3491cef29dTony Mantler        mInboxMap.remove(uri);
1760848874dababf76873290985168e9bf3d51d9c5dScott Kennedy        mUris.set(id, null);
1777a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal    }
1787a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal
1797a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal    /**
180de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal     * Returns the unread count for the default inbox for the account given. The account must be
181de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal     * watched with {@link #updateAccountList(Account[])}. If the account was not in an account
182de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal     * list passed previously, this method returns zero.
183de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal     * @param account an account whose unread count we wisht to track
184de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal     * @return the unread count if the account was in array passed previously to {@link
185de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal     * #updateAccountList(Account[])}. Zero otherwise.
1867a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal     */
187de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal    public final int getUnreadCount(Account account) {
18877ee0ceaefaa9be699a20bfbe162f4c0ef83c6e1Vikram Aggarwal        final Folder f = getDefaultInbox(account);
18977ee0ceaefaa9be699a20bfbe162f4c0ef83c6e1Vikram Aggarwal        if (f != null) {
19077ee0ceaefaa9be699a20bfbe162f4c0ef83c6e1Vikram Aggarwal            return f.unreadCount;
19177ee0ceaefaa9be699a20bfbe162f4c0ef83c6e1Vikram Aggarwal        }
19277ee0ceaefaa9be699a20bfbe162f4c0ef83c6e1Vikram Aggarwal        return 0;
19377ee0ceaefaa9be699a20bfbe162f4c0ef83c6e1Vikram Aggarwal    }
19477ee0ceaefaa9be699a20bfbe162f4c0ef83c6e1Vikram Aggarwal
19577ee0ceaefaa9be699a20bfbe162f4c0ef83c6e1Vikram Aggarwal    public final Folder getDefaultInbox(Account account) {
196de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal        final Uri uri = account.settings.defaultInbox;
1974c14ec6b03449a7d7e4ca0f91ee9fa3491cef29dTony Mantler        if (mInboxMap.containsKey(uri)) {
1984c14ec6b03449a7d7e4ca0f91ee9fa3491cef29dTony Mantler            final Folder candidate = mInboxMap.get(uri);
19977ee0ceaefaa9be699a20bfbe162f4c0ef83c6e1Vikram Aggarwal            if (candidate != null) {
20077ee0ceaefaa9be699a20bfbe162f4c0ef83c6e1Vikram Aggarwal                return candidate;
201d8fa038aa7235468ecdcf2cda4e4d70eb97ba520Vikram Aggarwal            }
202d8fa038aa7235468ecdcf2cda4e4d70eb97ba520Vikram Aggarwal        }
20377ee0ceaefaa9be699a20bfbe162f4c0ef83c6e1Vikram Aggarwal        return null;
2047a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal    }
2057a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal
206d8fa038aa7235468ecdcf2cda4e4d70eb97ba520Vikram Aggarwal    /**
207d8fa038aa7235468ecdcf2cda4e4d70eb97ba520Vikram Aggarwal     * Class to perform {@link LoaderManager.LoaderCallbacks} for populating unread counts.
208d8fa038aa7235468ecdcf2cda4e4d70eb97ba520Vikram Aggarwal     */
20977ee0ceaefaa9be699a20bfbe162f4c0ef83c6e1Vikram Aggarwal    private class UnreadLoads implements LoaderManager.LoaderCallbacks<ObjectCursor<Folder>> {
210d8fa038aa7235468ecdcf2cda4e4d70eb97ba520Vikram Aggarwal        // TODO(viki): Fix http://b/8494129 and read only the URI and unread count.
211b789b03fbedfb4fbaa0fb980725fbcd3e1d8d851Vikram Aggarwal        /** Only interested in the folder unread count, but asking for everything due to
212b789b03fbedfb4fbaa0fb980725fbcd3e1d8d851Vikram Aggarwal         * bug 8494129. */
213de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal        private final String[] projection = UIProvider.FOLDERS_PROJECTION;
214de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal
215d8fa038aa7235468ecdcf2cda4e4d70eb97ba520Vikram Aggarwal        @Override
21677ee0ceaefaa9be699a20bfbe162f4c0ef83c6e1Vikram Aggarwal        public Loader<ObjectCursor<Folder>> onCreateLoader(int id, Bundle args) {
217de60c9d0ad164a5daf358181a05bbd43edd5d5edVikram Aggarwal            final Uri uri = Uri.parse(args.getString(FOLDER_URI));
21877ee0ceaefaa9be699a20bfbe162f4c0ef83c6e1Vikram Aggarwal            return new ObjectCursorLoader<Folder>(mActivity.getActivityContext(), uri, projection,
21977ee0ceaefaa9be699a20bfbe162f4c0ef83c6e1Vikram Aggarwal                    Folder.FACTORY);
2207a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal        }
2217a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal
222d8fa038aa7235468ecdcf2cda4e4d70eb97ba520Vikram Aggarwal        @Override
22377ee0ceaefaa9be699a20bfbe162f4c0ef83c6e1Vikram Aggarwal        public void onLoadFinished(Loader<ObjectCursor<Folder>> loader, ObjectCursor<Folder> data) {
224d8fa038aa7235468ecdcf2cda4e4d70eb97ba520Vikram Aggarwal            if (data == null || data.getCount() <= 0 || !data.moveToFirst()) {
225d8fa038aa7235468ecdcf2cda4e4d70eb97ba520Vikram Aggarwal                return;
226d8fa038aa7235468ecdcf2cda4e4d70eb97ba520Vikram Aggarwal            }
22777ee0ceaefaa9be699a20bfbe162f4c0ef83c6e1Vikram Aggarwal            final Folder f = data.getModel();
228cd686c1cd99379c6d3ab66ccbfd7f6ae4e4eb67bScott Kennedy            final Uri uri = f.folderUri.getComparisonUri();
22977ee0ceaefaa9be699a20bfbe162f4c0ef83c6e1Vikram Aggarwal            final int unreadCount = f.unreadCount;
2304c14ec6b03449a7d7e4ca0f91ee9fa3491cef29dTony Mantler            final Folder previousFolder = mInboxMap.get(uri);
23177ee0ceaefaa9be699a20bfbe162f4c0ef83c6e1Vikram Aggarwal            final boolean unreadCountChanged = previousFolder == null
23277ee0ceaefaa9be699a20bfbe162f4c0ef83c6e1Vikram Aggarwal                    || unreadCount != previousFolder.unreadCount;
2334c14ec6b03449a7d7e4ca0f91ee9fa3491cef29dTony Mantler            mInboxMap.put(uri, f);
234d8fa038aa7235468ecdcf2cda4e4d70eb97ba520Vikram Aggarwal            // Once we have updated data, we notify the parent class that something new appeared.
23577ee0ceaefaa9be699a20bfbe162f4c0ef83c6e1Vikram Aggarwal            if (unreadCountChanged) {
23616027b7fabaf488f10fe90a41af4ece25cf1ef10Andrew Sapperstein                mConsumer.onUnreadCountChange();
23721115dcf79619a8fd63378ba89c5944b1256a7abVikram Aggarwal            }
2387a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal        }
2397a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal
240d8fa038aa7235468ecdcf2cda4e4d70eb97ba520Vikram Aggarwal        @Override
24177ee0ceaefaa9be699a20bfbe162f4c0ef83c6e1Vikram Aggarwal        public void onLoaderReset(Loader<ObjectCursor<Folder>> loader) {
242d8fa038aa7235468ecdcf2cda4e4d70eb97ba520Vikram Aggarwal            // Do nothing.
243d8fa038aa7235468ecdcf2cda4e4d70eb97ba520Vikram Aggarwal        }
2447a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal    }
2457a5d95a08464fb82b0310c82f3c39bfb8b63539fVikram Aggarwal}
246