Merge "Fix NPE accessing fragment arguments"
diff --git a/src/com/android/email/activity/UIControllerBase.java b/src/com/android/email/activity/UIControllerBase.java
index 72f9f0e..05515f0 100644
--- a/src/com/android/email/activity/UIControllerBase.java
+++ b/src/com/android/email/activity/UIControllerBase.java
@@ -48,6 +48,10 @@
     protected static final String BUNDLE_KEY_ACCOUNT_ID = "UIController.state.account_id";
     protected static final String BUNDLE_KEY_MAILBOX_ID = "UIController.state.mailbox_id";
     protected static final String BUNDLE_KEY_MESSAGE_ID = "UIController.state.message_id";
+    protected static final String BUNDLE_KEY_RESUME_INBOX_LOOKUP
+            = "UIController.state.resumeInboxLookup";
+    protected static final String BUNDLE_KEY_INBOX_LOOKUP_ACCOUNT_ID
+            = "UIController.state.inboxLookupAccountId";
 
     /** The owner activity */
     final EmailActivity mActivity;
@@ -63,12 +67,35 @@
      */
     private final ArrayList<Fragment> mRestoredFragments = new ArrayList<Fragment>();
 
+    /** {@code true} if the activity is resumed. */
+    private boolean mResumed;
+
     /**
      * Whether fragment installation should be hold.
      * We hold installing fragments until {@link #installRestoredFragments()} is called.
      */
     private boolean mHoldFragmentInstallation = true;
 
+    /**
+     * Use to find Inbox.  This should only run while the activity is resumed, because otherwise
+     * we may not be able to perform fragment transactions when we get a callback.
+     * See also {@link #mResumeInboxLookup}.
+     */
+    private MailboxFinder mInboxFinder;
+
+    /**
+     * Account ID passed to {@link #startInboxLookup(long)}.  We save it for resuming it in
+     * {@link #onActivityResume()}.
+     */
+    private long mInboxLookupAccountId;
+
+    /**
+     * We (re)start inbox lookup in {@link #onActivityResume} if it's set.
+     * Set in {@link #onActivityPause()} if it's still running, or {@link #startInboxLookup} is
+     * called before the activity is resumed.
+     */
+    private boolean mResumeInboxLookup;
+
     private final RefreshManager.Listener mRefreshListener
             = new RefreshManager.Listener() {
         @Override
@@ -135,6 +162,11 @@
         if (Logging.DEBUG_LIFECYCLE && Email.DEBUG) {
             Log.d(Logging.LOG_TAG, this + " onActivityResume");
         }
+        mResumed = true;
+        if (mResumeInboxLookup) {
+            startInboxLookup(mInboxLookupAccountId);
+            mResumeInboxLookup = false;
+        }
     }
 
     /**
@@ -144,6 +176,8 @@
         if (Logging.DEBUG_LIFECYCLE && Email.DEBUG) {
             Log.d(Logging.LOG_TAG, this + " onActivityPause");
         }
+        mResumeInboxLookup = (mInboxFinder != null);
+        stopInboxLookup();
     }
 
     /**
@@ -153,6 +187,7 @@
         if (Logging.DEBUG_LIFECYCLE && Email.DEBUG) {
             Log.d(Logging.LOG_TAG, this + " onActivityStop");
         }
+        mResumed = false;
     }
 
     /**
@@ -193,6 +228,8 @@
         if (Logging.DEBUG_LIFECYCLE && Email.DEBUG) {
             Log.d(Logging.LOG_TAG, this + " onSaveInstanceState");
         }
+        outState.putBoolean(BUNDLE_KEY_RESUME_INBOX_LOOKUP, mResumeInboxLookup);
+        outState.putLong(BUNDLE_KEY_INBOX_LOOKUP_ACCOUNT_ID, mInboxLookupAccountId);
     }
 
     /**
@@ -202,6 +239,8 @@
         if (Logging.DEBUG_LIFECYCLE && Email.DEBUG) {
             Log.d(Logging.LOG_TAG, this + " restoreInstanceState");
         }
+        mResumeInboxLookup = savedInstanceState.getBoolean(BUNDLE_KEY_RESUME_INBOX_LOOKUP);
+        mInboxLookupAccountId = savedInstanceState.getLong(BUNDLE_KEY_INBOX_LOOKUP_ACCOUNT_ID);
     }
 
     /**
@@ -334,6 +373,69 @@
     public abstract boolean onBackPressed(boolean isSystemBackKey);
 
     /**
+     * Callback called when the inbox lookup (started by {@link #startInboxLookup}) is finished.
+     */
+    protected abstract MailboxFinder.Callback getInboxLookupCallback();
+
+    private final MailboxFinder.Callback mMailboxFinderCallback = new MailboxFinder.Callback() {
+        private void cleanUp() {
+            mInboxFinder = null;
+        }
+
+        @Override
+        public void onAccountNotFound() {
+            getInboxLookupCallback().onAccountNotFound();
+            cleanUp();
+        }
+
+        @Override
+        public void onAccountSecurityHold(long accountId) {
+            getInboxLookupCallback().onAccountSecurityHold(accountId);
+            cleanUp();
+        }
+
+        @Override
+        public void onMailboxFound(long accountId, long mailboxId) {
+            getInboxLookupCallback().onMailboxFound(accountId, mailboxId);
+            cleanUp();
+        }
+
+        @Override
+        public void onMailboxNotFound(long accountId) {
+            getInboxLookupCallback().onMailboxNotFound(accountId);
+            cleanUp();
+        }
+    };
+
+    /**
+     * Start inbox lookup.
+     */
+    protected void startInboxLookup(long accountId) {
+        if (mInboxFinder != null) {
+            return; // already running
+        }
+        mInboxLookupAccountId = accountId;
+        if (!mResumed) {
+            mResumeInboxLookup = true; // Don't start yet.
+            return;
+        }
+        mInboxFinder = new MailboxFinder(mActivity, accountId, Mailbox.TYPE_INBOX,
+                mMailboxFinderCallback);
+        mInboxFinder.startLookup();
+    }
+
+    /**
+     * Stop inbox lookup.
+     */
+    protected void stopInboxLookup() {
+        if (mInboxFinder == null) {
+            return; // not running
+        }
+        mInboxFinder.cancel();
+        mInboxFinder = null;
+    }
+
+    /**
      * Handles the {@link android.app.Activity#onCreateOptionsMenu} callback.
      */
     public boolean onCreateOptionsMenu(MenuInflater inflater, Menu menu) {
diff --git a/src/com/android/email/activity/UIControllerOnePane.java b/src/com/android/email/activity/UIControllerOnePane.java
index d3b575e..3e59b4e 100644
--- a/src/com/android/email/activity/UIControllerOnePane.java
+++ b/src/com/android/email/activity/UIControllerOnePane.java
@@ -18,6 +18,7 @@
 
 import com.android.email.Email;
 import com.android.email.R;
+import com.android.email.activity.MailboxFinder.Callback;
 import com.android.emailcommon.Logging;
 import com.android.emailcommon.provider.EmailContent.Account;
 import com.android.emailcommon.provider.EmailContent.Message;
@@ -326,6 +327,12 @@
         return mCurrentMessageId;
     }
 
+    @Override
+    protected Callback getInboxLookupCallback() {
+        // We don't call startInboxLookup in UIControllerOnePane, so shouldn't be called.
+        throw new RuntimeException("SHOULD NOT BE CALLED"); // STOPSHIP
+    }
+
     private void refreshActionBar() {
         if (mActionBarController != null) {
             mActionBarController.refresh();
diff --git a/src/com/android/email/activity/UIControllerTwoPane.java b/src/com/android/email/activity/UIControllerTwoPane.java
index a7ea8b1..45d1fdf 100644
--- a/src/com/android/email/activity/UIControllerTwoPane.java
+++ b/src/com/android/email/activity/UIControllerTwoPane.java
@@ -21,6 +21,7 @@
 import com.android.email.Preferences;
 import com.android.email.R;
 import com.android.email.RefreshManager;
+import com.android.email.activity.MailboxFinder.Callback;
 import com.android.email.activity.setup.AccountSecurity;
 import com.android.emailcommon.Logging;
 import com.android.emailcommon.provider.EmailContent.Account;
@@ -76,8 +77,6 @@
 
     private MessageCommandButtonView mMessageCommandButtons;
 
-    private MailboxFinder mMailboxFinder;
-
     private MessageOrderManager mOrderManager;
     private final MessageOrderManagerCallback mMessageOrderManagerCallback =
         new MessageOrderManagerCallback();
@@ -517,7 +516,6 @@
     /** {@inheritDoc} */
     @Override
     public void onActivityDestroy() {
-        closeMailboxFinder();
         super.onActivityDestroy();
     }
 
@@ -525,16 +523,17 @@
     @Override
     public void onSaveInstanceState(Bundle outState) {
         super.onSaveInstanceState(outState);
-
-        // STOPSHIP If MailboxFinder is still running, it needs restarting after loadState().
     }
 
     /** {@inheritDoc} */
     @Override
     public void restoreInstanceState(Bundle savedInstanceState) {
         super.restoreInstanceState(savedInstanceState);
+    }
 
-        // STOPSHIP If MailboxFinder is still running, it needs restarting after loadState().
+    @Override
+    protected Callback getInboxLookupCallback() {
+        return this;
     }
 
     @Override
@@ -621,9 +620,7 @@
                 updateMessageList(ft, accountId, Mailbox.QUERY_ALL_INBOXES, true);
             } else {
                 // Try to find the inbox for the account
-                closeMailboxFinder();
-                mMailboxFinder = new MailboxFinder(mActivity, accountId, Mailbox.TYPE_INBOX, this);
-                mMailboxFinder.startLookup();
+                startInboxLookup(accountId);
             }
             mThreePane.showLeftPane();
         } else if (messageId == Message.NO_MESSAGE) {
@@ -718,8 +715,6 @@
      *     {@link Account#NO_ACCOUNT}.
      * @param mailboxId ID of the mailbox to load. Must never be {@link Mailbox#NO_MAILBOX}.
      * @param clearDependentPane if true, the message view will be cleared
-     *
-     * STOPSHIP Need to stop mailbox finder if it's still running
      */
     private void updateMessageList(FragmentTransaction ft,
             long accountId, long mailboxId, boolean clearDependentPane) {
@@ -731,6 +726,8 @@
             throw new IllegalArgumentException();
         }
 
+        stopInboxLookup();
+
         if (mailboxId != getMessageListMailboxId()) {
             uninstallMessageListFragment(ft);
             ft.add(mThreePane.getMiddlePaneId(), MessageListFragment.newInstance(
@@ -794,13 +791,6 @@
         }
     }
 
-    private void closeMailboxFinder() {
-        if (mMailboxFinder != null) {
-            mMailboxFinder.cancel();
-            mMailboxFinder = null;
-        }
-    }
-
     private class CommandButtonCallback implements MessageCommandButtonView.Callback {
         @Override
         public void onMoveToNewer() {