Merge "Adding a new provider status"
diff --git a/api/current.xml b/api/current.xml
index a66acbc..710188d 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -20395,6 +20395,19 @@
 <parameter name="view" type="android.view.View">
 </parameter>
 </method>
+<method name="setCustomView"
+ return="android.app.ActionBar.Tab"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="layoutResId" type="int">
+</parameter>
+</method>
 <method name="setIcon"
  return="android.app.ActionBar.Tab"
  abstract="true"
@@ -20408,6 +20421,19 @@
 <parameter name="icon" type="android.graphics.drawable.Drawable">
 </parameter>
 </method>
+<method name="setIcon"
+ return="android.app.ActionBar.Tab"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="resId" type="int">
+</parameter>
+</method>
 <method name="setTabListener"
  return="android.app.ActionBar.Tab"
  abstract="true"
@@ -20447,6 +20473,19 @@
 <parameter name="text" type="java.lang.CharSequence">
 </parameter>
 </method>
+<method name="setText"
+ return="android.app.ActionBar.Tab"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="resId" type="int">
+</parameter>
+</method>
 <field name="INVALID_POSITION"
  type="int"
  transient="false"
@@ -68694,6 +68733,29 @@
 </parameter>
 <parameter name="selection" type="java.lang.String">
 </parameter>
+<parameter name="groupBy" type="java.lang.String">
+</parameter>
+<parameter name="having" type="java.lang.String">
+</parameter>
+<parameter name="sortOrder" type="java.lang.String">
+</parameter>
+<parameter name="limit" type="java.lang.String">
+</parameter>
+</method>
+<method name="buildQuery"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="deprecated"
+ visibility="public"
+>
+<parameter name="projectionIn" type="java.lang.String[]">
+</parameter>
+<parameter name="selection" type="java.lang.String">
+</parameter>
 <parameter name="selectionArgs" type="java.lang.String[]">
 </parameter>
 <parameter name="groupBy" type="java.lang.String">
@@ -68771,6 +68833,33 @@
 </parameter>
 <parameter name="selection" type="java.lang.String">
 </parameter>
+<parameter name="groupBy" type="java.lang.String">
+</parameter>
+<parameter name="having" type="java.lang.String">
+</parameter>
+</method>
+<method name="buildUnionSubQuery"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="deprecated"
+ visibility="public"
+>
+<parameter name="typeDiscriminatorColumn" type="java.lang.String">
+</parameter>
+<parameter name="unionColumns" type="java.lang.String[]">
+</parameter>
+<parameter name="columnsPresentInTable" type="java.util.Set&lt;java.lang.String&gt;">
+</parameter>
+<parameter name="computedColumnsOffset" type="int">
+</parameter>
+<parameter name="typeDiscriminatorValue" type="java.lang.String">
+</parameter>
+<parameter name="selection" type="java.lang.String">
+</parameter>
 <parameter name="selectionArgs" type="java.lang.String[]">
 </parameter>
 <parameter name="groupBy" type="java.lang.String">
@@ -101743,6 +101832,17 @@
  visibility="public"
 >
 </field>
+<field name="VOICE_COMMUNICATION"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="7"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="VOICE_DOWNLINK"
  type="int"
  transient="false"
@@ -144703,6 +144803,17 @@
  visibility="public"
 >
 </method>
+<method name="getIcon"
+ return="android.graphics.drawable.Drawable"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getIntent"
  return="android.content.Intent"
  abstract="false"
@@ -145289,6 +145400,32 @@
 <parameter name="fragment" type="java.lang.String">
 </parameter>
 </method>
+<method name="setIcon"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="icon" type="android.graphics.drawable.Drawable">
+</parameter>
+</method>
+<method name="setIcon"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="iconResId" type="int">
+</parameter>
+</method>
 <method name="setIntent"
  return="void"
  abstract="false"
@@ -246893,7 +247030,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="arg0" type="T">
+<parameter name="t" type="T">
 </parameter>
 </method>
 </interface>
diff --git a/core/java/android/app/ActionBar.java b/core/java/android/app/ActionBar.java
index 246d661..7a6ad0f 100644
--- a/core/java/android/app/ActionBar.java
+++ b/core/java/android/app/ActionBar.java
@@ -590,6 +590,14 @@
         public abstract Tab setIcon(Drawable icon);
 
         /**
+         * Set the icon displayed on this tab.
+         *
+         * @param resId Resource ID referring to the drawable to use as an icon
+         * @return The current instance for call chaining
+         */
+        public abstract Tab setIcon(int resId);
+
+        /**
          * Set the text displayed on this tab. Text may be truncated if there is not
          * room to display the entire string.
          *
@@ -599,6 +607,15 @@
         public abstract Tab setText(CharSequence text);
 
         /**
+         * Set the text displayed on this tab. Text may be truncated if there is not
+         * room to display the entire string.
+         *
+         * @param resId A resource ID referring to the text that should be displayed
+         * @return The current instance for call chaining
+         */
+        public abstract Tab setText(int resId);
+
+        /**
          * Set a custom view to be used for this tab. This overrides values set by
          * {@link #setText(CharSequence)} and {@link #setIcon(Drawable)}.
          *
@@ -608,6 +625,15 @@
         public abstract Tab setCustomView(View view);
 
         /**
+         * Set a custom view to be used for this tab. This overrides values set by
+         * {@link #setText(CharSequence)} and {@link #setIcon(Drawable)}.
+         *
+         * @param layoutResId A layout resource to inflate and use as a custom tab view
+         * @return The current instance for call chaining
+         */
+        public abstract Tab setCustomView(int layoutResId);
+
+        /**
          * Retrieve a previously set custom view for this tab.
          *
          * @return The custom view set by {@link #setCustomView(View)}.
diff --git a/core/java/android/database/sqlite/SQLiteCursor.java b/core/java/android/database/sqlite/SQLiteCursor.java
index fc30da2..5a6c667 100644
--- a/core/java/android/database/sqlite/SQLiteCursor.java
+++ b/core/java/android/database/sqlite/SQLiteCursor.java
@@ -125,11 +125,11 @@
             // the cursor's state doesn't change
             while (true) {
                 mLock.lock();
-                if (mCursorState != mThreadState) {
-                    mLock.unlock();
-                    break;
-                }
                 try {
+                    if (mCursorState != mThreadState) {
+                        break;
+                    }
+
                     int count = getQuery().fillWindow(cw, mMaxRead, mCount);
                     // return -1 means there is still more data to be retrieved from the resultset
                     if (count != 0) {
@@ -241,9 +241,8 @@
         mColumnNameMap = null;
         mQuery = query;
 
+        query.mDatabase.lock();
         try {
-            query.mDatabase.lock();
-
             // Setup the list of columns
             int columnCount = mQuery.columnCountLocked();
             mColumns = new String[columnCount];
diff --git a/core/java/android/database/sqlite/SQLiteQueryBuilder.java b/core/java/android/database/sqlite/SQLiteQueryBuilder.java
index 610bf70..b6aca2b 100644
--- a/core/java/android/database/sqlite/SQLiteQueryBuilder.java
+++ b/core/java/android/database/sqlite/SQLiteQueryBuilder.java
@@ -321,7 +321,7 @@
         }
 
         String sql = buildQuery(
-                projectionIn, selection, selectionArgs, groupBy, having,
+                projectionIn, selection, groupBy, having,
                 sortOrder, limit);
 
         if (Log.isLoggable(TAG, Log.DEBUG)) {
@@ -345,10 +345,6 @@
      *   formatted as an SQL WHERE clause (excluding the WHERE
      *   itself).  Passing null will return all rows for the given
      *   URL.
-     * @param selectionArgs You may include ?s in selection, which
-     *   will be replaced by the values from selectionArgs, in order
-     *   that they appear in the selection.  The values will be bound
-     *   as Strings.
      * @param groupBy A filter declaring how to group rows, formatted
      *   as an SQL GROUP BY clause (excluding the GROUP BY itself).
      *   Passing null will cause the rows to not be grouped.
@@ -365,8 +361,8 @@
      * @return the resulting SQL SELECT statement
      */
     public String buildQuery(
-            String[] projectionIn, String selection, String[] selectionArgs,
-            String groupBy, String having, String sortOrder, String limit) {
+            String[] projectionIn, String selection, String groupBy,
+            String having, String sortOrder, String limit) {
         String[] projection = computeProjection(projectionIn);
 
         StringBuilder where = new StringBuilder();
@@ -394,6 +390,19 @@
     }
 
     /**
+     * @deprecated This method's signature is misleading since no SQL parameter
+     * substitution is carried out.  The selection arguments parameter does not get
+     * used at all.  To avoid confusion, call
+     * {@link #buildQuery(String[], String, String, String, String, String)} instead.
+     */
+    @Deprecated
+    public String buildQuery(
+            String[] projectionIn, String selection, String[] selectionArgs,
+            String groupBy, String having, String sortOrder, String limit) {
+        return buildQuery(projectionIn, selection, groupBy, having, sortOrder, limit);
+    }
+
+    /**
      * Construct a SELECT statement suitable for use in a group of
      * SELECT statements that will be joined through UNION operators
      * in buildUnionQuery.
@@ -422,10 +431,6 @@
      *   formatted as an SQL WHERE clause (excluding the WHERE
      *   itself).  Passing null will return all rows for the given
      *   URL.
-     * @param selectionArgs You may include ?s in selection, which
-     *   will be replaced by the values from selectionArgs, in order
-     *   that they appear in the selection.  The values will be bound
-     *   as Strings.
      * @param groupBy A filter declaring how to group rows, formatted
      *   as an SQL GROUP BY clause (excluding the GROUP BY itself).
      *   Passing null will cause the rows to not be grouped.
@@ -443,7 +448,6 @@
             int computedColumnsOffset,
             String typeDiscriminatorValue,
             String selection,
-            String[] selectionArgs,
             String groupBy,
             String having) {
         int unionColumnsCount = unionColumns.length;
@@ -463,12 +467,36 @@
             }
         }
         return buildQuery(
-                projectionIn, selection, selectionArgs, groupBy, having,
+                projectionIn, selection, groupBy, having,
                 null /* sortOrder */,
                 null /* limit */);
     }
 
     /**
+     * @deprecated This method's signature is misleading since no SQL parameter
+     * substitution is carried out.  The selection arguments parameter does not get
+     * used at all.  To avoid confusion, call
+     * {@link #buildUnionSubQuery}
+     * instead.
+     */
+    @Deprecated
+    public String buildUnionSubQuery(
+            String typeDiscriminatorColumn,
+            String[] unionColumns,
+            Set<String> columnsPresentInTable,
+            int computedColumnsOffset,
+            String typeDiscriminatorValue,
+            String selection,
+            String[] selectionArgs,
+            String groupBy,
+            String having) {
+        return buildUnionSubQuery(
+                typeDiscriminatorColumn, unionColumns, columnsPresentInTable,
+                computedColumnsOffset, typeDiscriminatorValue, selection,
+                groupBy, having);
+    }
+
+    /**
      * Given a set of subqueries, all of which are SELECT statements,
      * construct a query that returns the union of what those
      * subqueries return.
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index f8260ca..a402c91 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -324,6 +324,10 @@
         } catch (RuntimeException e) {
             reply.writeException(e);
             res = true;
+        } catch (OutOfMemoryError e) {
+            RuntimeException re = new RuntimeException("Out of memory", e);
+            reply.writeException(re);
+            res = true;
         }
         reply.recycle();
         data.recycle();
diff --git a/core/java/android/preference/Preference.java b/core/java/android/preference/Preference.java
index 12b9f0c..e869f3f 100644
--- a/core/java/android/preference/Preference.java
+++ b/core/java/android/preference/Preference.java
@@ -22,6 +22,7 @@
 import android.content.Intent;
 import android.content.SharedPreferences;
 import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -31,6 +32,7 @@
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
+import android.widget.ImageView;
 import android.widget.ListView;
 import android.widget.TextView;
 
@@ -52,6 +54,7 @@
  * {@link SharedPreferences}. It is up to the subclass to decide how to store
  * the value.
  * 
+ * @attr ref android.R.styleable#Preference_icon
  * @attr ref android.R.styleable#Preference_key
  * @attr ref android.R.styleable#Preference_title
  * @attr ref android.R.styleable#Preference_summary
@@ -87,6 +90,11 @@
     private int mOrder = DEFAULT_ORDER;
     private CharSequence mTitle;
     private CharSequence mSummary;
+    /**
+     * mIconResId is overridden by mIcon, if mIcon is specified.
+     */
+    private int mIconResId;
+    private Drawable mIcon;
     private String mKey;
     private Intent mIntent;
     private String mFragment;
@@ -197,6 +205,10 @@
         for (int i = a.getIndexCount(); i >= 0; i--) {
             int attr = a.getIndex(i); 
             switch (attr) {
+                case com.android.internal.R.styleable.Preference_icon:
+                    mIconResId = a.getResourceId(attr, 0);
+                    break;
+
                 case com.android.internal.R.styleable.Preference_key:
                     mKey = a.getString(attr);
                     break;
@@ -499,11 +511,20 @@
             }
         }
         
+        ImageView imageView = (ImageView) view.findViewById(com.android.internal.R.id.icon);
+        if (imageView != null && (mIconResId != 0 || mIcon != null)) {
+            if (mIcon == null) {
+                mIcon = getContext().getResources().getDrawable(mIconResId);
+            }
+            if (mIcon != null) {
+                imageView.setImageDrawable(mIcon);
+            }
+        }
         if (mShouldDisableView) {
             setEnabledStateOnViews(view, isEnabled());
         }
     }
-    
+
     /**
      * Makes sure the view (and any children) get the enabled state changed.
      */
@@ -587,6 +608,42 @@
     }
 
     /**
+     * Sets the icon for this Preference with a Drawable. 
+     * This icon will be placed into the ID
+     * {@link android.R.id#icon} within the View created by
+     * {@link #onCreateView(ViewGroup)}.
+     * 
+     * @param icon The optional icon for this Preference.
+     */
+    public void setIcon(Drawable icon) {
+        if ((icon == null && mIcon != null) || (icon != null && mIcon != icon)) {
+            mIcon = icon;
+            notifyChanged();
+        }
+    }
+
+    /**
+     * Sets the icon for this Preference with a resource ID. 
+     * 
+     * @see #setIcon(Drawable)
+     * @param iconResId The icon as a resource ID.
+     */
+    public void setIcon(int iconResId) {
+        mIconResId = iconResId;
+        setIcon(mContext.getResources().getDrawable(iconResId));
+    }
+
+    /**
+     * Returns the icon of this Preference.
+     * 
+     * @return The icon.
+     * @see #setIcon(Drawable)
+     */
+    public Drawable getIcon() {
+        return mIcon;
+    }
+
+    /**
      * Returns the summary of this Preference.
      * 
      * @return The summary.
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index ffe78e7..d388985 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -3646,7 +3646,10 @@
         int count = 0;
 
         if (down) {
-            final int top = listPadding.top - incrementalDeltaY;
+            int top = -incrementalDeltaY;
+            if ((mGroupFlags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK) {
+                top += listPadding.top;
+            }
             for (int i = 0; i < childCount; i++) {
                 final View child = getChildAt(i);
                 if (child.getBottom() >= top) {
@@ -3666,7 +3669,10 @@
                 }
             }
         } else {
-            final int bottom = getHeight() - listPadding.bottom - incrementalDeltaY;
+            int bottom = getHeight() - incrementalDeltaY;
+            if ((mGroupFlags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK) {
+                bottom -= listPadding.bottom;
+            }
             for (int i = childCount - 1; i >= 0; i--) {
                 final View child = getChildAt(i);
                 if (child.getTop() <= bottom) {
diff --git a/core/java/android/widget/GridView.java b/core/java/android/widget/GridView.java
index b963536..114ae81 100644
--- a/core/java/android/widget/GridView.java
+++ b/core/java/android/widget/GridView.java
@@ -196,8 +196,12 @@
         final int count = getChildCount();
 
         if (down) {
+            int paddingTop = 0;
+            if ((mGroupFlags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK) {
+                paddingTop = getListPaddingTop();
+            }
             final int startOffset = count > 0 ?
-                    getChildAt(count - 1).getBottom() + verticalSpacing : getListPaddingTop();
+                    getChildAt(count - 1).getBottom() + verticalSpacing : paddingTop;
             int position = mFirstPosition + count;
             if (mStackFromBottom) {
                 position += numColumns - 1;
@@ -205,8 +209,12 @@
             fillDown(position, startOffset);
             correctTooHigh(numColumns, verticalSpacing, getChildCount());
         } else {
+            int paddingBottom = 0;
+            if ((mGroupFlags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK) {
+                paddingBottom = getListPaddingBottom();
+            }
             final int startOffset = count > 0 ?
-                    getChildAt(0).getTop() - verticalSpacing : getHeight() - getListPaddingBottom();
+                    getChildAt(0).getTop() - verticalSpacing : getHeight() - paddingBottom;
             int position = mFirstPosition;
             if (!mStackFromBottom) {
                 position -= numColumns;
@@ -232,7 +240,10 @@
     private View fillDown(int pos, int nextTop) {
         View selectedView = null;
 
-        final int end = (mBottom - mTop) - mListPadding.bottom;
+        int end = (mBottom - mTop);
+        if ((mGroupFlags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK) {
+            end -= mListPadding.bottom;
+        }
 
         while (nextTop < end && pos < mItemCount) {
             View temp = makeRow(pos, nextTop, true);
@@ -316,7 +327,10 @@
     private View fillUp(int pos, int nextBottom) {
         View selectedView = null;
 
-        final int end = mListPadding.top;
+        int end = 0;
+        if ((mGroupFlags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK) {
+            end = mListPadding.top;
+        }
 
         while (nextBottom > end && pos >= 0) {
 
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index e0119e9..502cc38 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -595,13 +595,21 @@
     void fillGap(boolean down) {
         final int count = getChildCount();
         if (down) {
+            int paddingTop = 0;
+            if ((mGroupFlags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK) {
+                paddingTop = getListPaddingTop();
+            }
             final int startOffset = count > 0 ? getChildAt(count - 1).getBottom() + mDividerHeight :
-                    getListPaddingTop();
+                    paddingTop;
             fillDown(mFirstPosition + count, startOffset);
             correctTooHigh(getChildCount());
         } else {
+            int paddingBottom = 0;
+            if ((mGroupFlags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK) {
+                paddingBottom = getListPaddingBottom();
+            }
             final int startOffset = count > 0 ? getChildAt(0).getTop() - mDividerHeight :
-                    getHeight() - getListPaddingBottom();
+                    getHeight() - paddingBottom;
             fillUp(mFirstPosition - 1, startOffset);
             correctTooLow(getChildCount());
         }
@@ -621,7 +629,10 @@
     private View fillDown(int pos, int nextTop) {
         View selectedView = null;
 
-        int end = (mBottom - mTop) - mListPadding.bottom;
+        int end = (mBottom - mTop);
+        if ((mGroupFlags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK) {
+            end -= mListPadding.bottom;
+        }
 
         while (nextTop < end && pos < mItemCount) {
             // is this the selected item?
@@ -651,7 +662,10 @@
     private View fillUp(int pos, int nextBottom) {
         View selectedView = null;
 
-        int end = mListPadding.top;
+        int end = 0;
+        if ((mGroupFlags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK) {
+            end = mListPadding.top;
+        }
 
         while (nextBottom > end && pos >= 0) {
             // is this the selected item?
diff --git a/core/java/android/widget/Scroller.java b/core/java/android/widget/Scroller.java
index 3f2bd25..b1f50ba 100644
--- a/core/java/android/widget/Scroller.java
+++ b/core/java/android/widget/Scroller.java
@@ -67,13 +67,12 @@
     private static final int FLING_MODE = 1;
 
     private static float DECELERATION_RATE = (float) (Math.log(0.75) / Math.log(0.9));
-    private static float ALPHA = 400; // pixels / seconds
+    private static float ALPHA = 800; // pixels / seconds
     private static float START_TENSION = 0.4f; // Tension at start: (0.4 * total T, 1.0 * Distance)
     private static float END_TENSION = 1.0f - START_TENSION;
     private static final int NB_SAMPLES = 100;
     private static final float[] SPLINE = new float[NB_SAMPLES + 1];
 
-
     private float mDeceleration;
     private final float mPpi;
 
diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java
index 86523ac..20402a3 100644
--- a/core/java/com/android/internal/app/ActionBarImpl.java
+++ b/core/java/com/android/internal/app/ActionBarImpl.java
@@ -31,6 +31,7 @@
 import android.graphics.drawable.Drawable;
 import android.os.Handler;
 import android.view.ActionMode;
+import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
@@ -563,6 +564,11 @@
         }
 
         @Override
+        public Tab setCustomView(int layoutResId) {
+            return setCustomView(LayoutInflater.from(mContext).inflate(layoutResId, null));
+        }
+
+        @Override
         public Drawable getIcon() {
             return mIcon;
         }
@@ -588,12 +594,22 @@
         }
 
         @Override
+        public Tab setIcon(int resId) {
+            return setIcon(mContext.getResources().getDrawable(resId));
+        }
+
+        @Override
         public Tab setText(CharSequence text) {
             mText = text;
             return this;
         }
 
         @Override
+        public Tab setText(int resId) {
+            return setText(mContext.getResources().getText(resId));
+        }
+
+        @Override
         public void select() {
             selectTab(this);
         }
diff --git a/core/res/res/layout-xlarge/keyguard_screen_tab_unlock.xml b/core/res/res/layout-xlarge/keyguard_screen_tab_unlock.xml
index b3645aa..c76e833 100644
--- a/core/res/res/layout-xlarge/keyguard_screen_tab_unlock.xml
+++ b/core/res/res/layout-xlarge/keyguard_screen_tab_unlock.xml
@@ -21,23 +21,22 @@
   state of the device, as well as instructions on how to get past it
   depending on the state of the device.  It is the same for landscape
   and portrait.-->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:tabunlock="http://schemas.android.com/apk/res/com.android.tabunlock"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:background="#70000000"
-    android:gravity="center_horizontal"
-    android:id="@+id/root">
+    android:orientation="vertical"
+    android:id="@+id/root"
+    android:background="#70000000">
 
     <!-- left side: status and emergency call button -->
     <LinearLayout
-            android:layout_width="match_parent"
-            android:layout_height="0dip"
-            android:layout_weight="1"
-            android:orientation="vertical"
-            android:gravity="center_vertical"
-                >
-        <include layout="@layout/keyguard_screen_status_land" />
+        android:layout_width="match_parent"
+        android:layout_height="0dip"
+        android:layout_weight="1"
+        android:orientation="vertical"
+        android:gravity="center_vertical">
+        <include layout="@layout/keyguard_screen_status_port" />
     </LinearLayout>
 
     <LinearLayout
@@ -61,6 +60,7 @@
             android:id="@+id/wave_view"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
+            android:layout_gravity="center"
             />
 
         <!-- "emergency calls only" shown when sim is missing or PUKd -->
@@ -93,5 +93,5 @@
             />
     </LinearLayout>
 
-</RelativeLayout>
+</LinearLayout>
 
diff --git a/core/res/res/layout/preference.xml b/core/res/res/layout/preference.xml
index 46c3e9c..6bd5efa 100644
--- a/core/res/res/layout/preference.xml
+++ b/core/res/res/layout/preference.xml
@@ -24,13 +24,19 @@
     android:gravity="center_vertical"
     android:paddingRight="?android:attr/scrollbarSize">
 
-    <!-- Preference should place its actual preference widget here. -->
-    <LinearLayout android:id="@+android:id/widget_frame"
+    <LinearLayout
         android:layout_width="wrap_content"
         android:layout_height="match_parent"
         android:minWidth="@dimen/preference_widget_width"
         android:gravity="center"
-        android:orientation="vertical" />
+        android:orientation="horizontal">
+        <ImageView
+            android:id="@+android:id/icon"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center"
+            />
+    </LinearLayout>
 
     <RelativeLayout
         android:layout_width="wrap_content"
@@ -59,4 +65,12 @@
 
     </RelativeLayout>
 
+    <!-- Preference should place its actual preference widget here. -->
+    <LinearLayout android:id="@+android:id/widget_frame"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:minWidth="@dimen/preference_widget_width"
+        android:gravity="center"
+        android:orientation="vertical" />
+
 </LinearLayout>
diff --git a/core/res/res/layout/preference_child.xml b/core/res/res/layout/preference_child.xml
index 713aa17..e9b50e0 100644
--- a/core/res/res/layout/preference_child.xml
+++ b/core/res/res/layout/preference_child.xml
@@ -20,20 +20,26 @@
     android:layout_height="wrap_content"
     android:minHeight="?android:attr/listPreferredItemHeight"
     android:gravity="center_vertical"
+    android:paddingLeft="16dip"
     android:paddingRight="?android:attr/scrollbarSize">
 
-    <!-- Preference should place its actual preference widget here. -->
-    <LinearLayout android:id="@+android:id/widget_frame"
+    <LinearLayout
         android:layout_width="wrap_content"
         android:layout_height="match_parent"
         android:minWidth="@dimen/preference_widget_width"
         android:gravity="center"
-        android:orientation="vertical" />
+        android:orientation="horizontal">
+        <ImageView
+            android:id="@+android:id/icon"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center"
+            />
+    </LinearLayout>
 
     <RelativeLayout
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_marginLeft="16dip"
         android:layout_marginRight="6dip"
         android:layout_marginTop="6dip"
         android:layout_marginBottom="6dip"
@@ -58,4 +64,12 @@
 
     </RelativeLayout>
 
+    <!-- Preference should place its actual preference widget here. -->
+    <LinearLayout android:id="@+android:id/widget_frame"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:minWidth="@dimen/preference_widget_width"
+        android:gravity="center"
+        android:orientation="vertical" />
+
 </LinearLayout>
diff --git a/core/res/res/values-land/dimens.xml b/core/res/res/values-land/dimens.xml
index d562d96..b1f12b5 100644
--- a/core/res/res/values-land/dimens.xml
+++ b/core/res/res/values-land/dimens.xml
@@ -21,6 +21,6 @@
 <resources>
     <dimen name="password_keyboard_key_height">47dip</dimen>
     <dimen name="password_keyboard_spacebar_vertical_correction">2dip</dimen>
-    <dimen name="preference_screen_side_margin">32dp</dimen>
-    <dimen name="preference_widget_width">64dp</dimen>
+    <dimen name="preference_screen_side_margin">96dp</dimen>
+    <dimen name="preference_widget_width">72dp</dimen>
 </resources>
\ No newline at end of file
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 55b3258..555de5e 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3854,6 +3854,8 @@
 
     <!-- Base attributes available to Preference. -->
     <declare-styleable name="Preference">
+        <!-- The optional icon for the preference -->
+        <attr name="icon" />
         <!-- The key to store the Preference value. -->
         <attr name="key" format="string" />
         <!-- The title for the Preference in a PreferenceActivity screen. -->
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 64cd00a..c8a5de8 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1806,7 +1806,7 @@
 
     <!-- Do not translate.  WebView User Agent string -->
     <string name="web_user_agent" translatable="false">Mozilla/5.0 (Linux; U; <xliff:g id="x">Android %s</xliff:g>)
-        AppleWebKit/534.11 (KHTML, like Gecko) Version/4.0 <xliff:g id="mobile">%s</xliff:g>Safari/534.11</string>
+        AppleWebKit/534.12 (KHTML, like Gecko) Version/4.0 <xliff:g id="mobile">%s</xliff:g>Safari/534.12</string>
     <!-- Do not translate.  WebView User Agent targeted content -->
     <string name="web_user_agent_target_content" translatable="false">"Mobile "</string>
 
diff --git a/docs/html/guide/topics/manifest/uses-feature-element.jd b/docs/html/guide/topics/manifest/uses-feature-element.jd
index 45f4a66..b5b30f6 100644
--- a/docs/html/guide/topics/manifest/uses-feature-element.jd
+++ b/docs/html/guide/topics/manifest/uses-feature-element.jd
@@ -472,11 +472,11 @@
 Package</strong>. Select a destination filename and path and click
 <strong>OK</strong>. </li>
 <li>Next, locate the <code>aapt</code> tool, if it is not already in your PATH.
-If you are using SDK Tools r7 or earlier, you can find <code>aapt</code> in the
-<code>&lt;<em>SDK</em>&gt;/platforms/android-&lt;<em>platform</em>&gt;/tools/</code> directory.
+If you are using SDK Tools r8 or higher, you can find <code>aapt</code> in the
+<code>&lt;<em>SDK</em>&gt;/platform-tools/</code> directory.
 <p class="note"><strong>Note:</strong> You must use the version of
-<code>aapt</code> that is provided for the latest platform release available. If
-you do not have the latest platform release, download it using the <a
+<code>aapt</code> that is provided for the latest Platform-Tools component available. If
+you do not have the latest Platform-Tools component, download it using the <a
 href="{@docRoot}sdk/adding-components.html">Android SDK and AVD Manager</a>.
 </p></li>
 <li>Run <code>aapt</code> using this syntax: </li>
@@ -522,6 +522,14 @@
        <th>Comments</th>
     </tr>
     <tr>
+       <td>Audio</td>
+       <td><code>android.hardware.audio.low_latency</td>
+       <td>The application uses a low-latency audio pipeline on the device and
+is sensitive to delays or lag in sound input or output.</td>
+<td>
+</td>
+    </tr>
+    <tr>
        <td>Bluetooth</td>
        <td><code>android.hardware.bluetooth</td>
        <td>The application uses Bluetooth radio features in the device.</td>
@@ -529,7 +537,7 @@
 </td>
     </tr>
     <tr>
-       <td rowspan="3">Camera</td>
+       <td rowspan="4">Camera</td>
        <td><code>android.hardware.camera</code></td>
        <td>The application uses the device's camera. If the device supports
            multiple cameras, the application uses the camera that facing
@@ -539,7 +547,7 @@
 <tr>
   <td><code>android.hardware.camera.autofocus</code></td>
   <td>Subfeature. The application uses the device camera's autofocus capability.</td>
-  <td rowspan="2">If declared with the <code>"android:required="true"</code>
+  <td rowspan="3">If declared with the <code>"android:required="true"</code>
 attribute, these subfeatures implicitly declare the
 <code>android.hardware.camera</code> parent feature. </td>
 </tr>
@@ -547,6 +555,10 @@
   <td><code>android.hardware.camera.flash</code></td>
   <td>Subfeature. The application uses the device camera's flash.</td>
 </tr>
+<tr>
+  <td><code>android.hardware.camera.front</code></td>
+  <td>Subfeature. The application uses a front-facing camera on the device.</td>
+</tr>
 
 <tr>
   <td rowspan="3">Location</td>
@@ -568,21 +580,43 @@
   <td>Subfeature. The application uses precise location coordinates obtained
 from a Global Positioning System receiver on the device. </td>
 </tr>
-
 <tr>
-  <td rowspan="4">Sensors</td>
+  <td>Microphone</td>
+  <td><code>android.hardware.microphone</code></td>
+  <td>The application uses a microphone on the device.
+  </td>
+  <td></td>
+</tr>
+<tr>
+  <td>Near Field Communications</td>
+  <td><code>android.hardware.nfc</td>
+  <td>The application uses NFC radio features in the device.</td>
+  <td></td>
+</tr>
+<tr>
+  <td rowspan="6">Sensors</td>
   <td><code>android.hardware.sensor.accelerometer</code></td>
   <td>The application uses motion readings from an accelerometer on the
 device.</td>
   <td></td>
 </tr>
 <tr>
+  <td><code>android.hardware.sensor.barometer</code></td>
+  <td>The application uses the device's barometer.</td>
+  <td></td>
+</tr>
+<tr>
   <td><code>android.hardware.sensor.compass</code></td>
   <td>The application uses directional readings from a magnetometer (compass) on
 the device.</td>
   <td></td>
 </tr>
 <tr>
+  <td><code>android.hardware.sensor.gyroscope</code></td>
+  <td>The application uses the device's gyroscope sensor.</td>
+  <td></td>
+</tr>
+<tr>
   <td><code>android.hardware.sensor.light</code></td>
   <td>The application uses the device's light sensor.</td>
   <td></td>
@@ -593,12 +627,20 @@
   <td></td>
 </tr>
 <tr>
-  <td>Microphone</td>
-  <td><code>android.hardware.microphone</code></td>
-  <td>The application uses a microphone on the device.
+  <td rowspan="2">SIP/VOIP</td>
+  <td><code>android.hardware.sip</code></td>
+  <td>The application uses SIP service on the device.
   </td>
   <td></td>
 </tr>
+<tr>
+  <td><code>android.hardware.sip.voip</code></td>
+  <td>Subfeature. The application uses SIP-based VOIP service on the device.
+  </td>
+  <td>If declared with the <code>"android:required="true"</code> attribute, this
+subfeature implicitly declares the <code>android.hardware.sip</code>
+parent feature.</td>
+</tr>
 
 <tr>
   <td rowspan="3">Telephony</td>
@@ -622,14 +664,14 @@
 </tr>
 
 <tr>
-  <td rowspan="3">Touchscreen</td>
+  <td rowspan="4">Touchscreen</td>
   <td><code>android.hardware.touchscreen</code></td>
   <td>The application uses touchscreen capabilities on the device.</td>
   <td></td>
 </tr>
 <tr>
   <td><code>android.hardware.touchscreen.multitouch</code></td>
-  <td>The application uses basic two-point multitouch capabilities on the device
+  <td>Subfeature. The application uses basic two-point multitouch capabilities on the device
 screen.</td>
   <td>If declared with the <code>"android:required="true"</code> attribute, this
 subfeature implicitly declares the <code>android.hardware.touchscreen</code>
@@ -640,10 +682,16 @@
   <td>Subfeature. The application uses advanced multipoint multitouch
 capabilities on the device screen, such as for tracking two or more points fully
 independently.</td>
-  <td>If declared with the <code>"android:required="true"</code> attribute, this
+  <td rowspan="2">If declared with the <code>"android:required="true"</code> attribute, this
 subfeature implicitly declares the
 <code>android.hardware.touchscreen.multitouch</code> parent feature. </td>
 </tr>
+<tr>
+  <td><code>android.hardware.touchscreen.multitouch.jazzhand</code></td>
+  <td>Subfeature. The application uses advanced multipoint multitouch
+capabilities on the device screen, for tracking up to five points fully
+independently.</td>
+</tr>
 
 <tr>
   <td>Wifi</td>
diff --git a/include/ui/FramebufferNativeWindow.h b/include/ui/FramebufferNativeWindow.h
index c913355..2cd0911 100644
--- a/include/ui/FramebufferNativeWindow.h
+++ b/include/ui/FramebufferNativeWindow.h
@@ -29,6 +29,7 @@
 
 #include <ui/egl/android_natives.h>
 
+#define NUM_FRAME_BUFFERS  2
 
 extern "C" EGLNativeWindowType android_createDisplaySurface(void);
 
@@ -72,7 +73,7 @@
     framebuffer_device_t* fbDev;
     alloc_device_t* grDev;
 
-    sp<NativeBuffer> buffers[2];
+    sp<NativeBuffer> buffers[NUM_FRAME_BUFFERS];
     sp<NativeBuffer> front;
     
     mutable Mutex mutex;
diff --git a/libs/rs/java/Balls/src/com/android/balls/BallsRS.java b/libs/rs/java/Balls/src/com/android/balls/BallsRS.java
index 359f334..76c23b7 100644
--- a/libs/rs/java/Balls/src/com/android/balls/BallsRS.java
+++ b/libs/rs/java/Balls/src/com/android/balls/BallsRS.java
@@ -33,8 +33,6 @@
     private ProgramFragment mPFLines;
     private ProgramFragment mPFPoints;
     private ProgramVertex mPV;
-    private ProgramRaster mPR;
-    private ProgramStore mPS;
     private ScriptField_Point mPoints;
     private ScriptField_Point mArcs;
     private ScriptField_VpConsts mVpConsts;
@@ -48,12 +46,6 @@
         mVpConsts.set(i, 0, true);
     }
 
-    private void createProgramRaster() {
-        ProgramRaster.Builder b = new ProgramRaster.Builder(mRS);
-        mPR = b.create();
-        mScript.set_gPR(mPR);
-    }
-
     private void createProgramVertex() {
         updateProjectionMatrices();
 
@@ -71,7 +63,7 @@
         sb.addInput(mPoints.getElement());
         ProgramVertex pvs = sb.create();
         pvs.bindConstants(mVpConsts.getAllocation(), 0);
-        mScript.set_gPV(pvs);
+        mRS.contextBindProgramVertex(pvs);
     }
 
     private Allocation loadTexture(int id) {
@@ -125,10 +117,8 @@
         mScript.set_gPFLines(mPFLines);
         mScript.set_gPFPoints(mPFPoints);
         createProgramVertex();
-        createProgramRaster();
 
-        mPS = ProgramStore.BLEND_ADD_DEPTH_NO_DEPTH(mRS);
-        mScript.set_gPS(mPS);
+        mRS.contextBindProgramStore(ProgramStore.BLEND_ADD_DEPTH_NO_DEPTH(mRS));
 
         mPhysicsScript.set_gMinPos(new Float2(5, 5));
         mPhysicsScript.set_gMaxPos(new Float2(width - 5, height - 5));
diff --git a/libs/rs/java/Balls/src/com/android/balls/balls.rs b/libs/rs/java/Balls/src/com/android/balls/balls.rs
index bbd03cf..3edbe2d 100644
--- a/libs/rs/java/Balls/src/com/android/balls/balls.rs
+++ b/libs/rs/java/Balls/src/com/android/balls/balls.rs
@@ -4,13 +4,11 @@
 
 #include "balls.rsh"
 
-#pragma stateFragment(parent)
+#pragma stateVertex(parent)
+#pragma stateStore(parent)
 
 rs_program_fragment gPFPoints;
 rs_program_fragment gPFLines;
-rs_program_vertex gPV;
-rs_program_raster gPR;
-rs_program_store gPS;
 rs_mesh partMesh;
 rs_mesh arcMesh;
 
@@ -95,9 +93,6 @@
 
     frame++;
     rsgBindProgramFragment(gPFLines);
-    rsgBindProgramVertex(gPV);
-    rsgBindProgramRaster(gPR);
-    rsgBindProgramStore(gPS);
     rsgDrawMesh(arcMesh, 0, 0, arcIdx);
     rsgBindProgramFragment(gPFPoints);
     rsgDrawMesh(partMesh);
diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp
index 18bf9fa..143c4dc 100644
--- a/libs/rs/rsContext.cpp
+++ b/libs/rs/rsContext.cpp
@@ -262,21 +262,27 @@
     }
 }
 
+Context::PushState::PushState(Context *con) {
+    mRsc = con;
+    mFragment.set(con->getProgramFragment());
+    mVertex.set(con->getProgramVertex());
+    mStore.set(con->getProgramStore());
+    mRaster.set(con->getProgramRaster());
+}
+
+Context::PushState::~PushState() {
+    mRsc->setProgramFragment(mFragment.get());
+    mRsc->setProgramVertex(mVertex.get());
+    mRsc->setProgramStore(mStore.get());
+    mRsc->setProgramRaster(mRaster.get());
+    mRsc->setFont(mFont.get());
+}
+
 
 uint32_t Context::runScript(Script *s) {
-    ObjectBaseRef<ProgramFragment> frag(mFragment);
-    ObjectBaseRef<ProgramVertex> vtx(mVertex);
-    ObjectBaseRef<ProgramStore> store(mFragmentStore);
-    ObjectBaseRef<ProgramRaster> raster(mRaster);
-    ObjectBaseRef<Font> font(mFont);
+    PushState(this);
 
     uint32_t ret = s->run(this);
-
-    mFragment.set(frag);
-    mVertex.set(vtx);
-    mFragmentStore.set(store);
-    mRaster.set(raster);
-    mFont.set(font);
     return ret;
 }
 
@@ -441,13 +447,13 @@
      rsc->mScriptC.init(rsc);
      if (rsc->mIsGraphicsContext) {
          rsc->mStateRaster.init(rsc);
-         rsc->setRaster(NULL);
+         rsc->setProgramRaster(NULL);
          rsc->mStateVertex.init(rsc);
-         rsc->setVertex(NULL);
+         rsc->setProgramVertex(NULL);
          rsc->mStateFragment.init(rsc);
-         rsc->setFragment(NULL);
+         rsc->setProgramFragment(NULL);
          rsc->mStateFragmentStore.init(rsc);
-         rsc->setFragmentStore(NULL);
+         rsc->setProgramStore(NULL);
          rsc->mStateFont.init(rsc);
          rsc->setFont(NULL);
          rsc->mStateVertexArray.init(rsc);
@@ -753,7 +759,7 @@
     mRootScript.set(s);
 }
 
-void Context::setFragmentStore(ProgramStore *pfs) {
+void Context::setProgramStore(ProgramStore *pfs) {
     rsAssert(mIsGraphicsContext);
     if (pfs == NULL) {
         mFragmentStore.set(mStateFragmentStore.mDefault);
@@ -762,7 +768,7 @@
     }
 }
 
-void Context::setFragment(ProgramFragment *pf) {
+void Context::setProgramFragment(ProgramFragment *pf) {
     rsAssert(mIsGraphicsContext);
     if (pf == NULL) {
         mFragment.set(mStateFragment.mDefault);
@@ -771,7 +777,7 @@
     }
 }
 
-void Context::setRaster(ProgramRaster *pr) {
+void Context::setProgramRaster(ProgramRaster *pr) {
     rsAssert(mIsGraphicsContext);
     if (pr == NULL) {
         mRaster.set(mStateRaster.mDefault);
@@ -780,7 +786,7 @@
     }
 }
 
-void Context::setVertex(ProgramVertex *pv) {
+void Context::setProgramVertex(ProgramVertex *pv) {
     rsAssert(mIsGraphicsContext);
     if (pv == NULL) {
         mVertex.set(mStateVertex.mDefault);
@@ -951,22 +957,22 @@
 
 void rsi_ContextBindProgramStore(Context *rsc, RsProgramStore vpfs) {
     ProgramStore *pfs = static_cast<ProgramStore *>(vpfs);
-    rsc->setFragmentStore(pfs);
+    rsc->setProgramStore(pfs);
 }
 
 void rsi_ContextBindProgramFragment(Context *rsc, RsProgramFragment vpf) {
     ProgramFragment *pf = static_cast<ProgramFragment *>(vpf);
-    rsc->setFragment(pf);
+    rsc->setProgramFragment(pf);
 }
 
 void rsi_ContextBindProgramRaster(Context *rsc, RsProgramRaster vpr) {
     ProgramRaster *pr = static_cast<ProgramRaster *>(vpr);
-    rsc->setRaster(pr);
+    rsc->setProgramRaster(pr);
 }
 
 void rsi_ContextBindProgramVertex(Context *rsc, RsProgramVertex vpv) {
     ProgramVertex *pv = static_cast<ProgramVertex *>(vpv);
-    rsc->setVertex(pv);
+    rsc->setProgramVertex(pv);
 }
 
 void rsi_ContextBindFont(Context *rsc, RsFont vfont) {
diff --git a/libs/rs/rsContext.h b/libs/rs/rsContext.h
index 6945342d..c377c73 100644
--- a/libs/rs/rsContext.h
+++ b/libs/rs/rsContext.h
@@ -80,6 +80,21 @@
         Context * mContext;
         Script * mScript;
     };
+
+    class PushState {
+    public:
+        PushState(Context *);
+        ~PushState();
+
+    private:
+        ObjectBaseRef<ProgramFragment> mFragment;
+        ObjectBaseRef<ProgramVertex> mVertex;
+        ObjectBaseRef<ProgramStore> mStore;
+        ObjectBaseRef<ProgramRaster> mRaster;
+        ObjectBaseRef<Font> mFont;
+        Context *mRsc;
+    };
+
     ScriptTLSStruct *mTlsStruct;
     RsSurfaceConfig mUserSurfaceConfig;
 
@@ -101,18 +116,18 @@
 
     void swapBuffers();
     void setRootScript(Script *);
-    void setRaster(ProgramRaster *);
-    void setVertex(ProgramVertex *);
-    void setFragment(ProgramFragment *);
-    void setFragmentStore(ProgramStore *);
+    void setProgramRaster(ProgramRaster *);
+    void setProgramVertex(ProgramVertex *);
+    void setProgramFragment(ProgramFragment *);
+    void setProgramStore(ProgramStore *);
     void setFont(Font *);
 
     void updateSurface(void *sur);
 
-    const ProgramFragment * getFragment() {return mFragment.get();}
-    const ProgramStore * getFragmentStore() {return mFragmentStore.get();}
-    const ProgramRaster * getRaster() {return mRaster.get();}
-    const ProgramVertex * getVertex() {return mVertex.get();}
+    ProgramFragment * getProgramFragment() {return mFragment.get();}
+    ProgramStore * getProgramStore() {return mFragmentStore.get();}
+    ProgramRaster * getProgramRaster() {return mRaster.get();}
+    ProgramVertex * getProgramVertex() {return mVertex.get();}
     Font * getFont() {return mFont.get();}
 
     bool setupCheck();
diff --git a/libs/rs/rsFont.cpp b/libs/rs/rsFont.cpp
index 96e350d..e4d77b2 100644
--- a/libs/rs/rsFont.cpp
+++ b/libs/rs/rsFont.cpp
@@ -613,18 +613,12 @@
 }
 
 void FontState::issueDrawCommand() {
+    Context::PushState ps(mRSC);
 
-    ObjectBaseRef<const ProgramVertex> tmpV(mRSC->getVertex());
-    mRSC->setVertex(mRSC->getDefaultProgramVertex());
-
-    ObjectBaseRef<const ProgramRaster> tmpR(mRSC->getRaster());
-    mRSC->setRaster(mRSC->getDefaultProgramRaster());
-
-    ObjectBaseRef<const ProgramFragment> tmpF(mRSC->getFragment());
-    mRSC->setFragment(mFontShaderF.get());
-
-    ObjectBaseRef<const ProgramStore> tmpPS(mRSC->getFragmentStore());
-    mRSC->setFragmentStore(mFontProgramStore.get());
+    mRSC->setProgramVertex(mRSC->getDefaultProgramVertex());
+    mRSC->setProgramRaster(mRSC->getDefaultProgramRaster());
+    mRSC->setProgramFragment(mFontShaderF.get());
+    mRSC->setProgramStore(mFontProgramStore.get());
 
     if (mConstantsDirty) {
         mFontShaderFConstant->data(mRSC, &mConstants, sizeof(mConstants));
@@ -632,10 +626,6 @@
     }
 
     if (!mRSC->setupCheck()) {
-        mRSC->setVertex((ProgramVertex *)tmpV.get());
-        mRSC->setRaster((ProgramRaster *)tmpR.get());
-        mRSC->setFragment((ProgramFragment *)tmpF.get());
-        mRSC->setFragmentStore((ProgramStore *)tmpPS.get());
         return;
     }
 
@@ -651,12 +641,6 @@
     mIndexBuffer->uploadCheck(mRSC);
     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer->getBufferObjectID());
     glDrawElements(GL_TRIANGLES, mCurrentQuadIndex * 6, GL_UNSIGNED_SHORT, (uint16_t *)(0));
-
-    // Reset the state
-    mRSC->setVertex((ProgramVertex *)tmpV.get());
-    mRSC->setRaster((ProgramRaster *)tmpR.get());
-    mRSC->setFragment((ProgramFragment *)tmpF.get());
-    mRSC->setFragmentStore((ProgramStore *)tmpPS.get());
 }
 
 void FontState::appendMeshQuad(float x1, float y1, float z1,
diff --git a/libs/rs/rsScriptC.cpp b/libs/rs/rsScriptC.cpp
index 072cc168..ec7780e 100644
--- a/libs/rs/rsScriptC.cpp
+++ b/libs/rs/rsScriptC.cpp
@@ -104,16 +104,16 @@
 
 void ScriptC::setupGLState(Context *rsc) {
     if (mEnviroment.mFragmentStore.get()) {
-        rsc->setFragmentStore(mEnviroment.mFragmentStore.get());
+        rsc->setProgramStore(mEnviroment.mFragmentStore.get());
     }
     if (mEnviroment.mFragment.get()) {
-        rsc->setFragment(mEnviroment.mFragment.get());
+        rsc->setProgramFragment(mEnviroment.mFragment.get());
     }
     if (mEnviroment.mVertex.get()) {
-        rsc->setVertex(mEnviroment.mVertex.get());
+        rsc->setProgramVertex(mEnviroment.mVertex.get());
     }
     if (mEnviroment.mRaster.get()) {
-        rsc->setRaster(mEnviroment.mRaster.get());
+        rsc->setProgramRaster(mEnviroment.mRaster.get());
     }
 }
 
@@ -232,6 +232,7 @@
                          const RsScriptCall *sc) {
     MTLaunchStruct mtls;
     memset(&mtls, 0, sizeof(mtls));
+    Context::PushState ps(rsc);
 
     if (ain) {
         mtls.dimX = ain->getType()->getDimX();
diff --git a/libs/rs/rsScriptC_LibGL.cpp b/libs/rs/rsScriptC_LibGL.cpp
index ef1475c..0f84e4b 100644
--- a/libs/rs/rsScriptC_LibGL.cpp
+++ b/libs/rs/rsScriptC_LibGL.cpp
@@ -92,17 +92,17 @@
 
 static void SC_vpLoadProjectionMatrix(const rsc_Matrix *m) {
     GET_TLS();
-    rsc->getVertex()->setProjectionMatrix(rsc, m);
+    rsc->getProgramVertex()->setProjectionMatrix(rsc, m);
 }
 
 static void SC_vpLoadModelMatrix(const rsc_Matrix *m) {
     GET_TLS();
-    rsc->getVertex()->setModelviewMatrix(rsc, m);
+    rsc->getProgramVertex()->setModelviewMatrix(rsc, m);
 }
 
 static void SC_vpLoadTextureMatrix(const rsc_Matrix *m) {
     GET_TLS();
-    rsc->getVertex()->setTextureMatrix(rsc, m);
+    rsc->getProgramVertex()->setTextureMatrix(rsc, m);
 }
 
 static void SC_pfConstantColor(RsProgramFragment vpf, float r, float g, float b, float a) {
@@ -114,7 +114,7 @@
 
 static void SC_vpGetProjectionMatrix(rsc_Matrix *m) {
     GET_TLS();
-    rsc->getVertex()->getProjectionMatrix(rsc, m);
+    rsc->getProgramVertex()->getProjectionMatrix(rsc, m);
 }
 
 //////////////////////////////////////////////////////////////////////////////
@@ -165,8 +165,8 @@
 
 static void SC_drawSpriteScreenspace(float x, float y, float z, float w, float h) {
     GET_TLS();
-    ObjectBaseRef<const ProgramVertex> tmp(rsc->getVertex());
-    rsc->setVertex(rsc->getDefaultProgramVertex());
+    ObjectBaseRef<const ProgramVertex> tmp(rsc->getProgramVertex());
+    rsc->setProgramVertex(rsc->getDefaultProgramVertex());
     //rsc->setupCheck();
 
     //GLint crop[4] = {0, h, w, -h};
@@ -177,7 +177,7 @@
                 x+w, sh - y,     z,
                 x+w, sh - (y+h), z,
                 x,   sh - (y+h), z);
-    rsc->setVertex((ProgramVertex *)tmp.get());
+    rsc->setProgramVertex((ProgramVertex *)tmp.get());
 }
 /*
 static void SC_drawSprite(float x, float y, float z, float w, float h)
@@ -271,7 +271,7 @@
 
 static void SC_color(float r, float g, float b, float a) {
     GET_TLS();
-    ProgramFragment *pf = (ProgramFragment *)rsc->getFragment();
+    ProgramFragment *pf = (ProgramFragment *)rsc->getProgramFragment();
     pf->setConstantColor(rsc, r, g, b, a);
 }
 
diff --git a/libs/ui/FramebufferNativeWindow.cpp b/libs/ui/FramebufferNativeWindow.cpp
index a36d555..04a0195 100644
--- a/libs/ui/FramebufferNativeWindow.cpp
+++ b/libs/ui/FramebufferNativeWindow.cpp
@@ -83,6 +83,7 @@
     if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) {
         int stride;
         int err;
+        int i;
         err = framebuffer_open(module, &fbDev);
         LOGE_IF(err, "couldn't open framebuffer HAL (%s)", strerror(-err));
         
@@ -96,27 +97,33 @@
         mUpdateOnDemand = (fbDev->setUpdateRect != 0);
         
         // initialize the buffer FIFO
-        mNumBuffers = 2;
-        mNumFreeBuffers = 2;
+        mNumBuffers = NUM_FRAME_BUFFERS;
+        mNumFreeBuffers = NUM_FRAME_BUFFERS;
         mBufferHead = mNumBuffers-1;
-        buffers[0] = new NativeBuffer(
-                fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB);
-        buffers[1] = new NativeBuffer(
-                fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB);
-        
-        err = grDev->alloc(grDev,
-                fbDev->width, fbDev->height, fbDev->format, 
-                GRALLOC_USAGE_HW_FB, &buffers[0]->handle, &buffers[0]->stride);
 
-        LOGE_IF(err, "fb buffer 0 allocation failed w=%d, h=%d, err=%s",
-                fbDev->width, fbDev->height, strerror(-err));
+        for (i = 0; i < mNumBuffers; i++)
+        {
+                buffers[i] = new NativeBuffer(
+                        fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB);
+        }
 
-        err = grDev->alloc(grDev,
-                fbDev->width, fbDev->height, fbDev->format, 
-                GRALLOC_USAGE_HW_FB, &buffers[1]->handle, &buffers[1]->stride);
+        for (i = 0; i < mNumBuffers; i++)
+        {
+                err = grDev->alloc(grDev,
+                        fbDev->width, fbDev->height, fbDev->format,
+                        GRALLOC_USAGE_HW_FB, &buffers[i]->handle, &buffers[i]->stride);
 
-        LOGE_IF(err, "fb buffer 1 allocation failed w=%d, h=%d, err=%s",
-                fbDev->width, fbDev->height, strerror(-err));
+                LOGE_IF(err, "fb buffer %d allocation failed w=%d, h=%d, err=%s",
+                        i, fbDev->width, fbDev->height, strerror(-err));
+
+                if (err)
+                {
+                        mNumBuffers = i;
+                        mNumFreeBuffers = i;
+                        mBufferHead = mNumBuffers-1;
+                        break;
+                }
+        }
 
         const_cast<uint32_t&>(ANativeWindow::flags) = fbDev->flags; 
         const_cast<float&>(ANativeWindow::xdpi) = fbDev->xdpi;
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index 2bea84f..39c4a28 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -149,12 +149,10 @@
          *  {@link #DEFAULT} otherwise. */
         public static final int VOICE_RECOGNITION = 6;
 
-        /**
-         * @hide
-         * Microphone audio source tuned for voice communications such as VoIP. It
-         * will for instance take advantage of echo cancellation or automatic gain control
-         * if available. It otherwise behaves like {@link #DEFAULT} if no voice processing
-         * is available.
+        /** Microphone audio source tuned for voice communications such as VoIP. It
+         *  will for instance take advantage of echo cancellation or automatic gain control
+         *  if available. It otherwise behaves like {@link #DEFAULT} if no voice processing
+         *  is applied.
          */
         public static final int VOICE_COMMUNICATION = 7;
     }
diff --git a/media/java/android/media/MtpDatabase.java b/media/java/android/media/MtpDatabase.java
index 42d068f..e48e9e8 100644
--- a/media/java/android/media/MtpDatabase.java
+++ b/media/java/android/media/MtpDatabase.java
@@ -164,7 +164,7 @@
         }
     }
 
-    private void endSendObject(String path, int handle, int format, boolean succeeded) {
+    private void endSendObject(String path, int handle, int format, long actualSize, boolean succeeded) {
         if (succeeded) {
             // handle abstract playlists separately
             // they do not exist in the file system so don't use the media scanner here
@@ -184,6 +184,7 @@
                 ContentValues values = new ContentValues(1);
                 values.put(Audio.Playlists.DATA, path);
                 values.put(Audio.Playlists.NAME, name);
+                values.put(Files.FileColumns.FORMAT, format);
                 values.put(MediaColumns.MEDIA_SCANNER_NEW_OBJECT_ID, handle);
                 try {
                     Uri uri = mMediaProvider.insert(Audio.Playlists.EXTERNAL_CONTENT_URI, values);
@@ -191,6 +192,18 @@
                     Log.e(TAG, "RemoteException in endSendObject", e);
                 }
             } else {
+                if (actualSize >= 0) {
+                    // update size if necessary
+                    ContentValues values = new ContentValues();
+                    values.put(Files.FileColumns.SIZE, actualSize);
+                    try {
+                        String[] whereArgs = new String[] {  Integer.toString(handle) };
+                        mMediaProvider.update(mObjectsUri, values, ID_WHERE, whereArgs);
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "RemoteException in mMediaProvider.update", e);
+                    }
+                }
+
                 mMediaScanner.scanMtpFile(path, mVolumeName, handle, format);
             }
         } else {
diff --git a/media/java/android/media/videoeditor/AudioTrack.java b/media/java/android/media/videoeditor/AudioTrack.java
index d02709e..32ff553 100755
--- a/media/java/android/media/videoeditor/AudioTrack.java
+++ b/media/java/android/media/videoeditor/AudioTrack.java
@@ -102,7 +102,7 @@
         // Ducking is enabled by default

         mDuckingThreshold = 0;

         mDuckedTrackVolume = 0;

-        mIsDuckingEnabled = true;

+        mIsDuckingEnabled = false;

 

         // The audio waveform file is generated later

         mAudioWaveformFilename = null;

@@ -369,14 +369,15 @@
     /**

      * Enable ducking by specifying the required parameters

      *

-     * @param threshold Ducking will be activated when the relative energy in

+     * @param threshold Ducking will be activated when the energy in

      *      the media items audio signal goes above this value. The valid

-     *      range of values is 0 to 100.

+     *      range of values is 0db to 90dB. 0dB is equivalent to disabling

+     *      ducking.

      * @param duckedTrackVolume The relative volume of the audio track when ducking

      *      is active. The valid range of values is 0 to 100.

      */

     public void enableDucking(int threshold, int duckedTrackVolume) {

-        if (threshold < 0 || threshold > 100) {

+        if (threshold < 0 || threshold > 90) {

             throw new IllegalArgumentException("Invalid threshold value: " + threshold);

         }

 

diff --git a/media/jni/android_media_MtpDatabase.cpp b/media/jni/android_media_MtpDatabase.cpp
index 5377af6..4525d1f 100644
--- a/media/jni/android_media_MtpDatabase.cpp
+++ b/media/jni/android_media_MtpDatabase.cpp
@@ -99,6 +99,7 @@
     virtual void                    endSendObject(const char* path,
                                             MtpObjectHandle handle,
                                             MtpObjectFormat format,
+                                            int64_t actualSize,
                                             bool succeeded);
 
     virtual MtpObjectHandleList*    getObjectList(MtpStorageID storageID,
@@ -235,11 +236,11 @@
 }
 
 void MyMtpDatabase::endSendObject(const char* path, MtpObjectHandle handle,
-                                MtpObjectFormat format, bool succeeded) {
+                                MtpObjectFormat format, int64_t actualSize, bool succeeded) {
     JNIEnv* env = AndroidRuntime::getJNIEnv();
     jstring pathStr = env->NewStringUTF(path);
     env->CallVoidMethod(mDatabase, method_endSendObject, pathStr,
-                        (jint)handle, (jint)format, (jboolean)succeeded);
+                        (jint)handle, (jint)format, (jlong)actualSize, (jboolean)succeeded);
 
     if (pathStr)
         env->DeleteLocalRef(pathStr);
@@ -1076,7 +1077,7 @@
         LOGE("Can't find beginSendObject");
         return -1;
     }
-    method_endSendObject = env->GetMethodID(clazz, "endSendObject", "(Ljava/lang/String;IIZ)V");
+    method_endSendObject = env->GetMethodID(clazz, "endSendObject", "(Ljava/lang/String;IIJZ)V");
     if (method_endSendObject == NULL) {
         LOGE("Can't find endSendObject");
         return -1;
diff --git a/media/mtp/MtpDatabase.h b/media/mtp/MtpDatabase.h
index fafd221..900b517 100644
--- a/media/mtp/MtpDatabase.h
+++ b/media/mtp/MtpDatabase.h
@@ -42,6 +42,7 @@
     virtual void                    endSendObject(const char* path,
                                             MtpObjectHandle handle,
                                             MtpObjectFormat format,
+                                            int64_t size,
                                             bool succeeded) = 0;
 
     virtual MtpObjectHandleList*    getObjectList(MtpStorageID storageID,
diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp
index 6cf70ec..ca13636 100644
--- a/media/mtp/MtpServer.cpp
+++ b/media/mtp/MtpServer.cpp
@@ -624,6 +624,7 @@
     mData.getString(modified);     // date modified
     // keywords follow
 
+    LOGD("name: %s format: %04X\n", (const char *)name, format);
     time_t modifiedTime;
     if (!parseDateTime(modified, modifiedTime))
         modifiedTime = 0;
@@ -663,6 +664,7 @@
     MtpResponseCode result = MTP_RESPONSE_OK;
     mode_t mask;
     int ret;
+    uint64_t actualSize = -1;
 
     if (mSendObjectHandle == kInvalidObjectHandle) {
         LOGE("Expected SendObjectInfo before SendObject");
@@ -692,6 +694,7 @@
     mfr.offset = 0;
     mfr.length = mSendObjectFileSize;
 
+    LOGD("receiving %s\n", (const char *)mSendObjectFilePath);
     // transfer the file
     ret = ioctl(mFD, MTP_RECEIVE_FILE, (unsigned long)&mfr);
     close(mfr.fd);
@@ -704,11 +707,18 @@
             result = MTP_RESPONSE_TRANSACTION_CANCELLED;
         else
             result = MTP_RESPONSE_GENERAL_ERROR;
+    } else if (mSendObjectFileSize == 0xFFFFFFFF) {
+        // actual size is likely > 4 gig so stat the file to compute actual length
+        struct stat s;
+        if (lstat(mSendObjectFilePath, &s) == 0) {
+            actualSize = s.st_size;
+            LOGD("actualSize: %lld\n", actualSize);
+        }
     }
 
 done:
     mDatabase->endSendObject(mSendObjectFilePath, mSendObjectHandle, mSendObjectFormat,
-            result == MTP_RESPONSE_OK);
+            actualSize, result == MTP_RESPONSE_OK);
     mSendObjectHandle = kInvalidObjectHandle;
     mSendObjectFormat = 0;
     return result;
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_shadow.9.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_shadow.9.png
new file mode 100644
index 0000000..c888c21
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_shadow.9.png
Binary files differ
diff --git a/packages/SystemUI/res/layout-xlarge/status_bar.xml b/packages/SystemUI/res/layout-xlarge/status_bar.xml
index 8f2bea4..ddb5bb9 100644
--- a/packages/SystemUI/res/layout-xlarge/status_bar.xml
+++ b/packages/SystemUI/res/layout-xlarge/status_bar.xml
@@ -25,9 +25,10 @@
         android:id="@+id/bar_contents"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:animateLayoutChanges="true"
+        android:animateLayoutChanges="false"
         >
 
+        <!-- ticker: transient incoming notification information -->
         <FrameLayout
             android:id="@+id/ticker"
             android:layout_width="wrap_content"
@@ -39,6 +40,7 @@
             android:animateLayoutChanges="true"
             />
 
+        <!-- notification icons & panel access -->
         <LinearLayout
             android:id="@+id/notificationArea"
             android:layout_width="wrap_content"
@@ -65,7 +67,7 @@
             <LinearLayout
                 android:id="@+id/notificationTrigger"
                 android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
+                android:layout_height="match_parent"
                 >
                 <!-- paddingLeft: 24 dips = 32dp (total space to icon) - 8dp in the icon.
                 TODO: Make sure the font has a small enough leading that we don't need this
@@ -81,62 +83,70 @@
                     android:paddingLeft="24dip"
                     android:textColor="#2e2e2e"
                     />
-                <ImageView
-                    android:id="@+id/battery"
-                    android:layout_height="wrap_content"
-                    android:layout_width="wrap_content"
-                    android:layout_gravity="center_vertical"
-                    />
-                <ImageView
-                    android:id="@+id/network"
-                    android:layout_height="wrap_content"
-                    android:layout_width="wrap_content"
-                    android:layout_gravity="center_vertical"
-                    android:src="@drawable/ic_sysbar_wifi_mini"
-                    />
+                <LinearLayout
+                    android:layout_width="48dip"
+                    android:layout_height="match_parent"
+                    android:orientation="horizontal"
+                    >
+                    <ImageView
+                        android:id="@+id/battery"
+                        android:layout_height="wrap_content"
+                        android:layout_width="wrap_content"
+                        android:layout_gravity="center_vertical"
+                        />
+                    <ImageView
+                        android:id="@+id/network"
+                        android:layout_height="wrap_content"
+                        android:layout_width="wrap_content"
+                        android:layout_gravity="center_vertical"
+                        android:src="@drawable/ic_sysbar_wifi_mini"
+                        />
+                </LinearLayout>
             </LinearLayout>
         </LinearLayout>
 
+        <!-- navigation controls -->
         <LinearLayout
             android:id="@+id/navigationArea"
             android:layout_width="wrap_content"
             android:layout_height="match_parent"
             android:layout_alignParentLeft="true"
             android:orientation="horizontal"
-            android:animateLayoutChanges="true"
+            android:animateLayoutChanges="false"
             >
 
             <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/back"
-                android:layout_width="wrap_content"
+                android:layout_width="96dip"
                 android:layout_height="match_parent"
-                android:paddingLeft="15dip"
-                android:paddingRight="15dip"
+                android:paddingLeft="18dip"
+                android:paddingRight="18dip"
                 android:src="@drawable/ic_sysbar_back"
                 android:background="@drawable/ic_sysbar_icon_bg"
                 systemui:keyCode="4"
                 />
             <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/home"
-                android:layout_width="wrap_content"
+                android:layout_width="96dip"
                 android:layout_height="match_parent"
-                android:paddingLeft="15dip"
-                android:paddingRight="15dip"
+                android:paddingLeft="18dip"
+                android:paddingRight="18dip"
                 android:src="@drawable/ic_sysbar_home"
                 android:background="@drawable/ic_sysbar_icon_bg"
                 systemui:keyCode="3"
                 />
             <ImageButton android:id="@+id/recent_apps"
-                android:layout_width="wrap_content"
+                android:layout_width="96dip"
                 android:layout_height="match_parent"
                 android:src="@drawable/ic_sysbar_recent"
                 android:background="@drawable/ic_sysbar_icon_bg"
-                android:paddingLeft="15dip"
-                android:paddingRight="15dip"
+                android:paddingLeft="18dip"
+                android:clickable="true"
+                android:paddingRight="18dip"
                 />
             <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/menu"
-                android:layout_width="wrap_content"
+                android:layout_width="96dip"
                 android:layout_height="match_parent"
-                android:paddingLeft="15dip"
-                android:paddingRight="15dip"
+                android:paddingLeft="18dip"
+                android:paddingRight="18dip"
                 android:src="@drawable/ic_sysbar_menu"
                 android:background="@drawable/ic_sysbar_icon_bg"
                 systemui:keyCode="82"
@@ -144,11 +154,11 @@
                 />
             <com.android.systemui.statusbar.tablet.ShirtPocket
                 android:id="@+id/pocket"
-                android:layout_width="71dip"
+                android:layout_width="96dip"
                 android:layout_height="match_parent"
                 android:background="@drawable/ic_sysbar_icon_bg"
-                android:paddingLeft="15dip"
-                android:paddingRight="15dip"
+                android:paddingLeft="18dip"
+                android:paddingRight="18dip"
                 android:animateLayoutChanges="true"
                 android:clickable="true"
                 android:descendantFocusability="blocksDescendants"
@@ -173,18 +183,64 @@
                 android:visibility="invisible"
                 />
         </LinearLayout>
+
+        <!-- lights out mode: "shadow" views -->
+        <ImageView
+            android:id="@+id/notification_shadow"
+            android:layout_width="176dip"
+            android:layout_height="match_parent"
+            android:paddingRight="48dip"
+            android:layout_alignParentRight="true"
+            android:layout_alignParentBottom="true"
+            android:src="@drawable/ic_sysbar_shadow"
+            android:visibility="gone"
+            android:scaleType="fitXY"
+            />
+
+        <ImageView
+            android:id="@+id/back_shadow"
+            android:layout_width="96dip"
+            android:layout_height="match_parent"
+            android:paddingLeft="18dip"
+            android:paddingRight="18dip"
+            android:layout_alignParentLeft="true"
+            android:layout_alignParentBottom="true"
+            android:src="@drawable/ic_sysbar_shadow"
+            android:visibility="gone"
+            />
+        <ImageView
+            android:id="@+id/home_shadow"
+            android:layout_width="96dip"
+            android:layout_height="match_parent"
+            android:paddingLeft="18dip"
+            android:paddingRight="18dip"
+            android:layout_toRightOf="@id/back_shadow"
+            android:layout_alignParentBottom="true"
+            android:src="@drawable/ic_sysbar_shadow"
+            android:visibility="gone"
+            />
+        <ImageView
+            android:id="@+id/recent_shadow"
+            android:layout_width="96dip"
+            android:layout_height="match_parent"
+            android:paddingLeft="18dip"
+            android:paddingRight="18dip"
+            android:layout_toRightOf="@id/home_shadow"
+            android:layout_alignParentBottom="true"
+            android:src="@drawable/ic_sysbar_shadow"
+            android:visibility="gone"
+            />
+        <ImageView
+            android:id="@+id/menu_shadow"
+            android:layout_width="96dip"
+            android:layout_height="match_parent"
+            android:paddingLeft="18dip"
+            android:paddingRight="18dip"
+            android:layout_toRightOf="@id/recent_shadow"
+            android:layout_alignParentBottom="true"
+            android:src="@drawable/ic_sysbar_shadow"
+            android:visibility="gone"
+            />
+
     </RelativeLayout>
-
-    <!-- It's curtains for you. -->
-    <ImageView
-        android:id="@+id/lights_out"
-        android:src="@drawable/ic_sysbar_lightsout"
-        android:gravity="center"
-        android:background="#FF000000"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:visibility="invisible"
-        android:clickable="true"
-        />
 </com.android.systemui.statusbar.tablet.TabletStatusBarView>
-
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
index 0531f9d..1f4c9d1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -75,12 +75,15 @@
     public static final int MSG_CLOSE_NOTIFICATION_PEEK = 1003;
     public static final int MSG_OPEN_RECENTS_PANEL = 1020;
     public static final int MSG_CLOSE_RECENTS_PANEL = 1021;
-    public static final int MSG_LIGHTS_ON = 1030;
-    public static final int MSG_LIGHTS_OUT = 1031;
+    public static final int MSG_HIDE_SHADOWS = 1030;
+    public static final int MSG_SHOW_SHADOWS = 1031;
+    public static final int MSG_SHOW_SHADOWS_NO_COLLAPSE = 1032;
 
     private static final int MAX_IMAGE_LEVEL = 10000;
     private static final boolean USE_2D_RECENTS = true;
 
+    public static final int LIGHTS_ON_DELAY = 5000;
+
     int mIconSize;
 
     H mHandler = new H();
@@ -93,6 +96,9 @@
     View mNotificationTrigger;
     NotificationIconArea mNotificationIconArea;
     View mNavigationArea;
+
+    View mBackButton;
+    View mHomeButton;
     View mMenuButton;
     View mRecentButton;
 
@@ -113,7 +119,10 @@
     NetworkController mNetworkController;
 
     View mBarContents;
-    View mCurtains;
+
+    // lights out support
+    View mBackShadow, mHomeShadow, mRecentShadow, mMenuShadow, mNotificationShadow;
+    ShadowController mShadowController;
 
     NotificationIconArea.IconLayout mIconLayout;
 
@@ -245,14 +254,21 @@
         sb.setHandler(mHandler);
 
         mBarContents = sb.findViewById(R.id.bar_contents);
-        mCurtains = sb.findViewById(R.id.lights_out);
 
-        mRecentButton = sb.findViewById(R.id.recent_apps);
-        mRecentButton.setOnClickListener(mOnClickListener);
+        // "shadows" of the status bar features, for lights-out mode
+        mBackShadow = sb.findViewById(R.id.back_shadow);
+        mHomeShadow = sb.findViewById(R.id.home_shadow);
+        mRecentShadow = sb.findViewById(R.id.recent_shadow);
+        mMenuShadow = sb.findViewById(R.id.menu_shadow);
+        mNotificationShadow = sb.findViewById(R.id.notification_shadow);
 
-        SetLightsOnListener on = new SetLightsOnListener(true);
-        mCurtains.setOnClickListener(on);
-        mCurtains.setOnLongClickListener(on);
+        mShadowController = new ShadowController(false);
+
+        mBackShadow.setOnTouchListener(mShadowController.makeTouchListener());
+        mHomeShadow.setOnTouchListener(mShadowController.makeTouchListener());
+        mRecentShadow.setOnTouchListener(mShadowController.makeTouchListener());
+        mMenuShadow.setOnTouchListener(mShadowController.makeTouchListener());
+        mNotificationShadow.setOnTouchListener(mShadowController.makeTouchListener());
 
         // the whole right-hand side of the bar
         mNotificationArea = sb.findViewById(R.id.notificationArea);
@@ -282,10 +298,15 @@
 
         // The navigation buttons
         mNavigationArea = sb.findViewById(R.id.navigationArea);
+        mBackButton = mNavigationArea.findViewById(R.id.back);
+        mHomeButton = mNavigationArea.findViewById(R.id.home);
         mMenuButton = mNavigationArea.findViewById(R.id.menu);
+        mRecentButton = mNavigationArea.findViewById(R.id.recent_apps);
+        Slog.d(TAG, "rec=" + mRecentButton + ", listener=" + mOnClickListener);
+        mRecentButton.setOnClickListener(mOnClickListener);
 
         // The bar contents buttons
-        mInputMethodButton = (InputMethodButton) mBarContents.findViewById(R.id.imeButton);
+        mInputMethodButton = (InputMethodButton) sb.findViewById(R.id.imeButton);
 
         // set the initial view visibility
         setAreThereNotifications();
@@ -362,6 +383,8 @@
                         mNotificationPeekWindow.setVisibility(View.GONE);
 
                         mNotificationPanel.setVisibility(View.VISIBLE);
+
+                        // XXX: need to synchronize with shadows here
                         mNotificationArea.setVisibility(View.GONE);
                     }
                     break;
@@ -369,6 +392,8 @@
                     if (DEBUG) Slog.d(TAG, "closing notifications panel");
                     if (mNotificationPanel.getVisibility() == View.VISIBLE) {
                         mNotificationPanel.setVisibility(View.GONE);
+
+                        // XXX: need to synchronize with shadows here
                         mNotificationArea.setVisibility(View.VISIBLE);
                     }
                     break;
@@ -380,14 +405,14 @@
                     if (DEBUG) Slog.d(TAG, "closing recents panel");
                     if (mRecentsPanel != null) mRecentsPanel.setVisibility(View.GONE);
                     break;
-                case MSG_LIGHTS_ON:
-                    setViewVisibility(mCurtains, View.GONE, R.anim.lights_out_out);
-                    setViewVisibility(mBarContents, View.VISIBLE, R.anim.status_bar_in);
+                case MSG_HIDE_SHADOWS:
+                    mShadowController.hideAllShadows();
                     break;
-                case MSG_LIGHTS_OUT:
+                case MSG_SHOW_SHADOWS:
                     animateCollapse();
-                    setViewVisibility(mCurtains, View.VISIBLE, R.anim.lights_out_in);
-                    setViewVisibility(mBarContents, View.GONE, R.anim.status_bar_out);
+                    // fall through
+                case MSG_SHOW_SHADOWS_NO_COLLAPSE:
+                    mShadowController.showAllShadows();
                     break;
             }
         }
@@ -605,16 +630,16 @@
     // called by StatusBar
     @Override
     public void setLightsOn(boolean on) {
-        mHandler.removeMessages(MSG_LIGHTS_OUT);
-        mHandler.removeMessages(MSG_LIGHTS_ON);
-        mHandler.sendEmptyMessage(on ? MSG_LIGHTS_ON : MSG_LIGHTS_OUT);
+        mHandler.removeMessages(MSG_SHOW_SHADOWS);
+        mHandler.removeMessages(MSG_HIDE_SHADOWS);
+        mHandler.sendEmptyMessage(on ? MSG_HIDE_SHADOWS : MSG_SHOW_SHADOWS);
     }
 
     public void setMenuKeyVisible(boolean visible) {
         if (DEBUG) {
             Slog.d(TAG, (visible?"showing":"hiding") + " the MENU button");
         }
-        mMenuButton.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
+        mMenuButton.setVisibility(visible ? View.VISIBLE : View.GONE);
     }
 
     public void setIMEButtonVisible(boolean visible) {
@@ -664,7 +689,7 @@
     };
 
     public void onClickNotificationTrigger() {
-        if (DEBUG) Slog.d(TAG, "clicked notification icons");
+        if (DEBUG) Slog.d(TAG, "clicked notification icons; disabled=" + mDisabled);
         if ((mDisabled & StatusBarManager.DISABLE_EXPAND) == 0) {
             if (!mNotificationsOn) {
                 mNotificationsOn = true;
@@ -681,7 +706,7 @@
     }
 
     public void onClickRecentButton() {
-        if (DEBUG) Slog.d(TAG, "clicked recent apps");
+        if (DEBUG) Slog.d(TAG, "clicked recent apps; disabled=" + mDisabled);
         if (mRecentsPanel == null) {
             Intent intent = new Intent();
             intent.setClass(mContext, RecentApplicationsActivity.class);
@@ -1006,23 +1031,108 @@
         return true;
     }
 
-    public class SetLightsOnListener implements View.OnLongClickListener,
-           View.OnClickListener {
-        private boolean mOn;
+    public class ShadowController {
+        boolean mShowShadows;
+        View mTouchTarget;
 
-        SetLightsOnListener(boolean on) {
-            mOn = on;
+        ShadowController(boolean showShadows) {
+            mShowShadows = showShadows;
+            mTouchTarget = null;
         }
 
-        public void onClick(View v) {
-            setLightsOn(mOn);
+        public boolean getShadowState() {
+            return mShowShadows;
         }
 
-        public boolean onLongClick(View v) {
-            setLightsOn(mOn);
-            return true;
+        public View.OnTouchListener makeTouchListener() {
+            return new View.OnTouchListener() {
+                public boolean onTouch(View v, MotionEvent ev) {
+                    final int action = ev.getAction();
+
+                    if (DEBUG) Slog.d(TAG, "ShadowController: v=" + v + ", ev=" + ev);
+
+                    // currently redirecting events?
+                    if (mTouchTarget == null) {
+                        if (v == mBackShadow) {
+                            mTouchTarget = mBackButton;
+                        } else if (v == mHomeShadow) {
+                            mTouchTarget = mHomeButton;
+                        } else if (v == mMenuShadow) {
+                            mTouchTarget = mMenuButton;
+                        } else if (v == mRecentShadow) {
+                            mTouchTarget = mRecentButton;
+                        } else if (v == mNotificationShadow) {
+                            mTouchTarget = mNotificationArea;
+                        }
+                    }
+
+                    if (mTouchTarget != null && mTouchTarget.getVisibility() != View.GONE) {
+                        boolean last = false;
+                        switch (action) {
+                            case MotionEvent.ACTION_CANCEL:
+                            case MotionEvent.ACTION_UP:
+                                mHandler.removeMessages(MSG_SHOW_SHADOWS_NO_COLLAPSE);
+                                if (mShowShadows) {
+                                    mHandler.sendEmptyMessageDelayed(MSG_SHOW_SHADOWS_NO_COLLAPSE, 
+                                            v == mNotificationShadow ? 5000 : 500);
+                                }
+                                last = true;
+                                break;
+                            case MotionEvent.ACTION_DOWN:
+                                mHandler.removeMessages(MSG_SHOW_SHADOWS_NO_COLLAPSE);
+                                setShadowForButton(mTouchTarget, false);
+                                break;
+                        }
+                        mTouchTarget.dispatchTouchEvent(ev);
+                        if (last) mTouchTarget = null;
+                        return true;
+                    }
+
+                    return false;
+                }
+            };
         }
 
+        public void showAllShadows() {
+            mShowShadows = true;
+            setShadowForButton(mBackButton, true);
+            setShadowForButton(mHomeButton, true);
+            setShadowForButton(mRecentButton, true);
+            setShadowForButton(mMenuButton, true);
+            setShadowForButton(mNotificationArea, true);
+        }
+
+        public void hideAllShadows() {
+            mShowShadows = false;
+            setShadowForButton(mBackButton, false);
+            setShadowForButton(mHomeButton, false);
+            setShadowForButton(mRecentButton, false);
+            setShadowForButton(mMenuButton, false);
+            setShadowForButton(mNotificationArea, false);
+        }
+
+        // Use View.INVISIBLE for things hidden due to shadowing, and View.GONE for things that are
+        // disabled (and should not be shadowed or re-shown)
+        public void setShadowForButton(View button, boolean shade) {
+            View shadow = null;
+            if (button == mBackButton) {
+                shadow = mBackShadow;
+            } else if (button == mHomeButton) {
+                shadow = mHomeShadow;
+            } else if (button == mMenuButton) {
+                shadow = mMenuShadow;
+            } else if (button == mRecentButton) {
+                shadow = mRecentShadow;
+            } else if (button == mNotificationArea) {
+                shadow = mNotificationShadow;
+            }
+            if (shadow != null) {
+                if (button.getVisibility() != View.GONE) {
+                    shadow.setVisibility(shade ? View.VISIBLE : View.INVISIBLE);
+                    button.setVisibility(shade ? View.INVISIBLE : View.VISIBLE);
+                }
+            }
+        }
     }
 
     public class TouchOutsideListener implements View.OnTouchListener {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarView.java
index bd8266a..823b793 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarView.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.os.Handler;
 import android.util.AttributeSet;
+import android.util.Slog;
 import android.view.View;
 import android.view.MotionEvent;
 import android.widget.FrameLayout;
@@ -40,6 +41,9 @@
 
     public boolean onInterceptTouchEvent(MotionEvent ev) {
         if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+            if (TabletStatusBar.DEBUG) {
+                Slog.d(TabletStatusBar.TAG, "TabletStatusBarView intercepting touch event: " + ev);
+            }
             mHandler.removeMessages(TabletStatusBar.MSG_CLOSE_NOTIFICATION_PANEL);
             mHandler.sendEmptyMessage(TabletStatusBar.MSG_CLOSE_NOTIFICATION_PANEL);
             mHandler.removeMessages(TabletStatusBar.MSG_CLOSE_RECENTS_PANEL);
@@ -48,6 +52,9 @@
             for (int i=0; i < mPanels.length; i++) {
                 if (mPanels[i] != null && mPanels[i].getVisibility() == View.VISIBLE) {
                     if (eventInside(mIgnoreChildren[i], ev)) {
+                        if (TabletStatusBar.DEBUG) {
+                            Slog.d(TabletStatusBar.TAG, "TabletStatusBarView eating event for view: " + mIgnoreChildren[i]);
+                        }
                         return true;
                     }
                 }
diff --git a/policy/src/com/android/internal/policy/impl/SimUnlockScreen.java b/policy/src/com/android/internal/policy/impl/SimUnlockScreen.java
index 5518e11..486e7aa 100644
--- a/policy/src/com/android/internal/policy/impl/SimUnlockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/SimUnlockScreen.java
@@ -130,9 +130,10 @@
 
     /** {@inheritDoc} */
     public void cleanUp() {
-        // hide the dialog.
+        // dismiss the dialog.
         if (mSimUnlockProgressDialog != null) {
-            mSimUnlockProgressDialog.hide();
+            mSimUnlockProgressDialog.dismiss();
+            mSimUnlockProgressDialog = null;
         }
         mUpdateMonitor.removeCallback(this);
     }
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index 8d25d50..84bc100 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -557,6 +557,9 @@
 
     public List<InputMethodSubtype> getEnabledInputMethodSubtypeList(InputMethodInfo imi) {
         synchronized (mMethodMap) {
+            if (imi == null && mCurMethodId != null) {
+                imi = mMethodMap.get(mCurMethodId);
+            }
             return mSettings.getEnabledInputMethodSubtypeListLocked(imi);
         }
     }
@@ -2043,18 +2046,20 @@
                     getEnabledInputMethodsAndSubtypeListLocked();
             ArrayList<InputMethodSubtype> enabledSubtypes =
                     new ArrayList<InputMethodSubtype>();
-            for (Pair<String, ArrayList<String>> imsPair : imsList) {
-                InputMethodInfo info = mMethodMap.get(imsPair.first);
-                if (info != null && info.getId().equals(imi.getId())) {
-                    ArrayList<InputMethodSubtype> subtypes = info.getSubtypes();
-                    for (InputMethodSubtype ims: subtypes) {
-                        for (String s: imsPair.second) {
-                            if (String.valueOf(ims.hashCode()).equals(s)) {
-                                enabledSubtypes.add(ims);
+            if (imi != null) {
+                for (Pair<String, ArrayList<String>> imsPair : imsList) {
+                    InputMethodInfo info = mMethodMap.get(imsPair.first);
+                    if (info != null && info.getId().equals(imi.getId())) {
+                        ArrayList<InputMethodSubtype> subtypes = info.getSubtypes();
+                        for (InputMethodSubtype ims: subtypes) {
+                            for (String s: imsPair.second) {
+                                if (String.valueOf(ims.hashCode()).equals(s)) {
+                                    enabledSubtypes.add(ims);
+                                }
                             }
                         }
+                        break;
                     }
-                    break;
                 }
             }
             return enabledSubtypes;
diff --git a/telephony/java/com/android/internal/telephony/CallManager.java b/telephony/java/com/android/internal/telephony/CallManager.java
index d74a547..5b49305 100644
--- a/telephony/java/com/android/internal/telephony/CallManager.java
+++ b/telephony/java/com/android/internal/telephony/CallManager.java
@@ -380,12 +380,17 @@
                 break;
             case OFFHOOK:
                 Phone fgPhone = getFgPhone();
-                // Enable IN_CALL mode while foreground call is in DIALING,
-                // ALERTING, ACTIVE and DISCONNECTING state and not from sipPhone
+                // While foreground call is in DIALING,
+                // ALERTING, ACTIVE and DISCONNECTING state
                 if (getActiveFgCallState() != Call.State.IDLE
-                        && getActiveFgCallState() != Call.State.DISCONNECTED
-                        && !(fgPhone instanceof SipPhone)) {
-                    mode = AudioManager.MODE_IN_CALL;
+                        && getActiveFgCallState() != Call.State.DISCONNECTED) {
+                    if (fgPhone instanceof SipPhone) {
+                        // enable IN_COMMUNICATION audio mode for sipPhone
+                        mode = AudioManager.MODE_IN_COMMUNICATION;
+                    } else {
+                        // enable IN_CALL audio mode for telephony
+                        mode = AudioManager.MODE_IN_CALL;
+                    }
                 }
                 break;
         }
diff --git a/telephony/java/com/android/internal/telephony/RIL.java b/telephony/java/com/android/internal/telephony/RIL.java
index 35d5564..a77e73e 100644
--- a/telephony/java/com/android/internal/telephony/RIL.java
+++ b/telephony/java/com/android/internal/telephony/RIL.java
@@ -141,6 +141,7 @@
                 this.mNext = sPool;
                 sPool = this;
                 sPoolSize++;
+                mResult = null;
             }
         }
     }
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
index effb743..70328f7 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
@@ -106,7 +106,7 @@
      * It is a subset of allApns and has the same format
      */
     private ArrayList<ApnSetting> mWaitingApns = null;
-
+    private int mWaitingApnsPermanentFailureCountDown = 0;
     private ApnSetting mPreferredApn = null;
 
     /* Currently active APN */
@@ -361,6 +361,7 @@
 
             if (mState == State.IDLE) {
                 mWaitingApns = buildWaitingApns(mRequestedApnType);
+                mWaitingApnsPermanentFailureCountDown = mWaitingApns.size();
                 if (mWaitingApns.isEmpty()) {
                     if (DBG) log("No APN found");
                     notifyNoData(GsmDataConnection.FailCause.MISSING_UNKNOWN_APN);
@@ -996,6 +997,9 @@
         }
 
         if (ar.exception == null) {
+            if(DBG) {
+                log(String.format("onDataSetupComplete: success apn=%s", mWaitingApns.get(0).apn));
+            }
             // TODO: We should clear LinkProperties/Capabilities when torn down or disconnected
             mLinkProperties = getLinkProperties(mPendingDataConnection);
             mLinkCapabilities = getLinkCapabilities(mPendingDataConnection);
@@ -1047,27 +1051,32 @@
                 log(String.format("onDataSetupComplete: error apn=%s cause=%s", apnString, cause));
             }
             if (cause.isEventLoggable()) {
+                // Log this failure to the Event Logs.
                 GsmCellLocation loc = ((GsmCellLocation)mPhone.getCellLocation());
                 EventLog.writeEvent(EventLogTags.PDP_SETUP_FAIL,
                         cause.ordinal(), loc != null ? loc.getCid() : -1,
                         TelephonyManager.getDefault().getNetworkType());
             }
 
-            // Do not retry on permanent failure
-            // TODO: We should not fail permanently if more Apns to try!
-            if (cause.isPermanentFail()) {
-                notifyNoData(cause);
-                notifyDataConnection(Phone.REASON_APN_FAILED);
-                onEnableApn(apnTypeToId(mRequestedApnType), DISABLED);
-                return;
-            }
-
+            // Count permanent failures and remove the APN we just tried
+            mWaitingApnsPermanentFailureCountDown -= cause.isPermanentFail() ? 1 : 0;
             mWaitingApns.remove(0);
+            if (DBG) log(String.format("onDataSetupComplete: mWaitingApns.size=%d" +
+                            " mWaitingApnsPermanenatFailureCountDown=%d",
+                            mWaitingApns.size(), mWaitingApnsPermanentFailureCountDown));
+
+            // See if there are more APN's to try
             if (mWaitingApns.isEmpty()) {
-                // No more to try, start delayed retry
-                startDelayedRetry(cause, reason);
+                if (mWaitingApnsPermanentFailureCountDown == 0) {
+                    if (DBG) log("onDataSetupComplete: Permanent failures stop retrying");
+                    notifyNoData(cause);
+                    notifyDataConnection(Phone.REASON_APN_FAILED);
+                } else {
+                    if (DBG) log("onDataSetupComplete: Not all permanent failures, retry");
+                    startDelayedRetry(cause, reason);
+                }
             } else {
-                // we still have more apns to try
+                if (DBG) log("onDataSetupComplete: Try next APN");
                 setState(State.SCANNING);
                 // Wait a bit before trying the next APN, so that
                 // we're not tying up the RIL command channel
diff --git a/test-runner/src/android/test/InstrumentationTestRunner.java b/test-runner/src/android/test/InstrumentationTestRunner.java
index 3ac74f7..5ce3efc 100644
--- a/test-runner/src/android/test/InstrumentationTestRunner.java
+++ b/test-runner/src/android/test/InstrumentationTestRunner.java
@@ -785,7 +785,7 @@
             mIncludeDetailedStats = false;
             try {
                 // Look for TimedTest annotation on both test class and test method
-                if (testMethod.isAnnotationPresent(TimedTest.class)) {
+                if (testMethod != null && testMethod.isAnnotationPresent(TimedTest.class)) {
                     mIsTimedTest = true;
                     mIncludeDetailedStats = testMethod.getAnnotation(
                             TimedTest.class).includeDetailedStats();