Merge "Revert "Fix hierarchical folders"" into jb-ub-mail-ur10
diff --git a/src/com/android/mail/ui/AbstractActivityController.java b/src/com/android/mail/ui/AbstractActivityController.java
index ad59023..62702c1 100644
--- a/src/com/android/mail/ui/AbstractActivityController.java
+++ b/src/com/android/mail/ui/AbstractActivityController.java
@@ -38,7 +38,6 @@
 import android.content.Loader;
 import android.content.res.Configuration;
 import android.content.res.Resources;
-import android.database.Cursor;
 import android.database.DataSetObservable;
 import android.database.DataSetObserver;
 import android.net.Uri;
@@ -157,8 +156,6 @@
     private static final String SAVED_ACTION_FROM_SELECTED = "saved-action-from-selected";
     /** Tag for {@link #mDetachedConvUri} */
     private static final String SAVED_DETACHED_CONV_URI = "saved-detached-conv-uri";
-    /** Key to store {@link #mInbox}. */
-    private final static String SAVED_INBOX_KEY = "m-inbox";
 
     /** Tag  used when loading a wait fragment */
     protected static final String TAG_WAIT = "wait-fragment";
@@ -174,7 +171,6 @@
 
     protected Account mAccount;
     protected Folder mFolder;
-    protected Folder mInbox;
     /** True when {@link #mFolder} is first shown to the user. */
     private boolean mFolderChanged = false;
     protected MailActionBarView mActionBarView;
@@ -831,7 +827,7 @@
     }
 
     @Override
-    public void onFolderChanged(Folder folder, final boolean force) {
+    public void onFolderChanged(Folder folder) {
         /** If the folder doesn't exist, or its parent URI is empty,
          * this is not a child folder */
         final boolean isTopLevel = (folder == null) || (folder.parent == Uri.EMPTY);
@@ -842,7 +838,7 @@
                 ? DrawerLayout.LOCK_MODE_UNLOCKED : DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
 
         mDrawerContainer.closeDrawers();
-        changeFolder(folder, null, force);
+        changeFolder(folder, null);
     }
 
     /**
@@ -865,14 +861,12 @@
      * Changes the folder to the value provided here. This causes the view mode to change.
      * @param folder the folder to change to
      * @param query if non-null, this represents the search string that the folder represents.
-     * @param force <code>true</code> to force a folder change, <code>false</code> to disallow
-     *          changing to the current folder
      */
-    private void changeFolder(Folder folder, String query, final boolean force) {
+    private void changeFolder(Folder folder, String query) {
         if (!Objects.equal(mFolder, folder)) {
             commitDestructiveActions(false);
         }
-        if (folder != null && (!folder.equals(mFolder) || force)
+        if (folder != null && !folder.equals(mFolder)
                 || (mViewMode.getMode() != ViewMode.CONVERSATION_LIST)) {
             setListContext(folder, query);
             showConversationList(mConvListContext);
@@ -884,7 +878,7 @@
 
     @Override
     public void onFolderSelected(Folder folder) {
-        onFolderChanged(folder, false /* force */);
+        onFolderChanged(folder);
     }
 
     /**
@@ -917,7 +911,7 @@
         if (mFolderWatcher != null) {
             final Folder inbox = mFolderWatcher.getDefaultInbox(mAccount);
             if (inbox != null) {
-                onFolderChanged(inbox, false /* force */);
+                onFolderChanged(inbox);
                 handled = true;
             }
         }
@@ -2035,8 +2029,6 @@
 
         outState.putParcelable(SAVED_HIERARCHICAL_FOLDER, mFolderListFolder);
         mSafeToModifyFragments = false;
-
-        outState.putParcelable(SAVED_INBOX_KEY, mInbox);
     }
 
     /**
@@ -2252,8 +2244,6 @@
         if (mDialogAction != -1) {
             makeDialogListener(mDialogAction, mDialogFromSelectedSet);
         }
-
-        mInbox = savedState.getParcelable(SAVED_INBOX_KEY);
     }
 
     /**
@@ -3491,7 +3481,7 @@
                 case LOADER_ACCOUNT_INBOX:
                     if (data != null && !data.isClosed() && data.moveToFirst()) {
                         final Folder inbox = data.getModel();
-                        onFolderChanged(inbox, false /* force */);
+                        onFolderChanged(inbox);
                         // Just want to get the inbox, don't care about updates to it
                         // as this will be tracked by the folder change listener.
                         mActivity.getLoaderManager().destroyLoader(LOADER_ACCOUNT_INBOX);
@@ -3523,7 +3513,7 @@
                     final Folder folder = data.getModel();
                     boolean handled = false;
                     if (folder != null) {
-                        onFolderChanged(folder, false /* force */);
+                        onFolderChanged(folder);
                         handled = true;
                     }
                     if (mConversationToShow != null) {
@@ -4254,53 +4244,4 @@
     public boolean shouldHideMenuItems() {
         return mHideMenuItems;
     }
-
-    protected void navigateUpFolderHierarchy() {
-        new AsyncTask<Void, Void, Folder>() {
-            @Override
-            protected Folder doInBackground(final Void... params) {
-                if (mInbox == null) {
-                    // We don't have an inbox, but we need it
-                    final Cursor cursor = mContext.getContentResolver().query(
-                            mAccount.settings.defaultInbox, UIProvider.FOLDERS_PROJECTION, null,
-                            null, null);
-
-                    if (cursor != null) {
-                        try {
-                            if (cursor.moveToFirst()) {
-                                mInbox = new Folder(cursor);
-                            }
-                        } finally {
-                            cursor.close();
-                        }
-                    }
-                }
-
-                // Now try to load our parent
-                final Folder folder;
-
-                final Cursor cursor = mContext.getContentResolver().query(mFolder.parent,
-                        UIProvider.FOLDERS_PROJECTION, null, null, null);
-
-                if (cursor == null) {
-                    // We couldn't load the parent, so use the inbox
-                    folder = mInbox;
-                } else {
-                    try {
-                        cursor.moveToFirst();
-                        folder = new Folder(cursor);
-                    } finally {
-                        cursor.close();
-                    }
-                }
-
-                return folder;
-            }
-
-            @Override
-            protected void onPostExecute(final Folder result) {
-                onFolderSelected(result);
-            }
-        }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null);
-    }
 }
diff --git a/src/com/android/mail/ui/FolderChangeListener.java b/src/com/android/mail/ui/FolderChangeListener.java
index 0968fa7..cc9c051 100644
--- a/src/com/android/mail/ui/FolderChangeListener.java
+++ b/src/com/android/mail/ui/FolderChangeListener.java
@@ -26,8 +26,6 @@
      * Handles selecting a folder from within the {@link FolderListFragment}.
      *
      * @param folder the selected folder
-     * @param force <code>true</code> to force a folder change, <code>false</code> to disallow
-     *          changing to the current folder
      */
-    void onFolderChanged(Folder folder, boolean force);
+    void onFolderChanged(Folder folder);
 }
diff --git a/src/com/android/mail/ui/FolderListFragment.java b/src/com/android/mail/ui/FolderListFragment.java
index ea1dcdc..7eee145 100644
--- a/src/com/android/mail/ui/FolderListFragment.java
+++ b/src/com/android/mail/ui/FolderListFragment.java
@@ -216,7 +216,7 @@
      */
     private static Bundle getBundleFromArgs(Folder parentFolder, Uri folderListUri,
             final ArrayList<Integer> excludedFolderTypes) {
-        final Bundle args = new Bundle(3);
+        final Bundle args = new Bundle();
         if (parentFolder != null) {
             args.putParcelable(ARG_PARENT_FOLDER, parentFolder);
         }
@@ -1077,6 +1077,10 @@
         }
     }
 
+    public Folder getParentFolder() {
+        return mParentFolder;
+    }
+
     /**
      * Sets the currently selected folder safely.
      * @param folder the folder to change to. It is an error to pass null here.
@@ -1157,6 +1161,14 @@
     }
 
     /**
+     * Get whether the FolderListFragment is currently showing the hierarchy
+     * under a single parent.
+     */
+    public boolean showingHierarchy() {
+        return mParentFolder != null;
+    }
+
+    /**
      * Checks if the specified {@link Folder} is a type that we want to exclude from displaying.
      */
     private boolean isFolderTypeExcluded(final Folder folder) {
diff --git a/src/com/android/mail/ui/FolderSelectionActivity.java b/src/com/android/mail/ui/FolderSelectionActivity.java
index 16b74a5..14a1089 100644
--- a/src/com/android/mail/ui/FolderSelectionActivity.java
+++ b/src/com/android/mail/ui/FolderSelectionActivity.java
@@ -266,7 +266,7 @@
     }
 
     @Override
-    public void onFolderChanged(Folder folder, final boolean force) {
+    public void onFolderChanged(Folder folder) {
         if (!folder.equals(mSelectedFolder)) {
             mSelectedFolder = folder;
             Intent resultIntent = new Intent();
@@ -350,7 +350,7 @@
             createFolderListFragment(FolderListFragment.ofTree(folder));
             return;
         }
-        onFolderChanged(folder, false /* force */);
+        onFolderChanged(folder);
     }
 
     @Override
diff --git a/src/com/android/mail/ui/OnePaneController.java b/src/com/android/mail/ui/OnePaneController.java
index 8ce5c0c..ffd1a04 100644
--- a/src/com/android/mail/ui/OnePaneController.java
+++ b/src/com/android/mail/ui/OnePaneController.java
@@ -20,7 +20,10 @@
 import android.app.Fragment;
 import android.app.FragmentManager;
 import android.app.FragmentTransaction;
+import android.app.LoaderManager.LoaderCallbacks;
+import android.database.Cursor;
 import android.net.Uri;
+import android.os.AsyncTask;
 import android.os.Bundle;
 import android.support.v4.widget.DrawerLayout;
 import android.widget.ListView;
@@ -32,6 +35,7 @@
 import com.android.mail.providers.Folder;
 import com.android.mail.providers.UIProvider;
 import com.android.mail.utils.FolderUri;
+import com.android.mail.utils.LogUtils;
 import com.android.mail.utils.Utils;
 
 /**
@@ -40,6 +44,9 @@
  */
 
 public final class OnePaneController extends AbstractActivityController {
+    /** Key used to store {@link #mLastInboxConversationListTransactionId} */
+    private static final String INBOX_CONVERSATION_LIST_TRANSACTION_KEY =
+            "inbox_conversation-list-transaction";
     /** Key used to store {@link #mLastConversationListTransactionId} */
     private static final String CONVERSATION_LIST_TRANSACTION_KEY = "conversation-list-transaction";
     /** Key used to store {@link #mLastConversationTransactionId}. */
@@ -48,11 +55,15 @@
     private static final String CONVERSATION_LIST_VISIBLE_KEY = "conversation-list-visible";
     /** Key used to store {@link #mConversationListNeverShown}. */
     private static final String CONVERSATION_LIST_NEVER_SHOWN_KEY = "conversation-list-never-shown";
+    /** Key to store {@link #mInbox}. */
+    private final static String SAVED_INBOX_KEY = "m-inbox";
 
     private static final int INVALID_ID = -1;
     private boolean mConversationListVisible = false;
+    private int mLastInboxConversationListTransactionId = INVALID_ID;
     private int mLastConversationListTransactionId = INVALID_ID;
     private int mLastConversationTransactionId = INVALID_ID;
+    private Folder mInbox;
     /** Whether a conversation list for this account has ever been shown.*/
     private boolean mConversationListNeverShown = true;
 
@@ -66,20 +77,26 @@
         if (inState == null) {
             return;
         }
+        mLastInboxConversationListTransactionId =
+                inState.getInt(INBOX_CONVERSATION_LIST_TRANSACTION_KEY, INVALID_ID);
         mLastConversationListTransactionId =
                 inState.getInt(CONVERSATION_LIST_TRANSACTION_KEY, INVALID_ID);
         mLastConversationTransactionId = inState.getInt(CONVERSATION_TRANSACTION_KEY, INVALID_ID);
         mConversationListVisible = inState.getBoolean(CONVERSATION_LIST_VISIBLE_KEY);
         mConversationListNeverShown = inState.getBoolean(CONVERSATION_LIST_NEVER_SHOWN_KEY);
+        mInbox = inState.getParcelable(SAVED_INBOX_KEY);
     }
 
     @Override
     public void onSaveInstanceState(Bundle outState) {
         super.onSaveInstanceState(outState);
+        outState.putInt(INBOX_CONVERSATION_LIST_TRANSACTION_KEY,
+                mLastInboxConversationListTransactionId);
         outState.putInt(CONVERSATION_LIST_TRANSACTION_KEY, mLastConversationListTransactionId);
         outState.putInt(CONVERSATION_TRANSACTION_KEY, mLastConversationTransactionId);
         outState.putBoolean(CONVERSATION_LIST_VISIBLE_KEY, mConversationListVisible);
         outState.putBoolean(CONVERSATION_LIST_NEVER_SHOWN_KEY, mConversationListNeverShown);
+        outState.putParcelable(SAVED_INBOX_KEY, mInbox);
     }
 
     @Override
@@ -158,6 +175,8 @@
     @Override
     public String toString() {
         final StringBuilder sb = new StringBuilder(super.toString());
+        sb.append(" lastInboxTransId=");
+        sb.append(mLastInboxConversationListTransactionId);
         sb.append(" lastConvListTransId=");
         sb.append(mLastConversationListTransactionId);
         sb.append("}");
@@ -183,13 +202,13 @@
         if (!inInbox(mAccount, listContext)) {
             // Maintain fragment transaction history so we can get back to the
             // fragment used to launch this list.
-            mLastConversationListTransactionId = replaceFragment(conversationListFragment,
+            mLastConversationListTransactionId = replaceFragmentWithBack(conversationListFragment,
                     transition, TAG_CONVERSATION_LIST, R.id.content_pane);
         } else {
             // If going to the inbox, clear the folder list transaction history.
             mInbox = listContext.folder;
-            replaceFragment(conversationListFragment, transition, TAG_CONVERSATION_LIST,
-                    R.id.content_pane);
+            mLastInboxConversationListTransactionId = replaceFragmentWithBack(
+                    conversationListFragment, transition, TAG_CONVERSATION_LIST, R.id.content_pane);
 
             // If we ever to to the inbox, we want to unset the transation id for any other
             // non-inbox folder.
@@ -208,7 +227,7 @@
         super.showConversation(conversation, inLoaderCallbacks);
         mConversationListVisible = false;
         if (conversation == null) {
-            transitionBackToConversationListMode();
+            transitionBackToConversationListMode(inLoaderCallbacks);
             return;
         }
         disableCabMode();
@@ -277,17 +296,30 @@
     /**
      * Replace the content_pane with the fragment specified here. The tag is specified so that
      * the {@link ActivityController} can look up the fragments through the
-     * {@link android.app.FragmentManager}.
+     * {@link android.app.FragmentManager}. This action will be placed on the back stack.
      * @param fragment the new fragment to put
      * @param transition the transition to show
      * @param tag a tag for the fragment manager.
      * @param anchor ID of view to replace fragment in
      * @return transaction ID returned when the transition is committed.
      */
-    private int replaceFragment(Fragment fragment, int transition, String tag, int anchor) {
+    private int replaceFragmentWithBack(Fragment fragment, int transition, String tag, int anchor) {
+        return replaceFragment(fragment, transition, tag, anchor, true);
+    }
+
+    // (Not on the back stack -> no transaction ID to return.)
+    private void replaceFragment(Fragment fragment, int transition, String tag, int anchor) {
+        replaceFragment(fragment, transition, tag, anchor, false);
+    }
+
+    private int replaceFragment(Fragment fragment, int transition, String tag, int anchor,
+            boolean addToBackStack) {
         final FragmentManager fm = mActivity.getFragmentManager();
         FragmentTransaction fragmentTransaction = fm.beginTransaction();
         fragmentTransaction.setTransition(transition);
+        if (addToBackStack) {
+            fragmentTransaction.addToBackStack(null);
+        }
         fragmentTransaction.replace(anchor, fragment, tag);
         final int id = fragmentTransaction.commitAllowingStateLoss();
         fm.executePendingTransactions();
@@ -315,9 +347,9 @@
         if (mode == ViewMode.SEARCH_RESULTS_LIST) {
             mActivity.finish();
         } else if (mViewMode.isListMode() && !inInbox(mAccount, mConvListContext)) {
-            navigateUpFolderHierarchy();
+            transitionToInbox();
         } else if (mViewMode.isConversationMode() || mViewMode.isAdMode()) {
-            transitionBackToConversationListMode();
+            transitionBackToConversationListMode(false /* inLoaderCallbacks */);
         } else {
             mActivity.finish();
         }
@@ -325,6 +357,39 @@
         return true;
     }
 
+    private void goUpFolderHierarchy(Folder current) {
+        // This code is currently never called. Now that we have the URI, load the parent, if
+        // required. http://b/9694899
+        // onFolderSelected(current.parent);
+    }
+
+    private void navigateUp() {
+        new AsyncTask<Void, Void, Folder>() {
+            @Override
+            protected Folder doInBackground(final Void... params) {
+                final Folder folder;
+
+                final Cursor cursor = mContext.getContentResolver().query(mFolder.parent,
+                        UIProvider.FOLDERS_PROJECTION, null, null, null);
+
+                if (cursor == null) {
+                    folder = mInbox;
+                } else {
+                    cursor.moveToFirst();
+                    folder = new Folder(cursor);
+                    cursor.close();
+                }
+
+                return folder;
+            }
+
+            @Override
+            protected void onPostExecute(final Folder result) {
+                onFolderSelected(result);
+            }
+        }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null);
+    }
+
     /**
      * Switch to the Inbox by creating a new conversation list context that loads the inbox.
      */
@@ -333,7 +398,7 @@
         if (mInbox == null || !isDefaultInbox(mInbox.folderUri, mAccount)) {
             loadAccountInbox();
         } else {
-            onFolderChanged(mInbox, false /* force */);
+            onFolderChanged(mInbox);
         }
     }
 
@@ -343,6 +408,10 @@
         super.onFolderSelected(folder);
     }
 
+    private static boolean isTransactionIdValid(int id) {
+        return id >= 0;
+    }
+
     /**
      * Up works as follows:
      * 1) If the user is in a conversation list that is not the default account inbox,
@@ -365,7 +434,7 @@
                 // Show the drawer.
                 toggleDrawerState();
             } else {
-                navigateUpFolderHierarchy();
+                navigateUp();
             }
         } else if (mode == ViewMode.CONVERSATION || mode == ViewMode.SEARCH_RESULTS_CONVERSATION
                 || mode == ViewMode.AD) {
@@ -375,7 +444,7 @@
         return true;
     }
 
-    private void transitionBackToConversationListMode() {
+    private void transitionBackToConversationListMode(boolean inLoaderCallbacks) {
         final int mode = mViewMode.getMode();
         enableCabMode();
         mConversationListVisible = true;
@@ -384,14 +453,50 @@
         } else {
             mViewMode.enterConversationListMode();
         }
-
-        final Folder folder = mFolder != null ? mFolder : mInbox;
-        onFolderChanged(folder, true /* force */);
-
+        if (isTransactionIdValid(mLastConversationListTransactionId)) {
+            safelyPopBackStack(mLastConversationListTransactionId, inLoaderCallbacks);
+        } else if (isTransactionIdValid(mLastInboxConversationListTransactionId)) {
+            safelyPopBackStack(mLastInboxConversationListTransactionId, inLoaderCallbacks);
+            onFolderChanged(mInbox);
+        } else {
+            // TODO: revisit if this block is necessary
+            // Set the correct context for what the conversation view will be now.
+            onFolderChanged(mInbox);
+        }
         onConversationVisibilityChanged(false);
         onConversationListVisibilityChanged(true);
     }
 
+    /**
+     * Pop to a specified point in the fragment back stack without causing IllegalStateExceptions
+     * from committing a fragment transaction "at the wrong time".
+     * <p>
+     * If the caller specifies that we are in
+     * the scope of an {@link LoaderCallbacks#onLoadFinished(android.content.Loader, Object)},
+     * this method will pop back in a Handler. The deferred job will also check that the Activity
+     * is in a valid state for fragment transactions, using {@link #safeToModifyFragments()}.
+     * Otherwise, this method will pop back immediately if safe. Finally, if we are not in
+     * onLoadFinished and it's not safe, this method will just ignore the request.
+     *
+     * @param transactionId back stack destination to pop to, or -1 to just pop the top
+     * @param inLoaderCallbacks whether we are in the scope of an onLoadFinished (when fragment
+     * transactions are disallowed)
+     */
+    private void safelyPopBackStack(int transactionId, boolean inLoaderCallbacks) {
+        final PopBackStackRunnable r = new PopBackStackRunnable(transactionId);
+        if (inLoaderCallbacks) {
+            // always run deferred. ensure deferred job checks safety.
+            mHandler.post(r);
+        } else if (safeToModifyFragments()) {
+            // run now
+            r.popBackStack();
+        } else {
+            // ignore
+            LogUtils.i(LOG_TAG, "Activity has been saved; ignoring unsafe immediate request"
+                    + " to pop back stack");
+        }
+    }
+
     @Override
     public boolean shouldShowFirstConversation() {
         return false;
@@ -453,6 +558,34 @@
         }
     }
 
+    private final class PopBackStackRunnable implements Runnable {
+
+        private final int mTransactionId;
+
+        public PopBackStackRunnable(int transactionId) {
+            mTransactionId = transactionId;
+        }
+
+        public void popBackStack() {
+            final FragmentManager fm = mActivity.getFragmentManager();
+            if (mTransactionId < 0) {
+                fm.popBackStackImmediate();
+            } else {
+                fm.popBackStackImmediate(mTransactionId, 0);
+            }
+        }
+
+        @Override
+        public void run() {
+            if (safeToModifyFragments()) {
+                popBackStack();
+            } else {
+                LogUtils.i(LOG_TAG, "Activity has been saved; ignoring unsafe deferred request"
+                        + " to pop back stack");
+            }
+        }
+    }
+
     @Override
     public boolean isDrawerEnabled() {
         // The drawer is enabled for one pane mode
@@ -467,7 +600,7 @@
 
     @Override
     public void launchFragment(final Fragment fragment, final int selectPosition) {
-        replaceFragment(fragment, FragmentTransaction.TRANSIT_FRAGMENT_OPEN,
+        replaceFragmentWithBack(fragment, FragmentTransaction.TRANSIT_FRAGMENT_OPEN,
                 TAG_CUSTOM_FRAGMENT, R.id.content_pane);
     }
 }
diff --git a/src/com/android/mail/ui/TwoPaneController.java b/src/com/android/mail/ui/TwoPaneController.java
index 0269b56..ff022e2 100644
--- a/src/com/android/mail/ui/TwoPaneController.java
+++ b/src/com/android/mail/ui/TwoPaneController.java
@@ -159,8 +159,8 @@
     }
 
     @Override
-    public void onFolderChanged(Folder folder, final boolean force) {
-        super.onFolderChanged(folder, force);
+    public void onFolderChanged(Folder folder) {
+        super.onFolderChanged(folder);
         exitCabMode();
     }
 
@@ -171,7 +171,7 @@
             mViewMode.enterConversationListMode();
         }
 
-        if (folder.parent != Uri.EMPTY) {
+        if (folder.hasChildren) {
             // Show the up affordance when digging into child folders.
             mActionBarView.setBackButton();
         }
@@ -179,6 +179,15 @@
         super.onFolderSelected(folder);
     }
 
+    private void goUpFolderHierarchy(Folder current) {
+        // If the current folder is a child, up should show the parent folder.
+        // Fix this to load the parent folder: http://b/9694899
+//        final Folder parent = current.parent;
+//        if (parent != null) {
+//            onFolderSelected(parent);
+//        }
+    }
+
     @Override
     public void onViewModeChanged(int newMode) {
         if (!mSavedMiscellaneousView && mMiscellaneousViewTransactionId >= 0) {
@@ -228,10 +237,9 @@
         if (isDrawerEnabled()) {
             return;
         }
-        // On two-pane, the back button is only removed in the conversation list mode for top level
-        // folders, and shown for every other condition.
-        if ((mViewMode.isListMode() && (mFolder == null || mFolder.parent == null
-                || mFolder.parent == Uri.EMPTY)) || mViewMode.isWaitingForSync()) {
+        // On two-pane, the back button is only removed in the conversation list mode, and shown
+        // for every other condition.
+        if (mViewMode.isListMode() || mViewMode.isWaitingForSync()) {
             mActionBarView.removeBackButton();
         } else {
             mActionBarView.setBackButton();
@@ -425,10 +433,19 @@
             // folder list has had a chance to initialize.
             final FolderListFragment folderList = getFolderListFragment();
             if (mode == ViewMode.CONVERSATION_LIST && folderList != null
-                    && mFolder.parent != Uri.EMPTY) {
+                    && folderList.showingHierarchy()) {
                 // If the user navigated via the left folders list into a child folder,
                 // back should take the user up to the parent folder's conversation list.
-                navigateUpFolderHierarchy();
+                // TODO: Clean this code up: http://b/9694899
+                final Folder hierarchyFolder = getHierarchyFolder();
+                if (hierarchyFolder.parent != Uri.EMPTY) {
+                    goUpFolderHierarchy(hierarchyFolder);
+                } else  {
+                    // Show inbox; we are at the top of the hierarchy we were
+                    // showing, and it doesn't have a parent, so we must want to
+                    // the basic account folder list.
+                    loadAccountInbox();
+                }
             // Otherwise, if we are in the conversation list but not in the default
             // inbox and not on expansive layouts, we want to switch back to the default
             // inbox. This fixes b/9006969 so that on smaller tablets where we have this