Merge "Add rawFolders column to conversation."
diff --git a/src/com/android/mail/ui/AbstractActivityController.java b/src/com/android/mail/ui/AbstractActivityController.java
index eeee13c..44a20e0 100644
--- a/src/com/android/mail/ui/AbstractActivityController.java
+++ b/src/com/android/mail/ui/AbstractActivityController.java
@@ -114,9 +114,11 @@
     private boolean mFolderTouched = false;
 
     protected static final String LOG_TAG = new LogUtils().getLogTag();
-    private static final int ACCOUNT_CURSOR_LOADER = 0;
-    private static final int ACCOUNT_SETTINGS_LOADER = 1;
-    private static final int FOLDER_CURSOR_LOADER = 2;
+    /** Constants used to differentiate between the types of loaders. */
+    private static final int LOADER_ACCOUNT_CURSOR = 0;
+    private static final int LOADER_ACCOUNT_SETTINGS = 1;
+    private static final int LOADER_FOLDER_CURSOR = 2;
+    private static final int LOADER_RECENT_FOLDERS = 3;
 
     public AbstractActivityController(MailActivity activity, ViewMode viewMode) {
         mActivity = activity;
@@ -225,7 +227,8 @@
     public void onAccountChanged(Account account) {
         if (!account.equals(mAccount)) {
             mAccount = account;
-            mRecentFolderList.changeCurrentAccount(account);
+            mRecentFolderList.setCurrentAccount(account);
+            mActivity.getLoaderManager().restartLoader(LOADER_RECENT_FOLDERS, null, this);
             onSettingsChanged(null);
             restartSettingsLoader();
             mActionBarView.setAccount(mAccount);
@@ -238,7 +241,7 @@
 
     private void restartSettingsLoader() {
         if (mAccount.settingsQueryUri != null) {
-            mActivity.getLoaderManager().restartLoader(ACCOUNT_SETTINGS_LOADER, null, this);
+            mActivity.getLoaderManager().restartLoader(LOADER_ACCOUNT_SETTINGS, null, this);
         }
     }
 
@@ -286,7 +289,7 @@
             mFolder = folder;
             mFolderTouched = false;
             mActionBarView.setFolder(mFolder);
-            mActivity.getLoaderManager().restartLoader(FOLDER_CURSOR_LOADER, null, this);
+            mActivity.getLoaderManager().restartLoader(LOADER_FOLDER_CURSOR, null, this);
         } else if (folder == null) {
             LogUtils.wtf(LOG_TAG, "Folder in setFolder is null");
         }
@@ -512,7 +515,7 @@
                 if (intent.hasExtra(Utils.EXTRA_ACCOUNT)) {
                     mAccount = ((Account) intent.getParcelableExtra(Utils.EXTRA_ACCOUNT));
                     mActionBarView.setAccount(mAccount);
-                    mActivity.getLoaderManager().restartLoader(ACCOUNT_SETTINGS_LOADER, null, this);
+                    mActivity.getLoaderManager().restartLoader(LOADER_ACCOUNT_SETTINGS, null, this);
                     mActivity.invalidateOptionsMenu();
                 }
                 if (intent.hasExtra(Utils.EXTRA_FOLDER)) {
@@ -536,7 +539,7 @@
             }
         }
         // Create the accounts loader; this loads the account switch spinner.
-        mActivity.getLoaderManager().initLoader(ACCOUNT_CURSOR_LOADER, null, this);
+        mActivity.getLoaderManager().initLoader(LOADER_ACCOUNT_CURSOR, null, this);
     }
 
     @Override
@@ -576,17 +579,23 @@
     @Override
     public Loader<Cursor> onCreateLoader(int id, Bundle args) {
         // Create a loader to listen in on account changes.
-        if (id == ACCOUNT_CURSOR_LOADER) {
-            return new CursorLoader(mContext, AccountCacheProvider.getAccountsUri(),
-                    UIProvider.ACCOUNTS_PROJECTION, null, null, null);
-        } else if (id == FOLDER_CURSOR_LOADER) {
-            return new CursorLoader(mActivity.getActivityContext(), mFolder.uri,
-                    UIProvider.FOLDERS_PROJECTION, null, null, null);
-        } else if (id == ACCOUNT_SETTINGS_LOADER) {
-            if (mAccount.settingsQueryUri != null) {
-                return new CursorLoader(mActivity.getActivityContext(), mAccount.settingsQueryUri,
-                        UIProvider.SETTINGS_PROJECTION, null, null, null);
-            }
+        switch (id) {
+            case LOADER_ACCOUNT_CURSOR:
+                return new CursorLoader(mContext, AccountCacheProvider.getAccountsUri(),
+                        UIProvider.ACCOUNTS_PROJECTION, null, null, null);
+            case LOADER_FOLDER_CURSOR:
+                return new CursorLoader(mContext, mFolder.uri,
+                        UIProvider.FOLDERS_PROJECTION, null, null, null);
+            case LOADER_ACCOUNT_SETTINGS:
+                if (mAccount.settingsQueryUri != null) {
+                    return new CursorLoader(mContext, mAccount.settingsQueryUri,
+                            UIProvider.SETTINGS_PROJECTION, null, null, null);
+                }
+            case LOADER_RECENT_FOLDERS:
+                return new CursorLoader(mContext, mAccount.recentFolderListUri,
+                        UIProvider.FOLDERS_PROJECTION, null, null, null);
+            default:
+                LogUtils.wtf(LOG_TAG, "Loader returned unexpected id: " + id);
         }
         return null;
     }
@@ -670,19 +679,20 @@
     public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
         // We want to reinitialize only if we haven't ever been initialized, or
         // if the current account has vanished.
-        final int id = loader.getId();
         if (data == null) {
-            LogUtils.e(LOG_TAG, "Received null cursor from loader id: %d", id);
+            LogUtils.e(LOG_TAG, "Received null cursor from loader id: %d", loader.getId());
         }
-        if (id == ACCOUNT_CURSOR_LOADER) {
-
-            final boolean accountListUpdated = accountsUpdated(data);
-            if (!isLoaderInitialized || accountListUpdated) {
-                isLoaderInitialized = updateAccounts(loader, data);
-            }
-        } else if (id == FOLDER_CURSOR_LOADER) {
-            // Check status of the cursor.
-            if (data != null) {
+        switch (loader.getId()) {
+            case LOADER_ACCOUNT_CURSOR:
+                final boolean accountListUpdated = accountsUpdated(data);
+                if (!isLoaderInitialized || accountListUpdated) {
+                    isLoaderInitialized = updateAccounts(loader, data);
+                }
+                break;
+            case LOADER_FOLDER_CURSOR:
+                if (data == null)
+                    return;
+                // Check status of the cursor.
                 data.moveToFirst();
                 Folder folder = new Folder(data);
                 if (folder.isSyncInProgress()) {
@@ -695,12 +705,18 @@
                     mConversationListFragment.onFolderUpdated(folder);
                 }
                 LogUtils.v(LOG_TAG, "FOLDER STATUS = " + folder.syncStatus);
-            }
-        } else if (id == ACCOUNT_SETTINGS_LOADER) {
-            if (data != null) {
+                break;
+            case LOADER_ACCOUNT_SETTINGS:
+                if (data == null)
+                    return;
                 data.moveToFirst();
                 onSettingsChanged(new Settings(data));
-            }
+                break;
+            case LOADER_RECENT_FOLDERS:
+                if (data == null)
+                    return;
+                mRecentFolderList.loadFromUiProvider(data);
+                break;
         }
     }
 
diff --git a/src/com/android/mail/ui/RecentFolderList.java b/src/com/android/mail/ui/RecentFolderList.java
index c1c6279..59a65e3 100644
--- a/src/com/android/mail/ui/RecentFolderList.java
+++ b/src/com/android/mail/ui/RecentFolderList.java
@@ -21,6 +21,7 @@
 import android.content.Context;
 import android.database.Cursor;
 import android.text.TextUtils;
+import android.os.AsyncTask;
 
 import com.android.mail.providers.Account;
 import com.android.mail.providers.Folder;
@@ -63,6 +64,22 @@
      *  to the user).
      */
     private final static int NUM_FOLDERS = 5 + 1;
+    /**
+     * Class to store the recent folder list asynchronously.
+     */
+    private class StoreRecent extends AsyncTask<ContentValues, Void, Void> {
+        final ContentResolver mResolver;
+
+        public StoreRecent(Context context) {
+            mResolver = context.getContentResolver();
+        }
+
+        @Override
+        protected Void doInBackground(ContentValues... valuesArray) {
+            mResolver.update(mAccount.recentFolderListUri, valuesArray[0], null, null);
+            return null;
+        }
+    }
 
     /**
      * Create a Recent Folder List from the given account. This will query the UIProvider to
@@ -70,37 +87,33 @@
      * @param account
      */
     public RecentFolderList(Context context) {
-        mContext = context;
         mFolderCache = new LruCache<String, Folder>(NUM_FOLDERS);
+        mContext = context;
     }
 
     /**
      * Change the current account. This causes the recent label list to be written out to the
-     * provider, and a new list to be read for the new account.
+     * provider. When a cursor over the recent folders for this account is available, the client
+     * <b>must</b> call {@link #loadFromUiProvider(Cursor)} with the updated cursor. Till then,
+     * the recent account list will be empty.
      * @param account
      */
-    public void changeCurrentAccount(Account account) {
+    public void setCurrentAccount(Account account) {
         saveToUiProvider();
         mAccount = account;
-        loadFromUiProvider();
+        // At some point in the future, the load method will return and populate our cache with
+        // useful entries. But for now, the cache is invalid.
+        mFolderCache.clear();
     }
 
     /**
-     * Load the account information from the UI provider.
+     * Load the account information from the UI provider given the cursor over the recent folders.
+     * @param data a cursor over the recent folders.
      */
-    private void loadFromUiProvider() {
-        if (mAccount == null || mAccount.recentFolderListUri == null)
+    public void loadFromUiProvider(Cursor data) {
+        if (mAccount == null || mAccount.recentFolderListUri == null || data == null
+                || data.getCount() <= 0)
             return;
-        mFolderCache.clear();
-        final ContentResolver mResolver = mContext.getContentResolver();
-        // TODO(viki): Bad idea. Use a loader.
-        Cursor data = mResolver.query(mAccount.recentFolderListUri, UIProvider.FOLDERS_PROJECTION,
-                null, null, null);
-        if (data == null || data.getCount() <= 0) {
-            // No pre-stored recent folder list. Let's return an empty folder list.
-            return;
-        }
-        // Populate the recent folder cache from the UiProvider.
         int i = 0;
         while (data.moveToNext()) {
             assert (data.getColumnCount() == UIProvider.FOLDERS_PROJECTION.length);
@@ -130,18 +143,20 @@
     private void saveToUiProvider() {
         if (mAccount == null || mFolderCache.isEmpty() || mAccount.recentFolderListUri == null)
             return;
+        // TODO: Remove this test
+        if (TextUtils.equals("null", mAccount.recentFolderListUri.toString()))
+            return;
+
         // Write the current recent folder list into the account.
         // Store the ID of the folder and the last touched timestamp.
         ContentValues values = new ContentValues();
+        // TODO(viki): Fix the timestamps here, and put real timestamps rather than garbage.
         final long now = System.currentTimeMillis();
         for (String id : mFolderCache.keySet()) {
             values.put(id, now);
         }
-        final ContentResolver mResolver = mContext.getContentResolver();
-        // TODO: Remove this test
-        if (!TextUtils.equals("null", mAccount.recentFolderListUri.toString())) {
-            mResolver.update(mAccount.recentFolderListUri, values, null, null);
-        }
+        // Store the values in the background.
+        new StoreRecent(mContext).execute(values);
     }
 
     /**