Add subtitles for action bars and context modes.

Fix an issue where context mode content was cleared before animating out.

Change-Id: Ie7a065e65bc18e3da32de07543d0f71d2a2d648c
diff --git a/api/current.xml b/api/current.xml
index 72630eb..f941780 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -19620,6 +19620,43 @@
 <parameter name="title" type="java.lang.CharSequence">
 </parameter>
 </method>
+<method name="setStandardNavigationMode"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setSubtitle"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="subtitle" type="java.lang.CharSequence">
+</parameter>
+</method>
+<method name="setTitle"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="title" type="java.lang.CharSequence">
+</parameter>
+</method>
 <method name="startContextMode"
  return="void"
  abstract="true"
diff --git a/core/java/android/app/ActionBar.java b/core/java/android/app/ActionBar.java
index 1775a0d..67133e0 100644
--- a/core/java/android/app/ActionBar.java
+++ b/core/java/android/app/ActionBar.java
@@ -103,7 +103,7 @@
      * good for extended descriptions of activity state.
      *
      * @param title The action bar's title. null is treated as an empty string.
-     * @param subtitle The action bar's subtitle. null is treated as an empty string.
+     * @param subtitle The action bar's subtitle. null will remove the subtitle entirely.
      */
     public abstract void setStandardNavigationMode(CharSequence title, CharSequence subtitle);
 
@@ -111,13 +111,37 @@
      * Set the action bar into standard navigation mode, supplying a title and subtitle.
      * 
      * Standard navigation mode is default. The title is automatically set to the
-     * name of your Activity.
+     * name of your Activity on startup if an action bar is present.
      *
      * @param title The action bar's title. null is treated as an empty string.
      */
     public abstract void setStandardNavigationMode(CharSequence title);
 
     /**
+     * Set the action bar into standard navigation mode, using the currently set title
+     * and/or subtitle.
+     *
+     * Standard navigation mode is default. The title is automatically set to the name of
+     * your Activity on startup if an action bar is present.
+     */
+    public abstract void setStandardNavigationMode();
+
+    /**
+     * Set the action bar's title. This will only be displayed in standard navigation mode.
+     *
+     * @param title Title to set
+     */
+    public abstract void setTitle(CharSequence title);
+
+    /**
+     * Set the action bar's subtitle. This will only be displayed in standard navigation mode.
+     * Set to null to disable the subtitle entirely.
+     *
+     * @param subtitle Subtitle to set
+     */
+    public abstract void setSubtitle(CharSequence subtitle);
+
+    /**
      * Set display options. This changes all display option bits at once. To change
      * a limited subset of display options, see {@link #setDisplayOptions(int, int)}.
      * 
diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java
index b36524e..6ac68aa 100644
--- a/core/java/com/android/internal/app/ActionBarImpl.java
+++ b/core/java/com/android/internal/app/ActionBarImpl.java
@@ -23,6 +23,7 @@
 
 import android.app.ActionBar;
 import android.graphics.drawable.Drawable;
+import android.os.Handler;
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.View;
@@ -52,7 +53,17 @@
     private static final int CONTEXT_DISPLAY_SPLIT = 1;
     
     private int mContextDisplayMode;
-    
+
+    final Handler mHandler = new Handler();
+    final Runnable mCloseContext = new Runnable() {
+        public void run() {
+            mUpperContextView.closeMode();
+            if (mLowerContextView != null) {
+                mLowerContextView.removeAllViews();
+            }
+        }
+    };
+
     public ActionBarImpl(View decor) {
         mActionView = (ActionBarView) decor.findViewById(com.android.internal.R.id.action_bar);
         mUpperContextView = (ActionBarContextView) decor.findViewById(
@@ -66,7 +77,7 @@
             throw new IllegalStateException(getClass().getSimpleName() + " can only be used " +
                     "with a compatible window decor layout");
         }
-        
+
         mContextDisplayMode = mLowerContextView == null ?
                 CONTEXT_DISPLAY_NORMAL : CONTEXT_DISPLAY_SPLIT;
     }
@@ -75,17 +86,22 @@
         mActionView.setCustomNavigationView(view);
         mActionView.setCallback(null);
     }
-    
+
     public void setDropdownNavigationMode(SpinnerAdapter adapter, NavigationCallback callback) {
         mActionView.setCallback(callback);
         mActionView.setNavigationMode(NAVIGATION_MODE_DROPDOWN_LIST);
         mActionView.setDropdownAdapter(adapter);
     }
-    
+
+    public void setStandardNavigationMode() {
+        mActionView.setNavigationMode(NAVIGATION_MODE_STANDARD);
+        mActionView.setCallback(null);
+    }
+
     public void setStandardNavigationMode(CharSequence title) {
         setStandardNavigationMode(title, null);
     }
-    
+
     public void setStandardNavigationMode(CharSequence title, CharSequence subtitle) {
         mActionView.setNavigationMode(NAVIGATION_MODE_STANDARD);
         mActionView.setTitle(title);
@@ -93,10 +109,18 @@
         mActionView.setCallback(null);
     }
 
+    public void setTitle(CharSequence title) {
+        mActionView.setTitle(title);
+    }
+
+    public void setSubtitle(CharSequence subtitle) {
+        mActionView.setSubtitle(subtitle);
+    }
+
     public void setDisplayOptions(int options) {
         mActionView.setDisplayOptions(options);
     }
-    
+
     public void setDisplayOptions(int options, int mask) {
         final int current = mActionView.getDisplayOptions(); 
         mActionView.setDisplayOptions((options & mask) | (current & ~mask));
@@ -170,11 +194,11 @@
         @Override
         public void finish() {
             mCallback.onDestroyContextMode(this);
-            mUpperContextView.closeMode();
-            if (mLowerContextView != null) {
-                mLowerContextView.removeAllViews();
-            }
             mAnimatorView.setDisplayedChild(NORMAL_VIEW);
+
+            // Clear out the context mode views after the animation finishes
+            mHandler.postDelayed(mCloseContext, mAnimatorView.getOutAnimation().getDuration());
+
             if (mLowerContextView != null && mLowerContextView.getVisibility() != View.GONE) {
                 // TODO Animate this
                 mLowerContextView.setVisibility(View.GONE);
diff --git a/core/java/com/android/internal/widget/ActionBarContextView.java b/core/java/com/android/internal/widget/ActionBarContextView.java
index 0ad4447..848e92e 100644
--- a/core/java/com/android/internal/widget/ActionBarContextView.java
+++ b/core/java/com/android/internal/widget/ActionBarContextView.java
@@ -29,6 +29,7 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.ImageButton;
+import android.widget.LinearLayout;
 import android.widget.TextView;
 
 /**
@@ -47,7 +48,9 @@
     
     private ImageButton mCloseButton;
     private View mCustomView;
+    private LinearLayout mTitleLayout;
     private TextView mTitleView;
+    private TextView mSubtitleView;
     private Drawable mCloseDrawable;
     
     public ActionBarContextView(Context context) {
@@ -80,40 +83,48 @@
             removeView(mCustomView);
         }
         mCustomView = view;
-        if (mTitleView != null) {
-            removeView(mTitleView);
-            mTitleView = null;
+        if (mTitleLayout != null) {
+            removeView(mTitleLayout);
+            mTitleLayout = null;
         }
         if (view != null) {
             addView(view);
         }
         requestLayout();
     }
-    
+
     public void setTitle(CharSequence title) {
         mTitle = title;
-        if (mTitleView == null) {
+        initTitle();
+    }
+
+    public void setSubtitle(CharSequence subtitle) {
+        mSubtitle = subtitle;
+        initTitle();
+    }
+
+    private void initTitle() {
+        if (mTitleLayout == null) {
             LayoutInflater inflater = LayoutInflater.from(getContext());
-            mTitleView = (TextView) inflater.inflate(R.layout.action_bar_title_item, null);
-            mTitleView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
-                    LayoutParams.WRAP_CONTENT));
-            if (title != null) {
-                mTitleView.setText(title);
+            mTitleLayout = (LinearLayout) inflater.inflate(R.layout.action_bar_title_item, null);
+            mTitleView = (TextView) mTitleLayout.findViewById(R.id.action_bar_title);
+            mSubtitleView = (TextView) mTitleLayout.findViewById(R.id.action_bar_subtitle);
+            if (mTitle != null) {
+                mTitleView.setText(mTitle);
             }
-            addView(mTitleView);
+            if (mSubtitle != null) {
+                mSubtitleView.setText(mSubtitle);
+            }
+            addView(mTitleLayout);
         } else {
-            mTitleView.setText(title);
-            if (mTitleView.getParent() == null) {
-                addView(mTitleView);
+            mTitleView.setText(mTitle);
+            mSubtitleView.setText(mSubtitle);
+            if (mTitleLayout.getParent() == null) {
+                addView(mTitleLayout);
             }
         }
     }
-    
-    public void setSubtitle(CharSequence subtitle) {
-        mSubtitle = subtitle;
-        // TODO add subtitle support
-    }
-    
+
     public void initForMode(final ActionBar.ContextMode mode) {
         final ActionBarImpl.ContextMode implMode = (ActionBarImpl.ContextMode) mode;
         
@@ -148,17 +159,17 @@
                     implMode.dispatchOnContextItemClicked(item);
                 }
             });
-            
+
             addView(button);
         }
         requestLayout();
     }
-    
+
     public void closeMode() {
         removeAllViews();
         mCustomView = null;
     }
-    
+
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
@@ -185,15 +196,15 @@
                     childSpecHeight, itemMargin);
         }
 
-        if (mTitleView != null && mCustomView == null) {
-            availableWidth = measureChildView(mTitleView, availableWidth,
+        if (mTitleLayout != null && mCustomView == null) {
+            availableWidth = measureChildView(mTitleLayout, availableWidth,
                     childSpecHeight, itemMargin);
         }
 
         final int childCount = getChildCount();
         for (int i = 0; i < childCount; i++) {
             final View child = getChildAt(i);
-            if (child == mCloseButton || child == mTitleView || child == mCustomView) {
+            if (child == mCloseButton || child == mTitleLayout || child == mCustomView) {
                 continue;
             }
             
@@ -219,8 +230,8 @@
             x += positionChild(mCloseButton, x, y, contentHeight);
         }
         
-        if (mTitleView != null && mCustomView == null) {
-            x += positionChild(mTitleView, x, y, contentHeight) + itemMargin;
+        if (mTitleLayout != null && mCustomView == null) {
+            x += positionChild(mTitleLayout, x, y, contentHeight) + itemMargin;
         }
         
         if (mCustomView != null) {
@@ -232,7 +243,7 @@
         final int childCount = getChildCount();
         for (int i = 0; i < childCount; i++) {
             final View child = getChildAt(i);
-            if (child == mCloseButton || child == mTitleView || child == mCustomView) {
+            if (child == mCloseButton || child == mTitleLayout || child == mCustomView) {
                 continue;
             }
 
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index dcc1731..dcfdced 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -39,6 +39,7 @@
 import android.view.ViewGroup;
 import android.widget.AdapterView;
 import android.widget.ImageView;
+import android.widget.LinearLayout;
 import android.widget.Spinner;
 import android.widget.SpinnerAdapter;
 import android.widget.TextView;
@@ -80,6 +81,7 @@
 
     private ImageView mIconView;
     private ImageView mLogoView;
+    private LinearLayout mTitleLayout;
     private TextView mTitleView;
     private TextView mSubtitleView;
     private Spinner mSpinner;
@@ -250,9 +252,11 @@
         if (mode != oldMode) {
             switch (oldMode) {
             case ActionBar.NAVIGATION_MODE_STANDARD:
-                if (mTitleView != null) {
-                    removeView(mTitleView);
+                if (mTitleLayout != null) {
+                    removeView(mTitleLayout);
+                    mTitleLayout = null;
                     mTitleView = null;
+                    mSubtitleView = null;
                 }
                 break;
             case ActionBar.NAVIGATION_MODE_DROPDOWN_LIST:
@@ -361,13 +365,17 @@
     
     private void initTitle() {
         LayoutInflater inflater = LayoutInflater.from(getContext());
-        mTitleView = (TextView) inflater.inflate(R.layout.action_bar_title_item, null);
-        mTitleView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
-                LayoutParams.WRAP_CONTENT));
+        mTitleLayout = (LinearLayout) inflater.inflate(R.layout.action_bar_title_item, null);
+        mTitleView = (TextView) mTitleLayout.findViewById(R.id.action_bar_title);
+        mSubtitleView = (TextView) mTitleLayout.findViewById(R.id.action_bar_subtitle);
         if (mTitle != null) {
             mTitleView.setText(mTitle);
         }
-        addView(mTitleView);
+        if (mSubtitle != null) {
+            mSubtitleView.setText(mSubtitle);
+            mSubtitleView.setVisibility(VISIBLE);
+        }
+        addView(mTitleLayout);
     }
 
     @Override
@@ -404,8 +412,8 @@
         
         switch (mNavigationMode) {
         case ActionBar.NAVIGATION_MODE_STANDARD:
-            if (mTitleView != null) {
-                measureChildView(mTitleView, availableWidth, childSpecHeight, mSpacing);
+            if (mTitleLayout != null) {
+                measureChildView(mTitleLayout, availableWidth, childSpecHeight, mSpacing);
             }
             break;
         case ActionBar.NAVIGATION_MODE_DROPDOWN_LIST:
@@ -452,8 +460,8 @@
         
         switch (mNavigationMode) {
         case ActionBar.NAVIGATION_MODE_STANDARD:
-            if (mTitleView != null) {
-                x += positionChild(mTitleView, x, y, contentHeight) + mSpacing;
+            if (mTitleLayout != null) {
+                x += positionChild(mTitleLayout, x, y, contentHeight) + mSpacing;
             }
             break;
         case ActionBar.NAVIGATION_MODE_DROPDOWN_LIST:
diff --git a/core/res/res/layout/action_bar_title_item.xml b/core/res/res/layout/action_bar_title_item.xml
index d7f7c13..3c046fe 100644
--- a/core/res/res/layout/action_bar_title_item.xml
+++ b/core/res/res/layout/action_bar_title_item.xml
@@ -14,9 +14,20 @@
      limitations under the License.
 -->
 
-<TextView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-
-    android:singleLine="true"
-    android:ellipsize="end"
-    android:textAppearance="?android:attr/textAppearanceMediumInverse" />
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:layout_width="wrap_content"
+              android:layout_height="wrap_content"
+              android:orientation="vertical" >
+    <TextView android:id="@+id/action_bar_title"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:singleLine="true"
+        android:ellipsize="end"
+        android:textAppearance="?android:attr/textAppearanceMediumInverse" />
+    <TextView android:id="@+id/action_bar_subtitle"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:singleLine="true"
+        android:ellipsize="end"
+        android:textAppearance="?android:attr/textAppearanceSmallInverse" />
+</LinearLayout>