Merge "Revert "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 26960c6..61b7bf2 100644
--- a/src/com/android/mail/ui/AbstractActivityController.java
+++ b/src/com/android/mail/ui/AbstractActivityController.java
@@ -38,6 +38,7 @@
 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;
@@ -156,6 +157,8 @@
     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";
@@ -171,6 +174,7 @@
 
     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;
@@ -827,7 +831,7 @@
     }
 
     @Override
-    public void onFolderChanged(Folder folder) {
+    public void onFolderChanged(Folder folder, final boolean force) {
         /** 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);
@@ -838,7 +842,7 @@
                 ? DrawerLayout.LOCK_MODE_UNLOCKED : DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
 
         mDrawerContainer.closeDrawers();
-        changeFolder(folder, null);
+        changeFolder(folder, null, force);
     }
 
     /**
@@ -861,12 +865,14 @@
      * 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) {
+    private void changeFolder(Folder folder, String query, final boolean force) {
         if (!Objects.equal(mFolder, folder)) {
             commitDestructiveActions(false);
         }
-        if (folder != null && !folder.equals(mFolder)
+        if (folder != null && (!folder.equals(mFolder) || force)
                 || (mViewMode.getMode() != ViewMode.CONVERSATION_LIST)) {
             setListContext(folder, query);
             showConversationList(mConvListContext);
@@ -878,7 +884,7 @@
 
     @Override
     public void onFolderSelected(Folder folder) {
-        onFolderChanged(folder);
+        onFolderChanged(folder, false /* force */);
     }
 
     /**
@@ -911,7 +917,7 @@
         if (mFolderWatcher != null) {
             final Folder inbox = mFolderWatcher.getDefaultInbox(mAccount);
             if (inbox != null) {
-                onFolderChanged(inbox);
+                onFolderChanged(inbox, false /* force */);
                 handled = true;
             }
         }
@@ -2029,6 +2035,8 @@
 
         outState.putParcelable(SAVED_HIERARCHICAL_FOLDER, mFolderListFolder);
         mSafeToModifyFragments = false;
+
+        outState.putParcelable(SAVED_INBOX_KEY, mInbox);
     }
 
     /**
@@ -2244,6 +2252,8 @@
         if (mDialogAction != -1) {
             makeDialogListener(mDialogAction, mDialogFromSelectedSet);
         }
+
+        mInbox = savedState.getParcelable(SAVED_INBOX_KEY);
     }
 
     /**
@@ -3479,7 +3489,7 @@
                 case LOADER_ACCOUNT_INBOX:
                     if (data != null && !data.isClosed() && data.moveToFirst()) {
                         final Folder inbox = data.getModel();
-                        onFolderChanged(inbox);
+                        onFolderChanged(inbox, false /* force */);
                         // 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);
@@ -3511,7 +3521,7 @@
                     final Folder folder = data.getModel();
                     boolean handled = false;
                     if (folder != null) {
-                        onFolderChanged(folder);
+                        onFolderChanged(folder, false /* force */);
                         handled = true;
                     }
                     if (mConversationToShow != null) {
@@ -4242,4 +4252,53 @@
     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 cc9c051..0968fa7 100644
--- a/src/com/android/mail/ui/FolderChangeListener.java
+++ b/src/com/android/mail/ui/FolderChangeListener.java
@@ -26,6 +26,8 @@
      * 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);
+    void onFolderChanged(Folder folder, boolean force);
 }
diff --git a/src/com/android/mail/ui/FolderListFragment.java b/src/com/android/mail/ui/FolderListFragment.java
index 7eee145..ea1dcdc 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();
+        final Bundle args = new Bundle(3);
         if (parentFolder != null) {
             args.putParcelable(ARG_PARENT_FOLDER, parentFolder);
         }
@@ -1077,10 +1077,6 @@
         }
     }
 
-    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.
@@ -1161,14 +1157,6 @@
     }
 
     /**
-     * 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 14a1089..16b74a5 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) {
+    public void onFolderChanged(Folder folder, final boolean force) {
         if (!folder.equals(mSelectedFolder)) {
             mSelectedFolder = folder;
             Intent resultIntent = new Intent();
@@ -350,7 +350,7 @@
             createFolderListFragment(FolderListFragment.ofTree(folder));
             return;
         }
-        onFolderChanged(folder);
+        onFolderChanged(folder, false /* force */);
     }
 
     @Override
diff --git a/src/com/android/mail/ui/OnePaneController.java b/src/com/android/mail/ui/OnePaneController.java
index ffd1a04..8ce5c0c 100644
--- a/src/com/android/mail/ui/OnePaneController.java
+++ b/src/com/android/mail/ui/OnePaneController.java
@@ -20,10 +20,7 @@
 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;
@@ -35,7 +32,6 @@
 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;
 
 /**
@@ -44,9 +40,6 @@
  */
 
 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}. */
@@ -55,15 +48,11 @@
     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;
 
@@ -77,26 +66,20 @@
         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
@@ -175,8 +158,6 @@
     @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("}");
@@ -202,13 +183,13 @@
         if (!inInbox(mAccount, listContext)) {
             // Maintain fragment transaction history so we can get back to the
             // fragment used to launch this list.
-            mLastConversationListTransactionId = replaceFragmentWithBack(conversationListFragment,
+            mLastConversationListTransactionId = replaceFragment(conversationListFragment,
                     transition, TAG_CONVERSATION_LIST, R.id.content_pane);
         } else {
             // If going to the inbox, clear the folder list transaction history.
             mInbox = listContext.folder;
-            mLastInboxConversationListTransactionId = replaceFragmentWithBack(
-                    conversationListFragment, transition, TAG_CONVERSATION_LIST, R.id.content_pane);
+            replaceFragment(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.
@@ -227,7 +208,7 @@
         super.showConversation(conversation, inLoaderCallbacks);
         mConversationListVisible = false;
         if (conversation == null) {
-            transitionBackToConversationListMode(inLoaderCallbacks);
+            transitionBackToConversationListMode();
             return;
         }
         disableCabMode();
@@ -296,30 +277,17 @@
     /**
      * 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}. This action will be placed on the back stack.
+     * {@link android.app.FragmentManager}.
      * @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 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) {
+    private int replaceFragment(Fragment fragment, int transition, String tag, int anchor) {
         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();
@@ -347,9 +315,9 @@
         if (mode == ViewMode.SEARCH_RESULTS_LIST) {
             mActivity.finish();
         } else if (mViewMode.isListMode() && !inInbox(mAccount, mConvListContext)) {
-            transitionToInbox();
+            navigateUpFolderHierarchy();
         } else if (mViewMode.isConversationMode() || mViewMode.isAdMode()) {
-            transitionBackToConversationListMode(false /* inLoaderCallbacks */);
+            transitionBackToConversationListMode();
         } else {
             mActivity.finish();
         }
@@ -357,39 +325,6 @@
         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.
      */
@@ -398,7 +333,7 @@
         if (mInbox == null || !isDefaultInbox(mInbox.folderUri, mAccount)) {
             loadAccountInbox();
         } else {
-            onFolderChanged(mInbox);
+            onFolderChanged(mInbox, false /* force */);
         }
     }
 
@@ -408,10 +343,6 @@
         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,
@@ -434,7 +365,7 @@
                 // Show the drawer.
                 toggleDrawerState();
             } else {
-                navigateUp();
+                navigateUpFolderHierarchy();
             }
         } else if (mode == ViewMode.CONVERSATION || mode == ViewMode.SEARCH_RESULTS_CONVERSATION
                 || mode == ViewMode.AD) {
@@ -444,7 +375,7 @@
         return true;
     }
 
-    private void transitionBackToConversationListMode(boolean inLoaderCallbacks) {
+    private void transitionBackToConversationListMode() {
         final int mode = mViewMode.getMode();
         enableCabMode();
         mConversationListVisible = true;
@@ -453,50 +384,14 @@
         } else {
             mViewMode.enterConversationListMode();
         }
-        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);
-        }
+
+        final Folder folder = mFolder != null ? mFolder : mInbox;
+        onFolderChanged(folder, true /* force */);
+
         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;
@@ -558,34 +453,6 @@
         }
     }
 
-    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
@@ -600,7 +467,7 @@
 
     @Override
     public void launchFragment(final Fragment fragment, final int selectPosition) {
-        replaceFragmentWithBack(fragment, FragmentTransaction.TRANSIT_FRAGMENT_OPEN,
+        replaceFragment(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 ff022e2..0269b56 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) {
-        super.onFolderChanged(folder);
+    public void onFolderChanged(Folder folder, final boolean force) {
+        super.onFolderChanged(folder, force);
         exitCabMode();
     }
 
@@ -171,7 +171,7 @@
             mViewMode.enterConversationListMode();
         }
 
-        if (folder.hasChildren) {
+        if (folder.parent != Uri.EMPTY) {
             // Show the up affordance when digging into child folders.
             mActionBarView.setBackButton();
         }
@@ -179,15 +179,6 @@
         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) {
@@ -237,9 +228,10 @@
         if (isDrawerEnabled()) {
             return;
         }
-        // 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()) {
+        // 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()) {
             mActionBarView.removeBackButton();
         } else {
             mActionBarView.setBackButton();
@@ -433,19 +425,10 @@
             // folder list has had a chance to initialize.
             final FolderListFragment folderList = getFolderListFragment();
             if (mode == ViewMode.CONVERSATION_LIST && folderList != null
-                    && folderList.showingHierarchy()) {
+                    && mFolder.parent != Uri.EMPTY) {
                 // 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.
-                // 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();
-                }
+                navigateUpFolderHierarchy();
             // 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