Adding more ActivityController dependencies

ui.ControllableActivity added from Gmail.
One pane layout files brought in.
Minor changes to make everything work with the test activity.

Change-Id: I8cacd5f36394fe4a786590e2e381369a3afb5494
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 6586ef6..d86afe0 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -24,6 +24,8 @@
     <uses-permission android:name="android.permission.READ_CONTACTS"/>
     <!-- Allows access to EmailProvider (EAS/IMAP/POP3) -->
     <uses-permission android:name="com.android.email.permission.ACCESS_PROVIDER"/>
+    <uses-permission android:name="android.permission.NFC" />
+
     <application
         android:icon="@mipmap/ic_launcher_mail"
         android:label="@string/app_name"
@@ -41,7 +43,10 @@
         <activity android:name=".browse.ConversationViewActivity" />
         <activity android:name=".browse.FolderItem" />
         <activity
-           android:name=".browse.ActionbarActivity"
+           android:name=".ui.ActionbarActivity"
+           android:uiOptions="splitActionBarWhenNarrow" />
+        <activity
+           android:name=".ui.MailActivity"
            android:uiOptions="splitActionBarWhenNarrow" />
 
         <provider
diff --git a/res/layout/actionbar_view.xml b/res/layout/actionbar_view.xml
index ffaa03b..332dd6d 100644
--- a/res/layout/actionbar_view.xml
+++ b/res/layout/actionbar_view.xml
@@ -20,7 +20,7 @@
      The custom action bar view Gmail uses (containing drop down account spinner,
     label, and subject).
 -->
-<com.android.mail.MailActionBar xmlns:android="http://schemas.android.com/apk/res/android"
+<com.android.mail.ui.MailActionBar xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:email="http://schemas.android.com/apk/res/com.android.mail"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
@@ -36,4 +36,4 @@
 
     <include layout="@layout/actionbar_subject" />
 
-</com.android.mail.MailActionBar>
+</com.android.mail.ui.MailActionBar>
diff --git a/res/layout/layout_tests.xml b/res/layout/layout_tests.xml
index 4fb8c64..509f87a 100644
--- a/res/layout/layout_tests.xml
+++ b/res/layout/layout_tests.xml
@@ -45,5 +45,10 @@
             android:layout_height="wrap_content"
             android:layout_width="wrap_content"
             android:onClick="actionbarTest"/>
+        <Button
+            android:text="@string/test_application"
+            android:layout_height="wrap_content"
+            android:layout_width="wrap_content"
+            android:onClick="unifiedMail"/>
     </LinearLayout>
 </ScrollView>
diff --git a/res/layout/one_pane_activity.xml b/res/layout/one_pane_activity.xml
new file mode 100644
index 0000000..0d80aef
--- /dev/null
+++ b/res/layout/one_pane_activity.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <FrameLayout
+        android:id="@+id/content_pane"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"/>
+
+</RelativeLayout>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index d826869..e098ac8 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -26,6 +26,7 @@
     <string name="account_cache_provider">Account Cache Provider</string>
     <string name="dummy_gmail_provider">Dummy Gmail Provider</string>
     <string name="test_actionbar" translate="false">Test Actionbar Layout</string>
+    <string name="test_application" translate="false">Test Application</string>
 
     <string name="app_name">Unified Email</string>
 
diff --git a/src/com/android/mail/ConversationListContext.java b/src/com/android/mail/ConversationListContext.java
index 550a20f..920a868 100644
--- a/src/com/android/mail/ConversationListContext.java
+++ b/src/com/android/mail/ConversationListContext.java
@@ -17,6 +17,15 @@
 
 package com.android.mail;
 
+import android.content.Context;
+import android.content.Intent;
+import android.content.UriMatcher;
+import android.os.Bundle;
+import com.android.mail.providers.Account;
+import com.android.mail.providers.UIProvider;
+
+import java.util.ArrayList;
+
 /**
  * This class is supposed to have the same thing that the Gmail ConversationListContext
  * contained. For now, it has no implementation at all. The goal is to bring over functionality
@@ -24,9 +33,104 @@
  *
  * Original purpose:
  * An encapsulation over a request to a list of conversations and the various states around it.
- * This includes the label the user selected to view the list, or the search query for the
+ * This includes the folder the user selected to view the list, or the search query for the
  * list, etc.
  */
 public class ConversationListContext {
+    private static final String EXTRA_ACCOUNT = "account";
+    private static final String EXTRA_FOLDER = "folder";
+    private static final String EXTRA_SEARCH_QUERY = "query";
 
+    /**
+     * A matcher for data URI's that specify conversation list info.
+     */
+    private static final UriMatcher sUrlMatcher = new UriMatcher(UriMatcher.NO_MATCH);
+    /**
+     * The account for whom we are showing a list
+     */
+    private final Account mAccount;
+    /**
+     * The folder whose conversations we are displaying, if any.
+     */
+    private final String mFolderName;
+
+    /**
+     * The search query whose results we are displaying, if any.
+     */
+    private final String mSearchQuery;
+
+    // Tokenized search terms for search queries.
+    private ArrayList<String> mSearchTerms;
+
+    static {
+        // Get the real authority here.
+        // TODO(viki): Get the real authority, and the real URI matcher!!!
+        sUrlMatcher.addURI(UIProvider.AUTHORITY, "account/*/folder/*", 0);
+    }
+
+    /**
+     * De-serializes a context from a bundle.
+     */
+    public static ConversationListContext forBundle(Bundle bundle) {
+        // The account is created here as a new object. This is probably not the best thing to do.
+        // We should probably be reading an account instance from our controller.
+        Account account = bundle.getParcelable(EXTRA_ACCOUNT);
+        return new ConversationListContext(
+                account,
+                bundle.getString(EXTRA_SEARCH_QUERY),
+                bundle.getString(EXTRA_FOLDER));
+    }
+
+    /**
+     * Resolves an intent and builds an appropriate context for it.
+     */
+    public static ConversationListContext forIntent
+            (Context context, Account callerAccount, Intent intent) {
+        Account account = callerAccount;
+        String folder = null;
+        String action = intent.getAction();
+        // TODO(viki): Implement the other intents: Intent.SEARCH, Intent.PROVIDER_CHANGED.
+        if (Intent.ACTION_VIEW.equals(action) && intent.getData() != null) {
+            // TODO(viki): Look through the URI to find the account and the folder.
+        }
+        if (folder == null) {
+            folder = intent.getStringExtra(EXTRA_FOLDER);
+        }
+        return forFolder(context, account, folder);
+    }
+
+    /**
+     * Builds a context for a view to a Gmail folder. Note that folder may be null, in which case
+     * the context defaults to a view of the inbox.
+     */
+    private static ConversationListContext forFolder(
+            Context context, Account account, String folder) {
+        // Mock stuff for now.
+        return new ConversationListContext(account, null, folder);
+    }
+
+    /**
+     * Internal constructor
+     *
+     * To create a class, use the static {@link #forIntent} or {@link #forBundle(Bundle)} method.
+     * @param account
+     * @param searchQuery
+     * @param folder
+     */
+    private ConversationListContext(Account account, String searchQuery, String folder) {
+        mAccount = account;
+        mSearchQuery = searchQuery;
+        mFolderName = folder;
+    }
+
+    /**
+     * Serializes the context to a bundle.
+     */
+    public Bundle toBundle() {
+        Bundle result = new Bundle();
+        result.putParcelable(EXTRA_ACCOUNT, mAccount);
+        result.putString(EXTRA_SEARCH_QUERY, mSearchQuery);
+        result.putString(EXTRA_FOLDER, mFolderName);
+        return result;
+    }
 }
diff --git a/src/com/android/mail/UnifiedEmail.java b/src/com/android/mail/UnifiedEmail.java
index 5c0c8e0..e25155e 100644
--- a/src/com/android/mail/UnifiedEmail.java
+++ b/src/com/android/mail/UnifiedEmail.java
@@ -18,9 +18,10 @@
 package com.android.mail;
 
 import com.android.mail.browse.ConversationListActivity;
-import com.android.mail.browse.ActionbarActivity;
 import com.android.mail.browse.FolderItem;
 import com.android.mail.compose.ComposeActivity;
+import com.android.mail.ui.ActionbarActivity;
+import com.android.mail.ui.MailActivity;
 
 import android.app.Activity;
 import android.content.ComponentName;
@@ -56,4 +57,12 @@
     public void actionbarTest(View v){
         startActivityWithClass(ActionbarActivity.class);
     }
+
+    /**
+     * Try out the real mail activity now.
+     * @param v
+     */
+    public void unifiedMail(View v){
+        startActivityWithClass(MailActivity.class);
+    }
 }
diff --git a/src/com/android/mail/browse/ConversationItemView.java b/src/com/android/mail/browse/ConversationItemView.java
index 8938ec2..537d154 100644
--- a/src/com/android/mail/browse/ConversationItemView.java
+++ b/src/com/android/mail/browse/ConversationItemView.java
@@ -47,12 +47,13 @@
 import android.view.View;
 
 import com.android.mail.R;
-import com.android.mail.ViewMode;
 import com.android.mail.browse.ConversationItemViewModel.SenderFragment;
 import com.android.mail.perf.Timer;
 import com.android.mail.providers.Address;
 import com.android.mail.providers.Conversation;
 import com.android.mail.providers.UIProvider.ConversationColumns;
+import com.android.mail.ui.ConversationSelectionSet;
+import com.android.mail.ui.ViewMode;
 import com.android.mail.utils.Utils;
 
 public class ConversationItemView extends View {
diff --git a/src/com/android/mail/browse/ConversationItemViewCoordinates.java b/src/com/android/mail/browse/ConversationItemViewCoordinates.java
index c411d46..8f77354 100644
--- a/src/com/android/mail/browse/ConversationItemViewCoordinates.java
+++ b/src/com/android/mail/browse/ConversationItemViewCoordinates.java
@@ -27,7 +27,7 @@
 import android.view.ViewParent;
 import android.widget.TextView;
 import com.android.mail.R;
-import com.android.mail.ViewMode;
+import com.android.mail.ui.ViewMode;
 
 /**
  * Represents the coordinates of elements inside a CanvasConversationHeaderView
diff --git a/src/com/android/mail/browse/ConversationListActivity.java b/src/com/android/mail/browse/ConversationListActivity.java
index 08b899a..85fcb51 100644
--- a/src/com/android/mail/browse/ConversationListActivity.java
+++ b/src/com/android/mail/browse/ConversationListActivity.java
@@ -41,14 +41,15 @@
 import android.widget.AdapterView.OnItemSelectedListener;
 
 import com.android.mail.R;
-import com.android.mail.ViewMode;
+import com.android.mail.browse.ConversationCursor.ConversationListener;
 import com.android.mail.compose.ComposeActivity;
 import com.android.mail.providers.Account;
 import com.android.mail.providers.AccountCacheProvider;
 import com.android.mail.providers.Conversation;
 import com.android.mail.providers.UIProvider;
-import com.android.mail.browse.ConversationCursor.ConversationListener;
-import com.android.mail.browse.ConversationSelectionSet.ConversationSetObserver;
+import com.android.mail.ui.ConversationSelectionSet;
+import com.android.mail.ui.ConversationSetObserver;
+import com.android.mail.ui.ViewMode;
 
 import java.util.ArrayList;
 
@@ -203,12 +204,12 @@
     }
 
     @Override
-    public void onSetEmpty(ConversationSelectionSet set) {
+    public void onSetEmpty() {
         mSelectedConversationsActionMenu = null;
     }
 
     @Override
-    public void onSetBecomeUnempty(ConversationSelectionSet set) {
+    public void onSetPopulated(ConversationSelectionSet set) {
         mSelectedConversationsActionMenu = new SelectedConversationsActionMenu(this,
                 mBatchConversations);
         mSelectedConversationsActionMenu.activate();
diff --git a/src/com/android/mail/browse/ConversationSelectionSet.java b/src/com/android/mail/browse/ConversationSelectionSet.java
deleted file mode 100644
index 413f17d..0000000
--- a/src/com/android/mail/browse/ConversationSelectionSet.java
+++ /dev/null
@@ -1,311 +0,0 @@
-/*
- * Copyright (C) 2012 Google Inc.
- * Licensed to The Android Open Source Project.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.mail.browse;
-
-import com.android.mail.providers.Conversation;
-import com.android.mail.providers.UIProvider;
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.Lists;
-
-import android.database.Cursor;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-
-
-/**
- * A simple thread-safe wrapper over a set of conversations representing a selection set (e.g.
- * in a conversation list). This class dispatches changes when the set goes empty, and when it
- * becomes unempty.
- *
- * For simplicity, this class <b>does not allow modifications</b> to the collection in observers
- * when responding to change events.
- *
- * In the Unified codebase, this is called ui.ConversationSelectionSet
- */
-public class ConversationSelectionSet implements Parcelable {
-    private final HashMap<Long, Conversation> mInternalMap =
-            new HashMap<Long, Conversation>();
-
-    /**
-     * Whether or not change notifications should be suppressed. This is used for batch updates.
-     */
-    private boolean mLockedForChanges = false;
-
-    @VisibleForTesting
-    final ArrayList<ConversationSetObserver> mObservers = new ArrayList<ConversationSetObserver>();
-
-    /**
-     * Observers which can register on changes on this set.
-     * Observers are required to ensure that no modification is done to the set when handling
-     * events.
-     *
-     * In the Unified codebase, this is a separate interface in ui.ConversationSetObserver
-     */
-    public interface ConversationSetObserver {
-        /**
-         * Handle when the selection set becomes empty. The observer should not make any
-         * modifications to the set while handling this event.
-         */
-        void onSetEmpty(ConversationSelectionSet set);
-
-        /**
-         * Handle when the selection set becomes unempty. The observer should not make any
-         * modifications to the set while handling this event.
-         */
-        void onSetBecomeUnempty(ConversationSelectionSet set);
-
-        /**
-         * Handle when the selection set gets an element added or removed. The observer should not
-         * make any modifications to the set while handling this event.
-         *
-         * The set makes no guarantees that this method will get dispatched for each addition or
-         * removal for batch operations such as {@link #clear}, but will guarantee that it will
-         * get called at least once.
-         */
-        void onSetChanged(ConversationSelectionSet set);
-    }
-
-    /**
-     * Registers an observer to listen for interesting changes on this set.
-     * @param observer the observer to register.
-     */
-    public synchronized void addObserver(ConversationSetObserver observer) {
-        mObservers.add(observer);
-    }
-
-    /**
-     * Unregisters an observer for change events.
-     * @param observer the observer to unregister.
-     */
-    public synchronized void removeObserver(ConversationSetObserver observer) {
-        mObservers.remove(observer);
-    }
-
-    private synchronized void dispatchOnChange(ArrayList<ConversationSetObserver> observers) {
-        // Copy observers so that they may unregister themselves as listeners on event handling.
-        for (ConversationSetObserver observer : observers) {
-            observer.onSetChanged(this);
-        }
-    }
-
-    private synchronized void dispatchOnEmpty(ArrayList<ConversationSetObserver> observers) {
-        for (ConversationSetObserver observer : observers) {
-            observer.onSetEmpty(this);
-        }
-    }
-
-    private synchronized void dispatchOnBecomeUnempty(
-            ArrayList<ConversationSetObserver> observers) {
-        for (ConversationSetObserver observer : observers) {
-            observer.onSetBecomeUnempty(this);
-        }
-    }
-
-    /** @see java.util.HashMap#get */
-    public synchronized Conversation get(Long id) {
-        return mInternalMap.get(id);
-    }
-
-    /** @see java.util.HashMap#put */
-    public synchronized void put(Long id, Conversation info) {
-        boolean initiallyEmpty =  mInternalMap.isEmpty();
-        mInternalMap.put(id, info);
-
-        if (mLockedForChanges) {
-            return;
-        }
-
-        ArrayList<ConversationSetObserver> observersCopy = Lists.newArrayList(mObservers);
-        dispatchOnChange(observersCopy);
-        if (initiallyEmpty) {
-            dispatchOnBecomeUnempty(observersCopy);
-        }
-    }
-
-    /** @see java.util.HashMap#remove */
-    public synchronized void remove(Long id) {
-        boolean initiallyNotEmpty = !mInternalMap.isEmpty();
-        mInternalMap.remove(id);
-
-        if (mLockedForChanges) {
-            return;
-        }
-
-        ArrayList<ConversationSetObserver> observersCopy = Lists.newArrayList(mObservers);
-        dispatchOnChange(observersCopy);
-        if (mInternalMap.isEmpty() && initiallyNotEmpty) {
-            dispatchOnEmpty(observersCopy);
-        }
-    }
-
-    /** @see java.util.HashMap#isEmpty */
-    public synchronized boolean isEmpty() {
-        return mInternalMap.isEmpty();
-    }
-
-    /** @see java.util.HashMap#size */
-    public synchronized int size() {
-        return mInternalMap.size();
-    }
-
-    /** @see java.util.HashMap#keySet */
-    public synchronized Collection<Long> keySet() {
-        return mInternalMap.keySet();
-    }
-
-    /** @see java.util.HashMap#values */
-    public synchronized Collection<Conversation> values() {
-        return mInternalMap.values();
-    }
-
-    /** @see java.util.HashMap#containsKey */
-    public synchronized boolean containsKey(Long key) {
-        return mInternalMap.containsKey(key);
-    }
-
-    /** @see java.util.HashMap#clear */
-    public synchronized void clear() {
-        boolean initiallyNotEmpty = !mInternalMap.isEmpty();
-        mInternalMap.clear();
-
-        if (mLockedForChanges) {
-            return;
-        }
-
-        if (mInternalMap.isEmpty() && initiallyNotEmpty) {
-            ArrayList<ConversationSetObserver> observersCopy = Lists.newArrayList(mObservers);
-            dispatchOnChange(observersCopy);
-            dispatchOnEmpty(observersCopy);
-        }
-    }
-
-    /**
-     * Iterates through a cursor of conversations and ensures that the current set is present
-     * within the result set denoted by the cursor. Any conversations not foun in the result set
-     * is removed from the collection.
-     */
-    public synchronized void validateAgainstCursor(Cursor cursor) {
-        if (isEmpty()) {
-            return;
-        }
-
-        if (cursor == null) {
-            clear();
-            return;
-        }
-
-        // Get the current position of the cursor, so it can be reset
-        int currentPosition = cursor.getPosition();
-        if (currentPosition != -1) {
-            // Validate batch selection across all conversations, not just the most
-            // recently loaded set.  See bug 2405138 (Batch selection cleared when
-            // additional conversations are loaded on demand).
-            cursor.moveToPosition(-1);
-        }
-
-        // The query has run, but we have been in the list
-        // Make sure that the list of selected conversations
-        // contains only items that are in the result set
-        ArrayList<Long> selectedConversationsToToggle = new ArrayList<Long>(keySet());
-
-        // Go through the list of what we think is selected,
-        // if any of the conversations are not present,
-        // untoggle them from the list
-        //
-        // Only continue going through the list while we are unsure
-        // if a conversation is selected.  If we don't stop when
-        // there are no more items in the selectedConversationsToToggle
-        // collection, this will force the whole collection list to be loaded
-        // If we believe that there is at least one conversation selected,
-        // we need to keep looking to make sure that the conversation is still
-        // present
-        while (!selectedConversationsToToggle.isEmpty() && cursor.moveToNext()) {
-            selectedConversationsToToggle.remove(cursor.getLong(UIProvider.CONVERSATION_ID_COLUMN));
-        }
-
-        boolean changed = false;
-
-        // Now toggle the conversations that are incorrectly still selected
-        mLockedForChanges = true;
-        for (long conversationId : selectedConversationsToToggle) {
-            // deselectConversation doesn't update the view, which is OK here, as
-            // the view, if visible, will be removed
-            remove(conversationId);
-            changed = true;
-        }
-        mLockedForChanges = false;
-
-        ArrayList<ConversationSetObserver> observersCopy = Lists.newArrayList(mObservers);
-        if (changed) {
-            dispatchOnChange(observersCopy);
-        }
-
-        if (isEmpty()) {
-            dispatchOnEmpty(observersCopy);
-        }
-
-        cursor.moveToPosition(currentPosition);
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        Conversation[] values = values().toArray(new Conversation[size()]);
-        dest.writeParcelableArray(values, flags);
-    }
-
-    public static final Parcelable.Creator<ConversationSelectionSet> CREATOR =
-            new Parcelable.Creator<ConversationSelectionSet>() {
-
-        @Override
-        public ConversationSelectionSet createFromParcel(Parcel source) {
-            ConversationSelectionSet result = new ConversationSelectionSet();
-            Parcelable[] conversations = source.readParcelableArray(
-                    Conversation.class.getClassLoader());
-            for (Parcelable parceled : conversations) {
-                Conversation conversation = (Conversation) parceled;
-                result.put(conversation.id, conversation);
-            }
-            return result;
-        }
-
-        @Override
-        public ConversationSelectionSet[] newArray(int size) {
-            return new ConversationSelectionSet[size];
-        }
-    };
-
-    /**
-     * Toggles the given conversation in the selection set.
-     */
-    public synchronized void toggle(Conversation conversation) {
-        long conversationId = conversation.id;
-        if (containsKey(conversationId)) {
-            remove(conversationId);
-        } else {
-            put(conversationId, conversation);
-        }
-    }
-}
diff --git a/src/com/android/mail/browse/SelectedConversationsActionMenu.java b/src/com/android/mail/browse/SelectedConversationsActionMenu.java
index ca0b492..4be1b00 100644
--- a/src/com/android/mail/browse/SelectedConversationsActionMenu.java
+++ b/src/com/android/mail/browse/SelectedConversationsActionMenu.java
@@ -18,8 +18,9 @@
 package com.android.mail.browse;
 
 import com.android.mail.R;
-import com.android.mail.browse.ConversationSelectionSet.ConversationSetObserver;
 import com.android.mail.providers.Conversation;
+import com.android.mail.ui.ConversationSelectionSet;
+import com.android.mail.ui.ConversationSetObserver;
 import com.android.mail.utils.LogUtils;
 import com.google.common.annotations.VisibleForTesting;
 
@@ -124,12 +125,12 @@
     }
 
     @Override
-    public void onSetBecomeUnempty(ConversationSelectionSet set) {
+    public void onSetPopulated(ConversationSelectionSet set) {
         // Noop. This object can only exist while the set is non-empty.
     }
 
     @Override
-    public void onSetEmpty(ConversationSelectionSet set) {
+    public void onSetEmpty() {
         destroy();
     }
 
@@ -185,7 +186,6 @@
      */
     public void destroy() {
         deactivate();
-
         mSelectionSet.removeObserver(this);
         mSelectionSet.clear();
     }
diff --git a/src/com/android/mail/compose/AttachmentsView.java b/src/com/android/mail/compose/AttachmentsView.java
index 54b4c7f..2b9098f 100644
--- a/src/com/android/mail/compose/AttachmentsView.java
+++ b/src/com/android/mail/compose/AttachmentsView.java
@@ -81,6 +81,7 @@
             new AttachmentComposeView(getContext(), attachment);
 
         attachmentView.addDeleteListener(new OnClickListener() {
+            @Override
             public void onClick(View v) {
                 deleteAttachment(attachmentView, attachment);
             }
diff --git a/src/com/android/mail/providers/Account.java b/src/com/android/mail/providers/Account.java
index c7b635e..8a54d13 100644
--- a/src/com/android/mail/providers/Account.java
+++ b/src/com/android/mail/providers/Account.java
@@ -18,9 +18,10 @@
 
 import android.database.Cursor;
 import android.os.Parcel;
+import android.os.Parcelable;
 
 
-public class Account extends android.accounts.Account {
+public class Account extends android.accounts.Account implements Parcelable {
     /**
      * The version of the UI provider schema from which this account provider
      * will return results.
diff --git a/src/com/android/mail/ui/AbstractActivityController.java b/src/com/android/mail/ui/AbstractActivityController.java
index c411a6f..ebccce2 100644
--- a/src/com/android/mail/ui/AbstractActivityController.java
+++ b/src/com/android/mail/ui/AbstractActivityController.java
@@ -17,18 +17,26 @@
 
 package com.android.mail.ui;
 
+
+import android.app.ActionBar;
 import android.app.Activity;
 import android.app.Dialog;
+import android.app.ActionBar.LayoutParams;
 import android.content.Context;
 import android.content.Intent;
 import android.os.Bundle;
+import android.os.Parcelable;
 import android.view.ActionMode;
 import android.view.KeyEvent;
+import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.MotionEvent;
+import android.widget.LinearLayout;
 
-import com.android.mail.ViewMode;
+import com.android.mail.ConversationListContext;
+import com.android.mail.R;
+import com.android.mail.providers.Account;
 import com.android.mail.providers.Folder;
 
 /**
@@ -45,9 +53,18 @@
  * In the Gmail codebase, this was called BaseActivityController</p>
  */
 public abstract class AbstractActivityController implements ActivityController {
-    protected final MailActivity mActivity;
-    protected final ViewMode mViewMode;
+    private static final String SAVED_CONVERSATION = "saved-conversation";
+    private static final String SAVED_CONVERSATION_POSITION = "saved-conv-pos";
+    private static final String SAVED_CONVERSATIONS = "saved-conversations";
+    // Keys for serialization of various information in Bundles.
+    private static final String SAVED_LIST_CONTEXT = "saved-list-context";
+    private Account mAccount;
+    private ActionBarView mActionBarView;
+
+    protected final RestrictedActivity mActivity;
+    private ConversationSelectionSet mBatchConversations = new ConversationSelectionSet();
     protected final Context mContext;
+    protected final ViewMode mViewMode;
 
     public AbstractActivityController(MailActivity activity, ViewMode viewMode) {
         mActivity = activity;
@@ -56,10 +73,147 @@
     }
 
     @Override
+    public void clearSubject() {
+        // TODO(viki): Auto-generated method stub
+
+    }
+
+    @Override
+    public void dispatchTouchEvent(MotionEvent ev) {
+        // TODO(viki): Auto-generated method stub
+
+    }
+
+    @Override
+    public void doneChangingFolders(FolderOperations folderOperations) {
+        // TODO(viki): Auto-generated method stub
+
+    }
+
+    @Override
+    public void enterSearchMode() {
+        // TODO(viki): Auto-generated method stub
+
+    }
+
+    @Override
+    public void exitSearchMode() {
+        // TODO(viki): Auto-generated method stub
+
+    }
+
+    @Override
+    public ConversationSelectionSet getBatchConversations() {
+        // TODO(viki): Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public String getCurrentAccount() {
+        // TODO(viki): Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public ConversationListContext getCurrentListContext() {
+        // TODO(viki): Auto-generated method stub
+        return null;
+    }
+
+    @Override
     public String getHelpContext() {
         return "Mail";
     }
 
+    @Override
+    public String getUnshownSubject(String subject) {
+        // Calculate how much of the subject is shown, and return the remaining.
+        return null;
+    }
+
+    @Override
+    public void handleConversationLoadError() {
+        // TODO(viki): Auto-generated method stub
+
+    }
+
+    @Override
+    public void handleSearchRequested() {
+        // TODO(viki): Auto-generated method stub
+
+    }
+
+    /**
+     * Initialize the action bar. This is not visible to OnePaneController and TwoPaneController so
+     * they cannot override this behavior.
+     */
+    private void initCustomActionBarView() {
+        ActionBar actionBar = mActivity.getActionBar();
+        mActionBarView = (MailActionBar) LayoutInflater.from(mContext).inflate(
+                R.layout.actionbar_view, null);
+
+        if (actionBar != null && mActionBarView != null) {
+            // Why have a different variable for the same thing? We should apply the same actions
+            // on mActionBarView instead.
+            // mSubjectDisplayer = (ConversationSubjectDisplayer) mActionBarView;
+            mActionBarView.initialize(mActivity, this, mViewMode, actionBar);
+            actionBar.setCustomView((LinearLayout) mActionBarView, new ActionBar.LayoutParams(
+                    LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
+            actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM,
+                    ActionBar.DISPLAY_SHOW_CUSTOM
+                            | ActionBar.DISPLAY_SHOW_TITLE);
+        }
+    }
+
+    /**
+     * Returns whether the conversation list fragment is visible or not. Different layouts will have
+     * their own notion on the visibility of fragments, so this method needs to be overriden.
+     * @return
+     */
+    protected abstract boolean isConversationListVisible();
+
+    @Override
+    public boolean navigateToAccount(String account) {
+        // TODO(viki): Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public void navigateToFolder(String folderCanonicalName) {
+        // TODO(viki): Auto-generated method stub
+
+    }
+
+    @Override
+    public void onActionModeFinished(ActionMode mode) {
+        // TODO(viki): Auto-generated method stub
+
+    }
+
+    @Override
+    public void onActionModeStarted(ActionMode mode) {
+        // TODO(viki): Auto-generated method stub
+
+    }
+
+    @Override
+    public void onActivityResult(int requestCode, int resultCode, Intent data) {
+        // TODO(viki): Auto-generated method stub
+
+    }
+
+    @Override
+    public boolean onBackPressed() {
+        // TODO(viki): Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public void onConversationListVisibilityChanged(boolean visible) {
+        // TODO(viki): Auto-generated method stub
+
+    }
+
     /**
      * By default, doing nothing is right. A two-pane controller will need to
      * override this.
@@ -71,71 +225,13 @@
     }
 
     @Override
-    public void onLabelChanged(Folder label, long conversationId, boolean added) {
-        // TODO(viki): Auto-generated method stub
-
-    }
-
-    @Override
-    public void doneChangingLabels(FolderOperations labelOperations) {
-        // TODO(viki): Auto-generated method stub
-
-    }
-
-    @Override
-    public void handleSearchRequested() {
-        // TODO(viki): Auto-generated method stub
-
-    }
-
-    @Override
-    public void onStartBulkOperation() {
-        // TODO(viki): Auto-generated method stub
-
-    }
-
-    @Override
-    public void onEndBulkOperation() {
-        // TODO(viki): Auto-generated method stub
-
-    }
-
-    @Override
-    public void onStartDragMode() {
-        // TODO(viki): Auto-generated method stub
-
-    }
-
-    @Override
-    public void onStopDragMode() {
-        // TODO(viki): Auto-generated method stub
-
-    }
-
-    @Override
-    public void setSubject(String subject) {
-        // Do something useful with the subject. This requires changing the
-        // conversation view's
-        // subject text.
-    }
-
-    @Override
-    public String getUnshownSubject(String subject) {
-        // Calculate how much of the subject is shown, and return the remaining.
-        return null;
-    }
-
-    @Override
-    public void onConversationListVisibilityChanged(boolean visible) {
-        // TODO(viki): Auto-generated method stub
-
-    }
-
-    @Override
     public void onCreate(Bundle savedState) {
         // Initialize the action bar view.
+        initCustomActionBarView();
 
         final Intent intent = mActivity.getIntent();
+        // TODO(viki) Choose an account here.
+
         // Allow shortcut keys to function for the ActionBar and menus.
         mActivity.setDefaultKeyMode(Activity.DEFAULT_KEYS_SHORTCUT);
         final Context context = mActivity.getApplicationContext();
@@ -144,48 +240,10 @@
         restoreState(savedState);
     }
 
-    /**
-     * Restore the state from the previous bundle.
-     * @param savedState
-     */
-    protected void restoreState(Bundle savedState) {
-        // Do nothing here.
-    }
-
     @Override
-    public void onSetEmpty(ConversationSelectionSet set) {
+    public Dialog onCreateDialog(int id, Bundle bundle) {
         // TODO(viki): Auto-generated method stub
-
-    }
-
-    @Override
-    public void onSetPopulated(ConversationSelectionSet set) {
-        // TODO(viki): Auto-generated method stub
-
-    }
-
-    @Override
-    public void onSetChanged(ConversationSelectionSet set) {
-        // TODO(viki): Auto-generated method stub
-
-    }
-
-    @Override
-    public void onResume() {
-        // TODO(viki): Auto-generated method stub
-
-    }
-
-    @Override
-    public void onPause() {
-        // TODO(viki): Auto-generated method stub
-
-    }
-
-    @Override
-    public void onStop() {
-        // TODO(viki): Auto-generated method stub
-
+        return null;
     }
 
     @Override
@@ -195,31 +253,31 @@
     }
 
     @Override
-    public boolean onPrepareOptionsMenu(Menu menu) {
+    public void onEndBulkOperation() {
+        // TODO(viki): Auto-generated method stub
+
+    }
+
+    @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
         // TODO(viki): Auto-generated method stub
         return false;
     }
 
     @Override
+    public void onFolderChanged(Folder folder, long conversationId, boolean added) {
+        // TODO(viki): Auto-generated method stub
+
+    }
+
+    @Override
     public boolean onOptionsItemSelected(MenuItem item) {
         // TODO(viki): Auto-generated method stub
         return false;
     }
 
     @Override
-    public void onWindowFocusChanged(boolean hasFocus) {
-        // TODO(viki): Auto-generated method stub
-
-    }
-
-    @Override
-    public boolean onBackPressed() {
-        // TODO(viki): Auto-generated method stub
-        return false;
-    }
-
-    @Override
-    public void onSaveInstanceState(Bundle outState) {
+    public void onPause() {
         // TODO(viki): Auto-generated method stub
 
     }
@@ -231,67 +289,159 @@
     }
 
     @Override
-    public void onActionModeStarted(ActionMode mode) {
-        // TODO(viki): Auto-generated method stub
-
-    }
-
-    @Override
-    public void onActionModeFinished(ActionMode mode) {
-        // TODO(viki): Auto-generated method stub
-
-    }
-
-    @Override
-    public void onActivityResult(int requestCode, int resultCode, Intent data) {
-        // TODO(viki): Auto-generated method stub
-
-    }
-
-    @Override
-    public ConversationSelectionSet getBatchConversations() {
-        // TODO(viki): Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public void handleConversationLoadError() {
-        // TODO(viki): Auto-generated method stub
-
-    }
-
-    @Override
-    public void dispatchTouchEvent(MotionEvent ev) {
-        // TODO(viki): Auto-generated method stub
-
-    }
-
-    @Override
-    public Dialog onCreateDialog(int id, Bundle bundle) {
-        // TODO(viki): Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public boolean onKeyDown(int keyCode, KeyEvent event) {
+    public boolean onPrepareOptionsMenu(Menu menu) {
         // TODO(viki): Auto-generated method stub
         return false;
     }
 
     @Override
+    public void onResume() {
+        // TODO(viki): Auto-generated method stub
+        mBatchConversations.addObserver(this);
+        if (mActionBarView != null) {
+            mActionBarView.onResume();
+        }
+    }
+
+    @Override
+    public void onSaveInstanceState(Bundle outState) {
+        // TODO(viki): Auto-generated method stub
+
+    }
+
+    @Override
     public void onSearchRequested() {
         // TODO(viki): Auto-generated method stub
 
     }
 
     @Override
+    public void onSetChanged(ConversationSelectionSet set) {
+        // We don't care about changes to the set. Ignore.
+    }
+
+    @Override
+    public void onSetEmpty() {
+    }
+
+    @Override
+    public void onSetPopulated(ConversationSelectionSet set) {
+        // TODO(viki): Auto-generated method stub
+
+    }
+
+    @Override
+    public void onStartBulkOperation() {
+        // TODO(viki): Auto-generated method stub
+
+    }
+
+    @Override
+    public void onStartDragMode() {
+        // TODO(viki): Auto-generated method stub
+
+    }
+
+    @Override
+    public void onStop() {
+        // TODO(viki): Auto-generated method stub
+
+    }
+
+    @Override
+    public void onStopDragMode() {
+        // TODO(viki): Auto-generated method stub
+
+    }
+
+    @Override
     public void onViewModeChanged(ViewMode mode) {
         // TODO(viki): Auto-generated method stub
 
     }
 
     @Override
-    public void clearSubject() {
+    public void onWindowFocusChanged(boolean hasFocus) {
+        // TODO(viki): Auto-generated method stub
+
+    }
+
+    @Override
+    public void reloadSearch(String string) {
+        // TODO(viki): Auto-generated method stub
+
+    }
+
+    /**
+     * @param savedState
+     */
+    protected void restoreListContext(Bundle savedState) {
+        // TODO(viki): Auto-generated method stub
+
+    }
+
+    /**
+     * Restore the state of selected conversations. This needs to be done after the correct mode
+     * is set and the action bar is fully initialized. If not, several key pieces of state
+     * information will be missing, and the split views may not be initialized correctly.
+     * @param savedState
+     */
+    private void restoreSelectedConversations(Bundle savedState) {
+        if (savedState != null){
+            // Restore the view mode? This looks wrong.
+            mBatchConversations = savedState.getParcelable(SAVED_CONVERSATIONS);
+            if (mBatchConversations.isEmpty()) {
+                onSetPopulated(mBatchConversations);
+                onConversationVisibilityChanged(isConversationListVisible());
+            } else {
+                onSetEmpty();
+            }
+        } else {
+            onSetEmpty();
+        }
+    }
+
+    /**
+     * Restore the state from the previous bundle. Subclasses should call this method from the
+     * parent class, since it performs important UI initialization.
+     * @param savedState
+     */
+    protected void restoreState(Bundle savedState) {
+        if (savedState != null) {
+            restoreListContext(savedState);
+            // Attach the menu handler here.
+        } else {
+            final Intent intent = mActivity.getIntent();
+            //  TODO(viki): Show the list context from Intent
+            // showConversationList(ConversationListContext.forIntent(mContext, mAccount, intent));
+        }
+
+        // Set the correct mode based on the current context
+
+        // And restore the state of selected conversations
+        restoreSelectedConversations(savedState);
+    }
+
+    @Override
+    public void setSubject(String subject) {
+        // Do something useful with the subject. This requires changing the
+        // conversation view's subject text.
+    }
+
+    @Override
+    public void showFolderList() {
+        // TODO(viki): Auto-generated method stub
+
+    }
+
+    @Override
+    public void startActionBarStatusCursorLoader(String account) {
+        // TODO(viki): Auto-generated method stub
+
+    }
+
+    @Override
+    public void stopActionBarStatusCursorLoader(String account) {
         // TODO(viki): Auto-generated method stub
 
     }
diff --git a/src/com/android/mail/ui/AbstractMailActivity.java b/src/com/android/mail/ui/AbstractMailActivity.java
index 6215c57..9ede81b 100644
--- a/src/com/android/mail/ui/AbstractMailActivity.java
+++ b/src/com/android/mail/ui/AbstractMailActivity.java
@@ -27,8 +27,7 @@
 import android.view.WindowManager;
 
 import com.android.mail.R;
-import com.android.mail.RestrictedActivity;
-import com.android.mail.UiHandler;
+import com.android.mail.ui.ViewMode.Mode;
 
 import java.io.UnsupportedEncodingException;
 import java.net.URLEncoder;
@@ -46,7 +45,7 @@
  *
  */
 public abstract class AbstractMailActivity extends Activity
-        implements HelpCallback, RestrictedActivity {
+        implements ControllableActivity {
 
     private NfcAdapter mNfcAdapter; // final after onCreate
     private NdefMessage mForegroundNdef;
@@ -89,11 +88,6 @@
     }
 
     @Override
-    public Context getApplicationContext() {
-        return this;
-    }
-
-    @Override
     protected void onStart() {
         super.onStart();
 
@@ -183,4 +177,14 @@
                 new byte[0], recordBytes);
         return new NdefMessage(new NdefRecord[] { mailto });
     }
+
+    @Override
+    public ConversationSelectionSet getBatchConversations() {
+        return new ConversationSelectionSet();
+    }
+
+    @Override
+    public Mode getViewMode() {
+        return ViewMode.UNKNOWN;
+    }
 }
diff --git a/src/com/android/mail/ActionBarView.java b/src/com/android/mail/ui/ActionBarView.java
similarity index 95%
rename from src/com/android/mail/ActionBarView.java
rename to src/com/android/mail/ui/ActionBarView.java
index 2f8ab32..8c24d02 100644
--- a/src/com/android/mail/ActionBarView.java
+++ b/src/com/android/mail/ui/ActionBarView.java
@@ -15,7 +15,7 @@
  *      limitations under the License.
  *******************************************************************************/
 
-package com.android.mail;
+package com.android.mail.ui;
 
 import android.app.ActionBar;
 import android.os.Bundle;
@@ -54,9 +54,9 @@
          */
         SEARCH_RESULTS,
         /**
-         * Viewing a list of labels
+         * Viewing a list of folders
          */
-        LABEL,
+        FOLDER,
         /**
          * Viewing a conversation from search results
          */
@@ -118,10 +118,10 @@
     void updateActionBar(String[] mAccountNames, String currentAccount);
 
     /**
-     * Update the label that the user is currently viewing??
-     * @param label
+     * Update the folder that the user is currently viewing??
+     * @param folder
      */
-    void setLabel(String label);
+    void setFolder(String folder);
 
     /**
      * Returns the menu ID for the menu in this actionbar.
diff --git a/src/com/android/mail/browse/ActionbarActivity.java b/src/com/android/mail/ui/ActionbarActivity.java
similarity index 92%
rename from src/com/android/mail/browse/ActionbarActivity.java
rename to src/com/android/mail/ui/ActionbarActivity.java
index bf767bf..39079ac 100644
--- a/src/com/android/mail/browse/ActionbarActivity.java
+++ b/src/com/android/mail/ui/ActionbarActivity.java
@@ -15,15 +15,12 @@
  *      limitations under the License.
  *******************************************************************************/
 
-package com.android.mail.browse;
+package com.android.mail.ui;
 
 import com.android.mail.ConversationListContext;
-import com.android.mail.MailActionBar;
-import com.android.mail.ActionBarView.Mode;
-import com.android.mail.MailActionBar.Callback;
-import com.android.mail.RestrictedActivity;
 import com.android.mail.R;
-import com.android.mail.ViewMode;
+import com.android.mail.ui.ActionBarView.Mode;
+import com.android.mail.ui.MailActionBar.Callback;
 
 import android.app.ActionBar;
 import android.app.Activity;
@@ -111,7 +108,7 @@
     }
 
     public void testLabelMode(View v){
-        changeMode(Mode.LABEL);
+        changeMode(Mode.FOLDER);
     }
 
     @Override
@@ -136,12 +133,12 @@
     }
 
     @Override
-    public void navigateToLabel(String labelCanonicalName) {
+    public void navigateToFolder(String folderCanonicalName) {
         // TODO(viki): Auto-generated method stub
     }
 
     @Override
-    public void showLabelList() {
+    public void showFolderList() {
         // TODO(viki): Auto-generated method stub
     }
 
diff --git a/src/com/android/mail/ui/ActivityController.java b/src/com/android/mail/ui/ActivityController.java
index bd96d8b..e417ba7 100644
--- a/src/com/android/mail/ui/ActivityController.java
+++ b/src/com/android/mail/ui/ActivityController.java
@@ -26,7 +26,7 @@
 import android.view.MenuItem;
 import android.view.MotionEvent;
 
-import com.android.mail.ViewMode.ModeChangeListener;
+import com.android.mail.ui.ViewMode.ModeChangeListener;
 
 /**
  * An Activity controller knows how to combine views and listeners into a functioning activity.
@@ -34,7 +34,7 @@
  * or respond to user action.
  */
 public interface ActivityController extends MenuCallback, LayoutListener, SubjectDisplayChanger,
-        ConversationSetObserver, ModeChangeListener {
+        ConversationSetObserver, ModeChangeListener, MailActionBar.Callback {
 
     // As far as possible, the methods here that correspond to Activity lifecycle have the same name
     // as their counterpart in the Activity lifecycle.
@@ -78,9 +78,12 @@
     void onActivityResult(int requestCode, int resultCode, Intent data);
 
     /**
-     * Called by the Mail activity when the back button is pressed.
+     * Called by the Mail activity when the back button is pressed. Returning true consumes the
+     * event and disallows the calling method from trying to handle the back button any other way.
+     *
      * @see android.app.Activity#onBackPressed()
-     * @return
+     * @return true if the back press was handled and the event was consumed. Return false if the
+     * event was not consumed.
      */
     boolean onBackPressed();
 
diff --git a/src/com/android/mail/ui/ControllableActivity.java b/src/com/android/mail/ui/ControllableActivity.java
new file mode 100644
index 0000000..8d4a0a8
--- /dev/null
+++ b/src/com/android/mail/ui/ControllableActivity.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ *      Copyright (C) 2012 Google Inc.
+ *      Licensed to The Android Open Source Project.
+ *
+ *      Licensed under the Apache License, Version 2.0 (the "License");
+ *      you may not use this file except in compliance with the License.
+ *      You may obtain a copy of the License at
+ *
+ *           http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *      Unless required by applicable law or agreed to in writing, software
+ *      distributed under the License is distributed on an "AS IS" BASIS,
+ *      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *      See the License for the specific language governing permissions and
+ *      limitations under the License.
+ *******************************************************************************/
+
+package com.android.mail.ui;
+
+import com.android.mail.ui.ViewMode.Mode;
+
+/**
+ * A controllable activity is an Activity that has a Controller attached. This activity must be
+ * able to attach the various view fragments and delegate the method calls between them.
+ */
+public interface ControllableActivity extends HelpCallback, RestrictedActivity {
+    /**
+     * Returns the conversations selected by the user for performing a batch action like archive,
+     * delete, etc.
+     * @return conversations selected
+     */
+    ConversationSelectionSet getBatchConversations();
+
+    /**
+     * Returns the mode that the activity is currently in.
+     * @see com.android.mail.ui.ViewMode.Mode
+     * @return the mode the activity is currently in.
+     */
+    Mode getViewMode();
+
+}
diff --git a/src/com/android/mail/ui/ControllerFactory.java b/src/com/android/mail/ui/ControllerFactory.java
index d89d6b6..6b025ff 100644
--- a/src/com/android/mail/ui/ControllerFactory.java
+++ b/src/com/android/mail/ui/ControllerFactory.java
@@ -17,7 +17,6 @@
 
 package com.android.mail.ui;
 
-import com.android.mail.ViewMode;
 
 /**
  * Creates the appropriate {@link ActivityController} to control {@link MailActivity}.
diff --git a/src/com/android/mail/ui/ConversationSelectionSet.java b/src/com/android/mail/ui/ConversationSelectionSet.java
index d498591..3e4484e 100644
--- a/src/com/android/mail/ui/ConversationSelectionSet.java
+++ b/src/com/android/mail/ui/ConversationSelectionSet.java
@@ -23,14 +23,10 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 
-import com.android.mail.ConversationInfo;
-import com.android.mail.providers.Folder;
-
+import com.android.mail.providers.Conversation;
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.HashMap;
-import java.util.Map;
 
 /**
  * A simple thread-safe wrapper over a set of conversations representing a
@@ -40,8 +36,29 @@
  * responding to change events.
  */
 public class ConversationSelectionSet implements Parcelable {
-    private final HashMap<Long, ConversationInfo> mInternalMap =
-            new HashMap<Long, ConversationInfo>();
+    public static final Parcelable.Creator<ConversationSelectionSet> CREATOR =
+            new Parcelable.Creator<ConversationSelectionSet>() {
+
+        @Override
+        public ConversationSelectionSet createFromParcel(Parcel source) {
+            ConversationSelectionSet result = new ConversationSelectionSet();
+            Parcelable[] conversations = source.readParcelableArray(
+                            Conversation.class.getClassLoader());
+            for (Parcelable parceled : conversations) {
+                        Conversation conversation = (Conversation) parceled;
+                        result.put(conversation.id, conversation);
+            }
+            return result;
+        }
+
+        @Override
+        public ConversationSelectionSet[] newArray(int size) {
+            return new ConversationSelectionSet[size];
+        }
+    };
+
+    private final HashMap<Long, Conversation> mInternalMap =
+            new HashMap<Long, Conversation>();
 
     @VisibleForTesting
     final ArrayList<ConversationSetObserver> mObservers = new ArrayList<ConversationSetObserver>();
@@ -55,13 +72,33 @@
         mObservers.add(observer);
     }
 
-    /**
-     * Unregisters an observer for change events.
-     *
-     * @param observer the observer to unregister.
-     */
-    public synchronized void removeObserver(ConversationSetObserver observer) {
-        mObservers.remove(observer);
+    /** @see java.util.HashMap#clear */
+    public synchronized void clear() {
+        boolean initiallyNotEmpty = !mInternalMap.isEmpty();
+        mInternalMap.clear();
+
+        if (mInternalMap.isEmpty() && initiallyNotEmpty) {
+            ArrayList<ConversationSetObserver> observersCopy = Lists.newArrayList(mObservers);
+            dispatchOnChange(observersCopy);
+            dispatchOnEmpty(observersCopy);
+        }
+    }
+
+    /** @see java.util.HashMap#containsKey */
+    private synchronized boolean containsKey(Long key) {
+        return mInternalMap.containsKey(key);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    private synchronized void dispatchOnBecomeUnempty(
+            ArrayList<ConversationSetObserver> observers) {
+        for (ConversationSetObserver observer : observers) {
+            observer.onSetPopulated(this);
+        }
     }
 
     private synchronized void dispatchOnChange(ArrayList<ConversationSetObserver> observers) {
@@ -74,24 +111,25 @@
 
     private synchronized void dispatchOnEmpty(ArrayList<ConversationSetObserver> observers) {
         for (ConversationSetObserver observer : observers) {
-            observer.onSetEmpty(this);
-        }
-    }
-
-    private synchronized void dispatchOnBecomeUnempty(
-            ArrayList<ConversationSetObserver> observers) {
-        for (ConversationSetObserver observer : observers) {
-            observer.onSetPopulated(this);
+            observer.onSetEmpty();
         }
     }
 
     /** @see java.util.HashMap#get */
-    private synchronized ConversationInfo get(Long id) {
+    private synchronized Conversation get(Long id) {
         return mInternalMap.get(id);
     }
 
+    /**
+     * Is this conversation set empty?
+     * @return true if the conversation selection set is empty. False otherwise.
+     */
+    public synchronized boolean isEmpty() {
+        return mInternalMap.isEmpty();
+    }
+
     /** @see java.util.HashMap#put */
-    private synchronized void put(Long id, ConversationInfo info) {
+    private synchronized void put(Long id, Conversation info) {
         boolean initiallyEmpty = mInternalMap.isEmpty();
         mInternalMap.put(id, info);
 
@@ -114,99 +152,42 @@
         }
     }
 
+    /**
+     * Unregisters an observer for change events.
+     *
+     * @param observer the observer to unregister.
+     */
+    public synchronized void removeObserver(ConversationSetObserver observer) {
+        mObservers.remove(observer);
+    }
+
     /** @see java.util.HashMap#size */
-    private synchronized int size() {
+    public synchronized int size() {
         return mInternalMap.size();
     }
 
-    /** @see java.util.HashMap#values */
-    private synchronized Collection<ConversationInfo> values() {
-        return mInternalMap.values();
-    }
-
-    /** @see java.util.HashMap#containsKey */
-    private synchronized boolean containsKey(Long key) {
-        return mInternalMap.containsKey(key);
-    }
-
-    /** @see java.util.HashMap#clear */
-    private synchronized void clear() {
-        boolean initiallyNotEmpty = !mInternalMap.isEmpty();
-        mInternalMap.clear();
-
-        if (mInternalMap.isEmpty() && initiallyNotEmpty) {
-            ArrayList<ConversationSetObserver> observersCopy = Lists.newArrayList(mObservers);
-            dispatchOnChange(observersCopy);
-            dispatchOnEmpty(observersCopy);
-        }
-    }
-
     /**
-     * Determines the set of labels associated with the selected conversations.
-     * If the set of labels differ between the conversations, it will return the
-     * set by the first one in the iterator order.
-     *
-     * @return the set of labels associated with the selection set.
+     * Toggle a checkmark for the given conversation.
+     * @param conversation
      */
-    public synchronized Map<String, Folder> getFolders() {
-        if (mInternalMap.isEmpty()) {
-            return Collections.emptyMap();
+    public void toggle(Conversation conversation) {
+        long conversationId = conversation.id;
+        if (containsKey(conversationId)) {
+            remove(conversationId);
         } else {
-            return mInternalMap.values().iterator().next().getFolders();
+            put(conversationId, conversation);
         }
+
     }
 
-    @Override
-    public int describeContents() {
-        return 0;
+    /** @see java.util.HashMap#values */
+    public synchronized Collection<Conversation> values() {
+        return mInternalMap.values();
     }
 
     @Override
     public void writeToParcel(Parcel dest, int flags) {
-        ConversationInfo[] values = values().toArray(new ConversationInfo[size()]);
+        Conversation[] values = values().toArray(new Conversation[size()]);
         dest.writeParcelableArray(values, flags);
     }
-
-    public static final Parcelable.Creator<ConversationSelectionSet> CREATOR =
-            new Parcelable.Creator<ConversationSelectionSet>() {
-
-        @Override
-        public ConversationSelectionSet createFromParcel(Parcel source) {
-            ConversationSelectionSet result = new ConversationSelectionSet();
-            Parcelable[] conversations = source.readParcelableArray(
-                    ConversationInfo.class.getClassLoader());
-            for (Parcelable parceled : conversations) {
-                ConversationInfo conversation = (ConversationInfo) parceled;
-                result.put(conversation.getConversationId(), conversation);
-            }
-            return result;
-        }
-
-        @Override
-        public ConversationSelectionSet[] newArray(int size) {
-            return new ConversationSelectionSet[size];
-        }
-    };
-
-    /**
-     * Toggles the given conversation in the selection set.
-     */
-     public synchronized void toggle(long conversationId, long maxMessageId,
-             Map<String, Folder> folders) {
-         if (containsKey(conversationId)) {
-             remove(conversationId);
-         } else {
-             put(conversationId, new ConversationInfo(conversationId, maxMessageId, folders));
-         }
-     }
-
-     /**
-      * Updates the label a given conversation in the set may have.
-      */
-     public synchronized void onLabelChanged(Folder folders, long conversationId, boolean added) {
-         if (containsKey(conversationId)) {
-             ConversationInfo info = get(conversationId);
-             info.updateFolder(folders, added);
-         }
-     }
 }
diff --git a/src/com/android/mail/ui/ConversationSetObserver.java b/src/com/android/mail/ui/ConversationSetObserver.java
index 7599fbf..bd85e03 100644
--- a/src/com/android/mail/ui/ConversationSetObserver.java
+++ b/src/com/android/mail/ui/ConversationSetObserver.java
@@ -29,10 +29,9 @@
     // implementation, the observers can wreck the selection set unknowingly!!
 
     /**
-     * Called when the selection set becomes empty. The observer should not make any
-     * modifications to the set while handling this event.
+     * Called when the selection set becomes empty.
      */
-    void onSetEmpty(ConversationSelectionSet set);
+    void onSetEmpty();
 
     /**
      * Handle when the selection set is populated with some items. The observer should not make any
diff --git a/src/com/android/mail/MailActionBar.java b/src/com/android/mail/ui/MailActionBar.java
similarity index 77%
rename from src/com/android/mail/MailActionBar.java
rename to src/com/android/mail/ui/MailActionBar.java
index 8aeae2a..fe7cf70 100644
--- a/src/com/android/mail/MailActionBar.java
+++ b/src/com/android/mail/ui/MailActionBar.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package com.android.mail;
+package com.android.mail.ui;
 
 import android.app.ActionBar;
 import android.app.ActionBar.OnNavigationListener;
@@ -30,8 +30,15 @@
 import android.widget.TextView;
 import android.widget.Toast;
 
+import com.android.mail.R;
+import com.android.mail.AccountRecentLabelSpinner;
+import com.android.mail.AccountSpinnerAdapter;
+import com.android.mail.ConversationListContext;
+
 /**
  * View to manage the various states of the Gmail Action Bar
+ *
+ * TODO(viki): Include ConversatinSubjectDisplayer here as well.
  */
 public class MailActionBar extends LinearLayout implements ActionBarView, OnNavigationListener {
     /**
@@ -68,7 +75,7 @@
          */
         boolean navigateToAccount(final String account);
 
-        void navigateToLabel(final String labelCanonicalName);
+        void navigateToFolder(final String folderCanonicalName);
 
         /**
          * Invoked when the user is already viewing search results
@@ -77,29 +84,29 @@
          */
         void reloadSearch(String string);
 
-        void showLabelList();
+        void showFolderList();
 
         void startActionBarStatusCursorLoader(String account);
 
         void stopActionBarStatusCursorLoader(String account);
     }
 
+    private String[] mAccountNames;
     private ActionBar mActionBar;
     protected RestrictedActivity mActivity;
+    private Callback mCallback;
+    protected View mFolderView;
     private Mode mMode;
-    protected AccountRecentLabelSpinner mSpinnerView;
-    SpinnerAdapter mSpinner;
+
+    private MenuItem mRefreshItem;
+
     private MenuItem mSearch;
+    SpinnerAdapter mSpinner;
+    protected AccountRecentLabelSpinner mSpinnerView;
 
     // TODO(viki): This is a SnippetTextView in the Gmail source code. Resolve.
     private TextView mSubjectView;
 
-    protected View mLabelView;
-    private Callback mCallback;
-    private String[] mAccountNames;
-
-    private MenuItem mRefreshItem;
-
     public MailActionBar(Context context) {
         this(context, null);
     }
@@ -114,9 +121,6 @@
         mMode = Mode.NORMAL;
     }
 
-    /* (non-Javadoc)
-     * @see com.android.mail.ActionBarView#createOptionsMenu(android.view.Menu)
-     */
     @Override
     public boolean createOptionsMenu(Menu menu) {
         // If the mode is valid, then set the initial menu
@@ -129,17 +133,11 @@
         return true;
     }
 
-    /* (non-Javadoc)
-     * @see com.android.mail.ActionBarView#getMode()
-     */
     @Override
     public Mode getMode() {
         return mMode;
     }
 
-    /* (non-Javadoc)
-     * @see com.android.mail.ActionBarView#getOptionsMenuId()
-     */
     @Override
     public int getOptionsMenuId() {
         switch (mMode){
@@ -147,7 +145,7 @@
                 // Fallthrough
             case SEARCH_RESULTS:
                 return R.menu.conversation_list_menu;
-            case LABEL:
+            case FOLDER:
                 return R.menu.label_list_menu;
             case SEARCH_RESULTS_CONVERSATION:
                 return R.menu.conversation_actions;
@@ -157,27 +155,18 @@
         return 0;
     }
 
-    /* (non-Javadoc)
-     * @see com.android.mail.ActionBarView#handleRestore(android.os.Bundle)
-     */
     @Override
     public void handleRestore(Bundle savedInstanceState) {
         // TODO(viki): Auto-generated method stub
 
     }
 
-    /* (non-Javadoc)
-     * @see com.android.mail.ActionBarView#handleSaveInstanceState(android.os.Bundle)
-     */
     @Override
     public void handleSaveInstanceState(Bundle outState) {
         // TODO(viki): Auto-generated method stub
 
     }
 
-    /*
-     * @see com.android.mail.ActionBarView#initialize(com.android.mail.RestrictedActivity, com.android.mail.MailActionBar.Callback, com.android.mail.ViewMode, android.app.ActionBar)
-     */
     @Override
     public void initialize(RestrictedActivity activity, Callback callback, ViewMode viewMode,
             ActionBar actionBar) {
@@ -194,43 +183,38 @@
         mActionBar.setListNavigationCallbacks(mSpinner, this);
     }
 
-    /* (non-Javadoc)
-     * @see com.android.mail.ActionBarView#onPause()
-     */
+    @Override
+    public boolean onNavigationItemSelected(int itemPosition, long itemId) {
+        // Don't do anything. Toast on the action.
+        Toast.makeText(getContext(), "Selected item " + itemPosition, Toast.LENGTH_SHORT).show();
+        return false;
+    }
+
     @Override
     public void onPause() {
         // TODO(viki): Auto-generated method stub
 
     }
 
-    /* (non-Javadoc)
-     * @see com.android.mail.ActionBarView#onResume()
-     */
     @Override
     public void onResume() {
         // TODO(viki): Auto-generated method stub
 
     }
 
-    /* (non-Javadoc)
-     * @see com.android.mail.ActionBarView#onStatusResult(java.lang.String, int)
-     */
     @Override
     public void onStatusResult(String account, int status) {
-        // Update the inbox label if required
+        // Update the inbox folder if required
         mCallback.stopActionBarStatusCursorLoader(account);
     }
 
-    /* (non-Javadoc)
-     * @see com.android.mail.ActionBarView#prepareOptionsMenu()
-     */
     @Override
     public boolean prepareOptionsMenu(Menu menu) {
         if (mSubjectView != null){
             mSubjectView.setVisibility(GONE);
         }
-        if (mLabelView != null){
-            mLabelView.setVisibility(GONE);
+        if (mFolderView != null){
+            mFolderView.setVisibility(GONE);
         }
 
         switch (mMode){
@@ -255,15 +239,12 @@
                 if (mSearch != null) {
                     mSearch.collapseActionView();
                 }
-            case LABEL:
+            case FOLDER:
                 break;
         }
         return false;
     }
 
-    /* (non-Javadoc)
-     * @see com.android.mail.ActionBarView#setActionBarIconHome()
-     */
     @Override
     public void removeBackButton() {
         if (mActionBar == null) {
@@ -276,9 +257,6 @@
         mActivity.getActionBar().setHomeButtonEnabled(false);
     }
 
-    /* (non-Javadoc)
-     * @see com.android.mail.ActionBarView#setActionBarIconBack()
-     */
     @Override
     public void setBackButton() {
         if (mActionBar == null){
@@ -291,41 +269,18 @@
         mActivity.getActionBar().setHomeButtonEnabled(true);
     }
 
-    /* (non-Javadoc)
-     * @see com.android.mail.ActionBarView#setLabel(java.lang.String)
-     */
     @Override
-    public void setLabel(String label) {
+    public void setFolder(String folder) {
         // TODO(viki): Add this functionality to change the label.
-//        if (mAdvancedSearchWrapper != null) {
-//            mAdvancedSearchWrapper.setLabel(label);
-//        }
-//        super.setLabel(label);
     }
 
-    /* (non-Javadoc)
-     * @see com.android.mail.ActionBarView#setMode(com.android.mail.ActionBarView.Mode)
-     */
     @Override
     public boolean setMode(Mode mode) {
         mMode = mode;
         return true;
     }
 
-    /* (non-Javadoc)
-     * @see com.android.mail.ActionBarView#updateActionBar(java.lang.String[], java.lang.String)
-     */
     @Override
     public void updateActionBar(String[] accounts, String currentAccount) {
     }
-
-    /* (non-Javadoc)
-     * @see android.app.ActionBar.OnNavigationListener#onNavigationItemSelected(int, long)
-     */
-    @Override
-    public boolean onNavigationItemSelected(int itemPosition, long itemId) {
-        // Don't do anything. Toast on the action.
-        Toast.makeText(getContext(), "Selected item " + itemPosition, Toast.LENGTH_SHORT).show();
-        return false;
-    }
 }
diff --git a/src/com/android/mail/ui/MailActivity.java b/src/com/android/mail/ui/MailActivity.java
index a8a9c44..a3e3b96 100644
--- a/src/com/android/mail/ui/MailActivity.java
+++ b/src/com/android/mail/ui/MailActivity.java
@@ -26,7 +26,6 @@
 import android.view.MenuItem;
 import android.view.MotionEvent;
 
-import com.android.mail.ViewMode;
 
 /**
  * This is the root activity container that holds the left navigation fragment
@@ -34,6 +33,10 @@
  * conversation list or a conversation view).
  */
 public class MailActivity extends AbstractMailActivity {
+    // TODO(viki) This class lacks: Conversation Position tracking
+    // TODO(viki) This class lacks: What's New dialog
+    // TODO(viki) This class lacks: Sync Window Upgrade dialog
+
     /**
      * The activity controller to which we delegate most Activity lifecycle events.
      */
@@ -43,6 +46,13 @@
      */
     private ViewMode mViewMode;
 
+    /**
+     * A clean launch is when the activity is not resumed. We want to show a "What's New" dialog
+     * on a clean launch: when the user started the Activity by tapping on the icon: not when he
+     * selected "Up" from compose, not when he resumed the activity, etc.
+     */
+    private boolean mLaunchedCleanly = false;
+
     @Override
     public boolean dispatchTouchEvent(MotionEvent ev) {
         // TODO(viki): Why is there a check for null only in in this method?
@@ -54,6 +64,11 @@
     }
 
     @Override
+    public ConversationSelectionSet getBatchConversations() {
+        return mController.getBatchConversations();
+    }
+
+    @Override
     public void onActionModeFinished(ActionMode mode) {
         super.onActionModeFinished(mode);
         mController.onActionModeFinished(mode);
@@ -93,12 +108,14 @@
         // activity launched directly from a send-to intent. (in that case the
         // action is null.)
         if (savedState == null && intent.getAction() != null) {
+            mLaunchedCleanly = true;
         }
     }
 
     @Override
     public Dialog onCreateDialog(int id, Bundle bundle) {
         Dialog dialog = mController.onCreateDialog(id, bundle);
+        // TODO(viki): Handle what's new and the sync window upgrade dialog here.
         return dialog == null ? super.onCreateDialog(id, bundle) : dialog;
     }
 
@@ -144,7 +161,6 @@
     @Override
     public void onSaveInstanceState(Bundle outState) {
         super.onSaveInstanceState(outState);
-
         mController.onSaveInstanceState(outState);
     }
 
@@ -157,8 +173,9 @@
     @Override
     protected void onStart() {
         super.onStart();
-
-        // TODO(viki): Show a "what's new screen"
+        if (mLaunchedCleanly) {
+            // TODO(viki): Show a "what's new screen"
+        }
     }
 
     @Override
diff --git a/src/com/android/mail/ui/MenuCallback.java b/src/com/android/mail/ui/MenuCallback.java
index 13f9cf0..f4a535e 100644
--- a/src/com/android/mail/ui/MenuCallback.java
+++ b/src/com/android/mail/ui/MenuCallback.java
@@ -33,12 +33,12 @@
     /**
      * Invoked whenever a label is added or removed.
      */
-    void onLabelChanged(Folder label, long conversationId, boolean added);
+    void onFolderChanged(Folder label, long conversationId, boolean added);
 
     /**
      * Invoked once all the modifications on the labels have been performed.
      */
-    void doneChangingLabels(FolderOperations labelOperations);
+    void doneChangingFolders(FolderOperations labelOperations);
 
     /**
      * Invoked when the user requests search mode
diff --git a/src/com/android/mail/ui/OnePaneController.java b/src/com/android/mail/ui/OnePaneController.java
index ce29ef4..c096b5d 100644
--- a/src/com/android/mail/ui/OnePaneController.java
+++ b/src/com/android/mail/ui/OnePaneController.java
@@ -17,7 +17,10 @@
 
 package com.android.mail.ui;
 
-import com.android.mail.ViewMode;
+import android.os.Bundle;
+import android.view.Window;
+
+import com.android.mail.R;
 
 /**
  * Controller for one-pane Mail activity. One Pane is used for phones, where screen real estate is
@@ -25,8 +28,7 @@
  */
 
 // Called OnePaneActivityController in Gmail.
-public class OnePaneController extends AbstractActivityController {
-
+public final class OnePaneController extends AbstractActivityController {
     /**
      * @param activity
      * @param viewMode
@@ -36,4 +38,19 @@
         // TODO(viki): Auto-generated constructor stub
     }
 
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        // Request opaque actionbar
+        mActivity.getWindow().requestFeature(Window.FEATURE_ACTION_BAR);
+        // Set 1-pane content view.
+        mActivity.setContentView(R.layout.one_pane_activity);
+
+        super.onCreate(savedInstanceState);
+    }
+
+    @Override
+    protected boolean isConversationListVisible() {
+        // TODO(viki): Auto-generated method stub
+        return false;
+    }
 }
diff --git a/src/com/android/mail/RestrictedActivity.java b/src/com/android/mail/ui/RestrictedActivity.java
similarity index 99%
rename from src/com/android/mail/RestrictedActivity.java
rename to src/com/android/mail/ui/RestrictedActivity.java
index 2596fbc..2aec8ce 100644
--- a/src/com/android/mail/RestrictedActivity.java
+++ b/src/com/android/mail/ui/RestrictedActivity.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package com.android.mail;
+package com.android.mail.ui;
 
 import android.app.ActionBar;
 import android.app.Activity;
diff --git a/src/com/android/mail/ui/TwoPaneController.java b/src/com/android/mail/ui/TwoPaneController.java
index 5e8d85d..56510ee 100644
--- a/src/com/android/mail/ui/TwoPaneController.java
+++ b/src/com/android/mail/ui/TwoPaneController.java
@@ -17,7 +17,6 @@
 
 package com.android.mail.ui;
 
-import com.android.mail.ViewMode;
 
 /**
  * Controller for one-pane Mail activity. One Pane is used for phones, where screen real estate is
@@ -25,7 +24,7 @@
  */
 
 // Called OnePaneActivityController in Gmail.
-public class TwoPaneController extends AbstractActivityController {
+public final class TwoPaneController extends AbstractActivityController {
 
     /**
      * @param activity
@@ -36,4 +35,10 @@
         // TODO(viki): Auto-generated constructor stub
     }
 
+    @Override
+    protected boolean isConversationListVisible() {
+        // TODO(viki): Auto-generated method stub
+        return false;
+    }
+
 }
diff --git a/src/com/android/mail/UiHandler.java b/src/com/android/mail/ui/UiHandler.java
similarity index 98%
rename from src/com/android/mail/UiHandler.java
rename to src/com/android/mail/ui/UiHandler.java
index 696e1e9..447718a 100644
--- a/src/com/android/mail/UiHandler.java
+++ b/src/com/android/mail/ui/UiHandler.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package com.android.mail;
+package com.android.mail.ui;
 
 import android.app.Activity;
 import android.app.FragmentTransaction;
diff --git a/src/com/android/mail/ViewMode.java b/src/com/android/mail/ui/ViewMode.java
similarity index 79%
rename from src/com/android/mail/ViewMode.java
rename to src/com/android/mail/ui/ViewMode.java
index c3631f8..01b10be 100644
--- a/src/com/android/mail/ViewMode.java
+++ b/src/com/android/mail/ui/ViewMode.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package com.android.mail;
+package com.android.mail.ui;
 
 import com.android.mail.utils.Utils;
 import com.google.common.collect.Lists;
@@ -37,19 +37,52 @@
 
     // Do not change the order of the values in the enum. The ordinal position is used in a
     // saved instance bundle. When adding values, add them to the end of the enum.
-    enum Mode {
+    /**
+     * All possible modes that a Mail activity can be in.
+     */
+    public static enum Mode {
+        /**
+         * Uncertain mode. The mode has not been initialized.
+         */
         MODE_UNKNOWN,
-        MODE_LABEL_LIST,
+        /**
+         * Mode when showing a list of folders.
+         */
+        MODE_FOLDER_LIST,
+        /**
+         * Mode when showing a list of conversations
+         */
         MODE_CONVERSATION_LIST,
+        /**
+         * Mode when showing a single conversation.
+         */
         MODE_CONVERSATION,
+        /**
+         * Mode when showing results from user search.
+         */
         MODE_SEARCH_RESULTS,
     }
 
     // Handy names for external users of this class.
+    /**
+     * Uncertain mode. The mode has not been initialized.
+     */
     public static Mode UNKNOWN = Mode.MODE_UNKNOWN;
-    public static Mode LABEL_LIST = Mode.MODE_LABEL_LIST;
+    /**
+     * Mode when showing a list of folders.
+     */
+    public static Mode FOLDER_LIST = Mode.MODE_FOLDER_LIST;
+    /**
+     * Mode when showing a list of conversations
+     */
     public static Mode CONVERSATION_LIST = Mode.MODE_CONVERSATION_LIST;
+    /**
+     * Mode when showing a single conversation.
+     */
     public static Mode CONVERSATION = Mode.MODE_CONVERSATION;
+    /**
+     * Mode when showing results from user search.
+     */
     public static Mode SEARCH_RESULTS = Mode.MODE_SEARCH_RESULTS;
 
     private Mode mMode = UNKNOWN;
@@ -77,11 +110,11 @@
     }
 
     /**
-     * Requests a transition of the mode to show the label list as the prominent view.
+     * Requests a transition of the mode to show the folder list as the prominent view.
      * @return Whether or not a change occured.
      */
-    public boolean transitionToLabelListMode() {
-        return setModeInternal(LABEL_LIST);
+    public boolean transitionToFolderListMode() {
+        return setModeInternal(FOLDER_LIST);
     }
 
     /**
@@ -120,8 +153,8 @@
         return mMode == CONVERSATION_LIST;
     }
 
-    public boolean isLabelListMode() {
-        return mMode == LABEL_LIST;
+    public boolean isFolderListMode() {
+        return mMode == FOLDER_LIST;
     }
 
     public void handleSaveInstanceState(Bundle outState) {