Merge "Change recents UIs to do task switches."
diff --git a/api/current.xml b/api/current.xml
index 9923020..15224ce 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -9425,6 +9425,17 @@
  visibility="public"
 >
 </field>
+<field name="textIsSelectable"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843559"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="textLineHeight"
  type="int"
  transient="false"
@@ -10360,6 +10371,17 @@
  visibility="public"
 >
 </field>
+<field name="windowEnableSplitTouch"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843560"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="windowEnterAnimation"
  type="int"
  transient="false"
@@ -219227,6 +219249,19 @@
 <parameter name="data" type="android.os.Bundle">
 </parameter>
 </method>
+<method name="setCurrentInputMethodSubtype"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="subtype" type="android.view.inputmethod.InputMethodSubtype">
+</parameter>
+</method>
 <method name="setInputMethod"
  return="void"
  abstract="false"
@@ -219341,6 +219376,19 @@
 <parameter name="iconId" type="int">
 </parameter>
 </method>
+<method name="switchToLastInputMethod"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="imeToken" type="android.os.IBinder">
+</parameter>
+</method>
 <method name="toggleSoftInput"
  return="void"
  abstract="false"
@@ -243536,6 +243584,17 @@
  visibility="public"
 >
 </method>
+<method name="isTextSelectable"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="length"
  return="int"
  abstract="false"
@@ -244583,6 +244642,19 @@
 <parameter name="colors" type="android.content.res.ColorStateList">
 </parameter>
 </method>
+<method name="setTextIsSelectable"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="selectable" type="boolean">
+</parameter>
+</method>
 <method name="setTextKeepState"
  return="void"
  abstract="false"
@@ -246446,7 +246518,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="t" type="T">
+<parameter name="arg0" type="T">
 </parameter>
 </method>
 </interface>
diff --git a/core/java/android/app/DownloadManager.java b/core/java/android/app/DownloadManager.java
index 01414fa..3a6fd23 100644
--- a/core/java/android/app/DownloadManager.java
+++ b/core/java/android/app/DownloadManager.java
@@ -33,10 +33,7 @@
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashSet;
 import java.util.List;
-import java.util.Set;
 
 /**
  * The download manager is a system service that handles long-running HTTP downloads. Clients may
@@ -281,46 +278,32 @@
      */
     public static final String EXTRA_NOTIFICATION_CLICK_DOWNLOAD_IDS = "extra_click_download_ids";
 
-    // this array must contain all public columns
-    private static final String[] COLUMNS = new String[] {
-        COLUMN_ID,
-        COLUMN_MEDIAPROVIDER_URI,
-        Downloads.Impl.COLUMN_DESTINATION,
-        COLUMN_TITLE,
-        COLUMN_DESCRIPTION,
-        COLUMN_URI,
-        COLUMN_MEDIA_TYPE,
-        COLUMN_TOTAL_SIZE_BYTES,
-        COLUMN_LOCAL_URI,
-        COLUMN_STATUS,
-        COLUMN_REASON,
-        COLUMN_BYTES_DOWNLOADED_SO_FAR,
-        COLUMN_LAST_MODIFIED_TIMESTAMP,
-        COLUMN_LOCAL_FILENAME,
-    };
-
-    // columns to request from DownloadProvider
-    private static final String[] UNDERLYING_COLUMNS = new String[] {
+    /**
+     * columns to request from DownloadProvider.
+     * @hide
+     */
+    public static final String[] UNDERLYING_COLUMNS = new String[] {
         Downloads.Impl._ID,
+        Downloads.Impl._DATA,
         Downloads.Impl.COLUMN_MEDIAPROVIDER_URI,
         Downloads.Impl.COLUMN_DESTINATION,
         Downloads.Impl.COLUMN_TITLE,
         Downloads.Impl.COLUMN_DESCRIPTION,
         Downloads.Impl.COLUMN_URI,
-        Downloads.Impl.COLUMN_MIME_TYPE,
-        Downloads.Impl.COLUMN_TOTAL_BYTES,
         Downloads.Impl.COLUMN_STATUS,
-        Downloads.Impl.COLUMN_CURRENT_BYTES,
-        Downloads.Impl.COLUMN_LAST_MODIFICATION,
         Downloads.Impl.COLUMN_FILE_NAME_HINT,
-        Downloads.Impl._DATA,
+        Downloads.Impl.COLUMN_MIME_TYPE + " AS " + COLUMN_MEDIA_TYPE,
+        Downloads.Impl.COLUMN_TOTAL_BYTES + " AS " + COLUMN_TOTAL_SIZE_BYTES,
+        Downloads.Impl.COLUMN_LAST_MODIFICATION + " AS " + COLUMN_LAST_MODIFIED_TIMESTAMP,
+        Downloads.Impl.COLUMN_CURRENT_BYTES + " AS " + COLUMN_BYTES_DOWNLOADED_SO_FAR,
+        /* add the following 'computed' columns to the cursor.
+         * they are not 'returned' by the database, but their inclusion
+         * eliminates need to have lot of methods in CursorTranslator
+         */
+        "'placeholder' AS " + COLUMN_LOCAL_URI,
+        "'placeholder' AS " + COLUMN_REASON
     };
 
-    private static final Set<String> LONG_COLUMNS = new HashSet<String>(
-            Arrays.asList(COLUMN_ID, COLUMN_TOTAL_SIZE_BYTES, COLUMN_STATUS, COLUMN_REASON,
-                          COLUMN_BYTES_DOWNLOADED_SO_FAR, COLUMN_LAST_MODIFIED_TIMESTAMP,
-                          Downloads.Impl.COLUMN_DESTINATION));
-
     /**
      * This class contains all the information necessary to request a new download. The URI is the
      * only required parameter.
@@ -871,11 +854,7 @@
      * @return the number of downloads actually removed
      */
     public int remove(long... ids) {
-        if (ids == null || ids.length == 0) {
-            // called with nothing to remove!
-            throw new IllegalArgumentException("input param 'ids' can't be null");
-        }
-        return mResolver.delete(mBaseUri, getWhereClauseForIds(ids), getWhereArgsForIds(ids));
+        return markRowDeleted(ids);
     }
 
     /**
@@ -1032,117 +1011,32 @@
         }
 
         @Override
-        public int getColumnIndex(String columnName) {
-            return Arrays.asList(COLUMNS).indexOf(columnName);
-        }
-
-        @Override
-        public int getColumnIndexOrThrow(String columnName) throws IllegalArgumentException {
-            int index = getColumnIndex(columnName);
-            if (index == -1) {
-                throw new IllegalArgumentException("No such column: " + columnName);
-            }
-            return index;
-        }
-
-        @Override
-        public String getColumnName(int columnIndex) {
-            int numColumns = COLUMNS.length;
-            if (columnIndex < 0 || columnIndex >= numColumns) {
-                throw new IllegalArgumentException("Invalid column index " + columnIndex + ", "
-                                                   + numColumns + " columns exist");
-            }
-            return COLUMNS[columnIndex];
-        }
-
-        @Override
-        public String[] getColumnNames() {
-            String[] returnColumns = new String[COLUMNS.length];
-            System.arraycopy(COLUMNS, 0, returnColumns, 0, COLUMNS.length);
-            return returnColumns;
-        }
-
-        @Override
-        public int getColumnCount() {
-            return COLUMNS.length;
-        }
-
-        @Override
-        public byte[] getBlob(int columnIndex) {
-            throw new UnsupportedOperationException();
-        }
-
-        @Override
-        public double getDouble(int columnIndex) {
-            return getLong(columnIndex);
-        }
-
-        private boolean isLongColumn(String column) {
-            return LONG_COLUMNS.contains(column);
-        }
-
-        @Override
-        public float getFloat(int columnIndex) {
-            return (float) getDouble(columnIndex);
-        }
-
-        @Override
         public int getInt(int columnIndex) {
             return (int) getLong(columnIndex);
         }
 
         @Override
         public long getLong(int columnIndex) {
-            return translateLong(getColumnName(columnIndex));
-        }
-
-        @Override
-        public short getShort(int columnIndex) {
-            return (short) getLong(columnIndex);
+            if (getColumnName(columnIndex).equals(COLUMN_REASON)) {
+                return getReason(super.getInt(getColumnIndex(Downloads.Impl.COLUMN_STATUS)));
+            } else if (getColumnName(columnIndex).equals(COLUMN_STATUS)) {
+                return translateStatus(super.getInt(getColumnIndex(Downloads.Impl.COLUMN_STATUS)));
+            } else {
+                return super.getLong(columnIndex);
+            }
         }
 
         @Override
         public String getString(int columnIndex) {
-            return translateString(getColumnName(columnIndex));
-        }
-
-        private String translateString(String column) {
-            if (isLongColumn(column)) {
-                return Long.toString(translateLong(column));
-            }
-            if (column.equals(COLUMN_TITLE)) {
-                return getUnderlyingString(Downloads.Impl.COLUMN_TITLE);
-            }
-            if (column.equals(COLUMN_DESCRIPTION)) {
-                return getUnderlyingString(Downloads.Impl.COLUMN_DESCRIPTION);
-            }
-            if (column.equals(COLUMN_URI)) {
-                return getUnderlyingString(Downloads.Impl.COLUMN_URI);
-            }
-            if (column.equals(COLUMN_MEDIA_TYPE)) {
-                return getUnderlyingString(Downloads.Impl.COLUMN_MIME_TYPE);
-            }
-            if (column.equals(COLUMN_LOCAL_FILENAME)) {
-                return getUnderlyingString(Downloads.Impl._DATA);
-            }
-            if (column.equals(COLUMN_MEDIAPROVIDER_URI)) {
-                return getUnderlyingString(Downloads.Impl.COLUMN_MEDIAPROVIDER_URI);
-            }
-
-            assert column.equals(COLUMN_LOCAL_URI);
-            return getLocalUri();
+            return (getColumnName(columnIndex).equals(COLUMN_LOCAL_URI)) ? getLocalUri() :
+                    super.getString(columnIndex);
         }
 
         private String getLocalUri() {
-            long destinationType = getUnderlyingLong(Downloads.Impl.COLUMN_DESTINATION);
-            if (destinationType == Downloads.Impl.DESTINATION_FILE_URI) {
-                // return client-provided file URI for external download
-                return getUnderlyingString(Downloads.Impl.COLUMN_FILE_NAME_HINT);
-            }
-
-            if (destinationType == Downloads.Impl.DESTINATION_EXTERNAL) {
-                // return stored destination for legacy external download
-                String localPath = getUnderlyingString(Downloads.Impl._DATA);
+            long destinationType = getLong(getColumnIndex(Downloads.Impl.COLUMN_DESTINATION));
+            if (destinationType == Downloads.Impl.DESTINATION_FILE_URI ||
+                    destinationType == Downloads.Impl.DESTINATION_EXTERNAL) {
+                String localPath = getString(getColumnIndex(Downloads.Impl._DATA));
                 if (localPath == null) {
                     return null;
                 }
@@ -1150,38 +1044,10 @@
             }
 
             // return content URI for cache download
-            long downloadId = getUnderlyingLong(Downloads.Impl._ID);
+            long downloadId = getLong(getColumnIndex(Downloads.Impl._ID));
             return ContentUris.withAppendedId(mBaseUri, downloadId).toString();
         }
 
-        private long translateLong(String column) {
-            if (!isLongColumn(column)) {
-                // mimic behavior of underlying cursor -- most likely, throw NumberFormatException
-                return Long.valueOf(translateString(column));
-            }
-
-            if (column.equals(COLUMN_ID)) {
-                return getUnderlyingLong(Downloads.Impl._ID);
-            }
-            if (column.equals(COLUMN_TOTAL_SIZE_BYTES)) {
-                return getUnderlyingLong(Downloads.Impl.COLUMN_TOTAL_BYTES);
-            }
-            if (column.equals(COLUMN_STATUS)) {
-                return translateStatus((int) getUnderlyingLong(Downloads.Impl.COLUMN_STATUS));
-            }
-            if (column.equals(COLUMN_REASON)) {
-                return getReason((int) getUnderlyingLong(Downloads.Impl.COLUMN_STATUS));
-            }
-            if (column.equals(COLUMN_BYTES_DOWNLOADED_SO_FAR)) {
-                return getUnderlyingLong(Downloads.Impl.COLUMN_CURRENT_BYTES);
-            }
-            if (column.equals(Downloads.Impl.COLUMN_DESTINATION)) {
-                return getUnderlyingLong(Downloads.Impl.COLUMN_DESTINATION);
-            }
-            assert column.equals(COLUMN_LAST_MODIFIED_TIMESTAMP);
-            return getUnderlyingLong(Downloads.Impl.COLUMN_LAST_MODIFICATION);
-        }
-
         private long getReason(int status) {
             switch (translateStatus(status)) {
                 case STATUS_FAILED:
@@ -1249,14 +1115,6 @@
             }
         }
 
-        private long getUnderlyingLong(String column) {
-            return super.getLong(super.getColumnIndex(column));
-        }
-
-        private String getUnderlyingString(String column) {
-            return super.getString(super.getColumnIndex(column));
-        }
-
         private int translateStatus(int status) {
             switch (status) {
                 case Downloads.Impl.STATUS_PENDING:
diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java
index 34bd386..221fe23 100644
--- a/core/java/android/content/SyncManager.java
+++ b/core/java/android/content/SyncManager.java
@@ -705,6 +705,14 @@
         }
     }
 
+    private void clearBackoffSetting(SyncOperation op) {
+        mSyncStorageEngine.setBackoff(op.account, op.authority,
+                SyncStorageEngine.NOT_IN_BACKOFF_MODE, SyncStorageEngine.NOT_IN_BACKOFF_MODE);
+        synchronized (mSyncQueue) {
+            mSyncQueue.onBackoffChanged(op.account, op.authority, 0);
+        }
+    }
+
     private void increaseBackoffSetting(SyncOperation op) {
         final long now = SystemClock.elapsedRealtime();
 
@@ -1854,6 +1862,7 @@
                     // TODO: set these correctly when the SyncResult is extended to include it
                     downstreamActivity = 0;
                     upstreamActivity = 0;
+                    clearBackoffSetting(syncOperation);
                 } else {
                     Log.d(TAG, "failed sync operation " + syncOperation + ", " + syncResult);
                     // the operation failed so increase the backoff time
diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java
index 41bb364..7efb7fd 100644
--- a/core/java/android/database/sqlite/SQLiteDatabase.java
+++ b/core/java/android/database/sqlite/SQLiteDatabase.java
@@ -1081,7 +1081,7 @@
                 mConnectionPool.close();
             }
         } finally {
-            unlock();            
+            unlock();
         }
     }
 
@@ -1772,8 +1772,7 @@
      */
     public int updateWithOnConflict(String table, ContentValues values,
             String whereClause, String[] whereArgs, int conflictAlgorithm) {
-        int setValuesSize = values.size();
-        if (values == null || setValuesSize == 0) {
+        if (values == null || values.size() == 0) {
             throw new IllegalArgumentException("Empty values");
         }
 
@@ -1784,6 +1783,7 @@
         sql.append(" SET ");
 
         // move all bind args to one array
+        int setValuesSize = values.size();
         int bindArgsSize = (whereArgs == null) ? setValuesSize : (setValuesSize + whereArgs.length);
         Object[] bindArgs = new Object[bindArgsSize];
         int i = 0;
@@ -2118,7 +2118,7 @@
 
             int maxCacheSz = (mConnectionNum == 0) ? mMaxSqlCacheSize :
                     mParentConnObj.mMaxSqlCacheSize;
-            
+
             if (SQLiteDebug.DEBUG_SQL_CACHE) {
                 boolean printWarning = (mConnectionNum == 0)
                         ? (!mCacheFullWarning && mCompiledQueries.size() == maxCacheSz)
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 033ee7c..5e7a133 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -1432,6 +1432,28 @@
         }
     }
 
+    public boolean setCurrentInputMethodSubtype(InputMethodSubtype subtype) {
+        synchronized (mH) {
+            try {
+                return mService.setCurrentInputMethodSubtype(subtype);
+            } catch (RemoteException e) {
+                Log.w(TAG, "IME died: " + mCurId, e);
+                return false;
+            }
+        }
+    }
+
+    public boolean switchToLastInputMethod(IBinder imeToken) {
+        synchronized (mH) {
+            try {
+                return mService.switchToLastInputMethod(imeToken);
+            } catch (RemoteException e) {
+                Log.w(TAG, "IME died: " + mCurId, e);
+                return false;
+            }
+        }
+    }
+
     void doDump(FileDescriptor fd, PrintWriter fout, String[] args) {
         final Printer p = new PrintWriterPrinter(fout);
         p.println("Input method client state for " + this + ":");
diff --git a/core/java/android/webkit/DebugFlags.java b/core/java/android/webkit/DebugFlags.java
index 8e25395..3cb5e24 100644
--- a/core/java/android/webkit/DebugFlags.java
+++ b/core/java/android/webkit/DebugFlags.java
@@ -45,5 +45,9 @@
     public static final boolean WEB_TEXT_VIEW = false;
     public static final boolean WEB_VIEW = false;
     public static final boolean WEB_VIEW_CORE = false;
-
+    /*
+     * Set to true to allow the WebTextView to draw on top of the web page in a
+     * different color so that you can see how the two line up.
+     */
+    public static final boolean DRAW_WEBTEXTVIEW = false;
 }
diff --git a/core/java/android/webkit/WebTextView.java b/core/java/android/webkit/WebTextView.java
index a58d648..f477f8f 100644
--- a/core/java/android/webkit/WebTextView.java
+++ b/core/java/android/webkit/WebTextView.java
@@ -157,7 +157,7 @@
         // Set the text color to black, regardless of the theme.  This ensures
         // that other applications that use embedded WebViews will properly
         // display the text in password textfields.
-        setTextColor(Color.BLACK);
+        setTextColor(DebugFlags.DRAW_WEBTEXTVIEW ? Color.RED : Color.BLACK);
         // This helps to align the text better with the text in the web page.
         setIncludeFontPadding(false);
     }
@@ -404,8 +404,9 @@
         // onDraw should only be called for password fields.  If WebTextView is
         // still drawing, but is no longer corresponding to a password field,
         // remove it.
-        if (mWebView == null || !mWebView.nativeFocusCandidateIsPassword()
-                || !isSameTextField(mWebView.nativeFocusCandidatePointer())) {
+        if (!DebugFlags.DRAW_WEBTEXTVIEW && (mWebView == null
+                || !mWebView.nativeFocusCandidateIsPassword()
+                || !isSameTextField(mWebView.nativeFocusCandidatePointer()))) {
             // Although calling remove() would seem to make more sense here,
             // changing it to not be a password field will make it not draw.
             // Other code will make sure that it is removed completely, but this
@@ -819,7 +820,9 @@
         }
         // For password fields, draw the WebTextView.  For others, just show
         // webkit's drawing.
-        setWillNotDraw(!inPassword);
+        if (!DebugFlags.DRAW_WEBTEXTVIEW) {
+            setWillNotDraw(!inPassword);
+        }
         setBackgroundDrawable(inPassword ? mBackground : null);
     }
 
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 4e0c386..14dbfe2 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -7481,7 +7481,7 @@
     private native Rect     nativeFocusCandidatePaddingRect();
     /* package */ native int      nativeFocusCandidatePointer();
     private native String   nativeFocusCandidateText();
-    /* package */ native int      nativeFocusCandidateTextSize();
+    /* package */ native float    nativeFocusCandidateTextSize();
     /**
      * Returns an integer corresponding to WebView.cpp::type.
      * See WebTextView.setType()
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 6e927a6..0fcd26c 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -1803,6 +1803,8 @@
                 } else {
                     width = Math.max(w, mViewportWidth);
                 }
+            } else if (mSettings.getUseFixedViewport()) {
+                width = mWebView.getViewWidth();
             } else {
                 width = textwrapWidth;
             }
diff --git a/core/java/android/widget/AdapterViewAnimator.java b/core/java/android/widget/AdapterViewAnimator.java
index 7d78777..695ea6b 100644
--- a/core/java/android/widget/AdapterViewAnimator.java
+++ b/core/java/android/widget/AdapterViewAnimator.java
@@ -24,7 +24,6 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.TypedArray;
-import android.graphics.Rect;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Parcel;
diff --git a/core/java/android/widget/MediaController.java b/core/java/android/widget/MediaController.java
index 27a6ad3..690164c 100644
--- a/core/java/android/widget/MediaController.java
+++ b/core/java/android/widget/MediaController.java
@@ -298,7 +298,8 @@
             p.y = anchorpos[1] + mAnchor.getHeight() - p.height;
             p.format = PixelFormat.TRANSLUCENT;
             p.type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
-            p.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
+            p.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
+                    | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH;
             p.token = null;
             p.windowAnimations = 0; // android.R.style.DropDownAnimationDown;
             mWindowManager.addView(mDecor, p);
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index 95678c6..0f61cd4 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -25,6 +25,7 @@
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.StateListDrawable;
+import android.os.Build;
 import android.os.IBinder;
 import android.util.AttributeSet;
 import android.util.DisplayMetrics;
@@ -87,7 +88,7 @@
     private boolean mTouchable = true;
     private boolean mOutsideTouchable = false;
     private boolean mClippingEnabled = true;
-    private boolean mSplitTouchEnabled;
+    private int mSplitTouchEnabled = -1;
     private boolean mLayoutInScreen;
     private boolean mClipToScreen;
 
@@ -602,14 +603,17 @@
      * @hide
      */
     public boolean isSplitTouchEnabled() {
-        return mSplitTouchEnabled;
+        if (mSplitTouchEnabled < 0 && mContext != null) {
+            return mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB;
+        }
+        return mSplitTouchEnabled == 1;
     }
 
     /**
      * <p>Allows the popup window to split touches across other windows that also
-     * support split touch.  When this flag is not set, the first pointer
+     * support split touch.  When this flag is false, the first pointer
      * that goes down determines the window to which all subsequent touches
-     * go until all pointers go up.  When this flag is set, each pointer
+     * go until all pointers go up.  When this flag is true, each pointer
      * (not necessarily the first) that goes down determines the window
      * to which all subsequent touches of that pointer will go until that
      * pointer goes up thereby enabling touches with multiple pointers
@@ -620,7 +624,7 @@
      * @hide
      */
     public void setSplitTouchEnabled(boolean enabled) {
-        mSplitTouchEnabled = enabled;
+        mSplitTouchEnabled = enabled ? 1 : 0;
     }
 
     /**
@@ -993,7 +997,7 @@
         if (!mClippingEnabled) {
             curFlags |= WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
         }
-        if (mSplitTouchEnabled) {
+        if (isSplitTouchEnabled()) {
             curFlags |= WindowManager.LayoutParams.FLAG_SPLIT_TOUCH;
         }
         if (mLayoutInScreen) {
diff --git a/core/java/android/widget/StackView.java b/core/java/android/widget/StackView.java
index 01044d9..7c38714 100644
--- a/core/java/android/widget/StackView.java
+++ b/core/java/android/widget/StackView.java
@@ -122,7 +122,7 @@
     private boolean mFirstLayoutHappened = false;
     private int mStackMode;
     private int mFramePadding;
-    private final Rect invalidateRect = new Rect();
+    private final Rect stackInvalidateRect = new Rect();
 
     public StackView(Context context) {
         super(context);
@@ -243,6 +243,7 @@
     @Override
     @android.view.RemotableViewMethod
     public void showNext() {
+        if (mSwipeGestureType != GESTURE_NONE) return;
         if (!mTransitionIsSetup) {
             View v = getViewAtRelativeIndex(1);
             if (v != null) {
@@ -257,6 +258,7 @@
     @Override
     @android.view.RemotableViewMethod
     public void showPrevious() {
+        if (mSwipeGestureType != GESTURE_NONE) return;
         if (!mTransitionIsSetup) {
             View v = getViewAtRelativeIndex(0);
             if (v != null) {
@@ -301,8 +303,11 @@
         // Here we need to make sure that the z-order of the children is correct
         for (int i = mCurrentWindowEnd; i >= mCurrentWindowStart; i--) {
             int index = modulo(i, getWindowSize());
-            View v = mViewsMap.get(index).view;
-            if (v != null) v.bringToFront();
+            ViewAndIndex vi = mViewsMap.get(index);
+            if (vi != null) {
+                View v = mViewsMap.get(index).view;
+                if (v != null) v.bringToFront();
+            }
         }
         mTransitionIsSetup = false;
     }
@@ -331,16 +336,15 @@
 
     @Override
     protected void dispatchDraw(Canvas canvas) {
-        canvas.getClipBounds(invalidateRect);
+        canvas.getClipBounds(stackInvalidateRect);
         final int childCount = getChildCount();
         for (int i = 0; i < childCount; i++) {
             LayoutParams lp = (LayoutParams) getChildAt(i).getLayoutParams();
-            invalidateRect.union(lp.getInvalidateRect());
+            stackInvalidateRect.union(lp.getInvalidateRect());
             lp.resetInvalidateRect();
         }
-
         canvas.save(Canvas.CLIP_SAVE_FLAG);
-        canvas.clipRect(invalidateRect, Region.Op.UNION);
+        canvas.clipRect(stackInvalidateRect, Region.Op.UNION);
         super.dispatchDraw(canvas);
         canvas.restore();
     }
@@ -553,6 +557,10 @@
 
         if (deltaY > mSwipeThreshold && mSwipeGestureType == GESTURE_SLIDE_DOWN
                 && mStackSlider.mMode == StackSlider.NORMAL_MODE) {
+            // We reset the gesture variable, because otherwise we will ignore showPrevious() /
+            // showNext();
+            mSwipeGestureType = GESTURE_NONE;
+
             // Swipe threshold exceeded, swipe down
             if (mStackMode == ITEMS_SLIDE_UP) {
                 showPrevious();
@@ -562,6 +570,10 @@
             mHighlight.bringToFront();
         } else if (deltaY < -mSwipeThreshold && mSwipeGestureType == GESTURE_SLIDE_UP
                 && mStackSlider.mMode == StackSlider.NORMAL_MODE) {
+            // We reset the gesture variable, because otherwise we will ignore showPrevious() /
+            // showNext();
+            mSwipeGestureType = GESTURE_NONE;
+
             // Swipe threshold exceeded, swipe up
             if (mStackMode == ITEMS_SLIDE_UP) {
                 showNext();
@@ -897,7 +909,6 @@
         int horizontalOffset;
         int verticalOffset;
         View mView;
-        int left, top, right, bottom;
         private final Rect parentRect = new Rect();
         private final Rect invalidateRect = new Rect();
         private final RectF invalidateRectf = new RectF();
@@ -952,44 +963,32 @@
         }
 
         void resetInvalidateRect() {
-           invalidateRect.set(0, 0, 0, 0);
+            invalidateRect.set(0, 0, 0, 0);
         }
 
         // This is public so that ObjectAnimator can access it
         public void setVerticalOffset(int newVerticalOffset) {
-            int offsetDelta = newVerticalOffset - verticalOffset;
+            setOffsets(horizontalOffset, newVerticalOffset);
+        }
+
+        public void setHorizontalOffset(int newHorizontalOffset) {
+            setOffsets(newHorizontalOffset, verticalOffset);
+        }
+
+        public void setOffsets(int newHorizontalOffset, int newVerticalOffset) {
+            int horizontalOffsetDelta = newHorizontalOffset - horizontalOffset;
+            horizontalOffset = newHorizontalOffset;
+            int verticalOffsetDelta = newVerticalOffset - verticalOffset;
             verticalOffset = newVerticalOffset;
 
             if (mView != null) {
                 mView.requestLayout();
-                int top = Math.min(mView.getTop() + offsetDelta, mView.getTop());
-                int bottom = Math.max(mView.getBottom() + offsetDelta, mView.getBottom());
+                int left = Math.min(mView.getLeft() + horizontalOffsetDelta, mView.getLeft());
+                int right = Math.max(mView.getRight() + horizontalOffsetDelta, mView.getRight());
+                int top = Math.min(mView.getTop() + verticalOffsetDelta, mView.getTop());
+                int bottom = Math.max(mView.getBottom() + verticalOffsetDelta, mView.getBottom());
 
-                invalidateRectf.set(mView.getLeft(), top, mView.getRight(), bottom);
-
-                float xoffset = -invalidateRectf.left;
-                float yoffset = -invalidateRectf.top;
-                invalidateRectf.offset(xoffset, yoffset);
-                mView.getMatrix().mapRect(invalidateRectf);
-                invalidateRectf.offset(-xoffset, -yoffset);
-                invalidateRect.union((int) Math.floor(invalidateRectf.left),
-                        (int) Math.floor(invalidateRectf.top),
-                        (int) Math.ceil(invalidateRectf.right),
-                        (int) Math.ceil(invalidateRectf.bottom));
-
-                invalidateGlobalRegion(mView, invalidateRect);
-            }
-        }
-
-        public void setHorizontalOffset(int newHorizontalOffset) {
-            int offsetDelta = newHorizontalOffset - horizontalOffset;
-            horizontalOffset = newHorizontalOffset;
-
-            if (mView != null) {
-                mView.requestLayout();
-                int left = Math.min(mView.getLeft() + offsetDelta, mView.getLeft());
-                int right = Math.max(mView.getRight() + offsetDelta, mView.getRight());
-                invalidateRectf.set(left,  mView.getTop(), right, mView.getBottom());
+                invalidateRectf.set(left, top, right, bottom);
 
                 float xoffset = -invalidateRectf.left;
                 float yoffset = -invalidateRectf.top;
@@ -997,7 +996,7 @@
                 mView.getMatrix().mapRect(invalidateRectf);
                 invalidateRectf.offset(-xoffset, -yoffset);
 
-                invalidateRect.union((int) Math.floor(invalidateRectf.left),
+                invalidateRect.set((int) Math.floor(invalidateRectf.left),
                         (int) Math.floor(invalidateRectf.top),
                         (int) Math.ceil(invalidateRectf.right),
                         (int) Math.ceil(invalidateRectf.bottom));
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index fdd75d5..5320b10 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -66,6 +66,7 @@
 import android.text.TextPaint;
 import android.text.TextUtils;
 import android.text.TextWatcher;
+import android.text.method.ArrowKeyMovementMethod;
 import android.text.method.DateKeyListener;
 import android.text.method.DateTimeKeyListener;
 import android.text.method.DialerKeyListener;
@@ -755,6 +756,11 @@
                 if (lineHeight != 0) {
                     setLineHeight(lineHeight);
                 }
+                break;
+
+            case com.android.internal.R.styleable.TextView_textIsSelectable:
+                mTextIsSelectable = a.getBoolean(attr, false);
+                break;
             }
         }
         a.recycle();
@@ -844,6 +850,14 @@
 
             mInput = TextKeyListener.getInstance(autotext, cap);
             mInputType = inputType;
+        } else if (mTextIsSelectable) {
+            // Prevent text changes from keyboard.
+            mInputType = EditorInfo.TYPE_NULL;
+            mInput = null;
+            bufferType = BufferType.SPANNABLE;
+            setFocusableInTouchMode(true);
+            // So that selection can be changed using arrow keys and touch is handled.
+            setMovementMethod(ArrowKeyMovementMethod.getInstance());
         } else if (editable) {
             mInput = TextKeyListener.getInstance();
             mInputType = EditorInfo.TYPE_CLASS_TEXT;
@@ -1098,6 +1112,8 @@
      * within the text can cause individual lines to be taller or shorter
      * than this height, and the layout may contain additional first-
      * or last-line padding.
+     *
+     * @attr ref android.R.styleable#TextView_textLineHeight
      */
     public int getLineHeight() {
         if (mLineHeight != 0) {
@@ -4028,6 +4044,71 @@
         return false;
     }
 
+    /**
+     * When a TextView is used to display a useful piece of information to the user (such as a
+     * contact's address), it should be made selectable, so that the user can select and copy this
+     * content.
+     *
+     * Use {@link #setTextIsSelectable(boolean)} or the
+     * {@link android.R.styleable#TextView_textIsSelectable} XML attribute to make this TextView
+     * selectable (the text is not selectable by default). Note that the content of an EditText is
+     * always selectable.
+     *
+     * @return True if the text displayed in this TextView can be selected by the user.
+     *
+     * @attr ref android.R.styleable#TextView_textIsSelectable
+     */
+    public boolean isTextSelectable() {
+        return mTextIsSelectable;
+    }
+
+    /**
+     * Sets whether or not (default) the content of this view is selectable by the user.
+     *
+     * See {@link #isTextSelectable} for details.
+     *
+     * @param selectable Whether or not the content of this TextView should be selectable.
+     */
+    public void setTextIsSelectable(boolean selectable) {
+        if (mTextIsSelectable == selectable) return;
+
+        mTextIsSelectable = selectable;
+
+        setFocusableInTouchMode(selectable);
+        setFocusable(selectable);
+        setClickable(selectable);
+        setLongClickable(selectable);
+
+        // mInputType is already EditorInfo.TYPE_NULL and mInput is null;
+
+        setMovementMethod(selectable ? ArrowKeyMovementMethod.getInstance() : null);
+        setText(getText(), selectable ? BufferType.SPANNABLE : BufferType.NORMAL);
+
+        // Called by setText above, but safer in case of future code changes
+        prepareCursorControllers();
+    }
+
+    @Override
+    protected int[] onCreateDrawableState(int extraSpace) {
+        final int[] drawableState = super.onCreateDrawableState(extraSpace);
+        if (mTextIsSelectable) {
+            // Disable pressed state, which was introduced when TextView was made clickable.
+            // Prevents text color change.
+            // setClickable(false) would have a similar effect, but it also disables focus changes
+            // and long press actions, which are both needed by text selection.
+            final int length = drawableState.length;
+            for (int i = 0; i < length; i++) {
+                if (drawableState[i] == R.attr.state_pressed) {
+                    final int[] nonPressedState = new int[length - 1];
+                    System.arraycopy(drawableState, 0, nonPressedState, 0, i);
+                    System.arraycopy(drawableState, i + 1, nonPressedState, i, length - i - 1);
+                    return nonPressedState;
+                }
+            }
+        }
+        return drawableState;
+    }
+
     @Override
     protected void onDraw(Canvas canvas) {
         if (mCurrentAlpha <= ViewConfiguration.ALPHA_THRESHOLD_INT) return;
@@ -4190,12 +4271,13 @@
             selStart = getSelectionStart();
             selEnd = getSelectionEnd();
 
-            if (mCursorVisible && selStart >= 0 && isEnabled()) {
+            if ((mCursorVisible || mTextIsSelectable) && selStart >= 0 && isEnabled()) {
                 if (mHighlightPath == null)
                     mHighlightPath = new Path();
 
                 if (selStart == selEnd) {
-                    if ((SystemClock.uptimeMillis() - mShowCursor) % (2 * BLINK) < BLINK) {
+                    if (!mTextIsSelectable &&
+                            (SystemClock.uptimeMillis() - mShowCursor) % (2 * BLINK) < BLINK) {
                         if (mHighlightPathBogus) {
                             mHighlightPath.reset();
                             mLayout.getCursorPath(selStart, mHighlightPath, mText);
@@ -7011,9 +7093,9 @@
                         mSelectionModifierCursorController.updatePosition();
                     }
                 }
-                if (action == MotionEvent.ACTION_UP && isFocused() && !mScrolled) {
+                if (action == MotionEvent.ACTION_UP && !mScrolled && isFocused()) {
                     InputMethodManager imm = (InputMethodManager)
-                          getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+                    getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
 
                     CommitSelectionReceiver csr = null;
                     if (getSelectionStart() != oldSelStart || getSelectionEnd() != oldSelEnd ||
@@ -7047,7 +7129,8 @@
                     || windowParams.type > WindowManager.LayoutParams.LAST_SUB_WINDOW;
         }
 
-        if (windowSupportsHandles && isTextEditable() && mCursorVisible && mLayout != null) {
+        if (windowSupportsHandles && isTextEditable() && mCursorVisible && mLayout != null &&
+                !mTextIsSelectable) {
             if (mInsertionPointCursorController == null) {
                 mInsertionPointCursorController = new InsertionPointCursorController();
             }
@@ -7070,10 +7153,12 @@
     }
 
     /**
-     * @return True iff this TextView contains a text that can be edited.
+     * @return True iff this TextView contains a text that can be edited, or if this is
+     * a selectable TextView.
      */
     private boolean isTextEditable() {
-        return mText instanceof Editable && onCheckIsTextEditor() && isEnabled();
+        return (mText instanceof Editable && onCheckIsTextEditor() && isEnabled())
+                || mTextIsSelectable;
     }
 
     /**
@@ -7320,9 +7405,7 @@
         // prepareCursorController() relies on this method.
         // If you change this condition, make sure prepareCursorController is called anywhere
         // the value of this condition might be changed.
-        return (mText instanceof Spannable &&
-                mMovement != null &&
-                mMovement.canSelectArbitrarily());
+        return (mText instanceof Spannable && mMovement != null && mMovement.canSelectArbitrarily());
     }
 
     private boolean canCut() {
@@ -8883,6 +8966,7 @@
     private float                   mSpacingMult = 1;
     private float                   mSpacingAdd = 0;
     private int                     mLineHeight = 0;
+    private boolean                 mTextIsSelectable = false;
 
     private static final int        LINES = 1;
     private static final int        EMS = LINES;
diff --git a/core/java/com/android/internal/os/SamplingProfilerIntegration.java b/core/java/com/android/internal/os/SamplingProfilerIntegration.java
index 6d2bcae..c930c57c 100644
--- a/core/java/com/android/internal/os/SamplingProfilerIntegration.java
+++ b/core/java/com/android/internal/os/SamplingProfilerIntegration.java
@@ -53,7 +53,10 @@
 
     static {
         samplingProfilerHz = SystemProperties.getInt("persist.sys.profiler_hz", 0);
-        if (samplingProfilerHz > 0) {
+        // Disabling this for now, as it crashes when enabled server-side.  So adding
+        // a new property ("REALLY") for those wanting to test and fix it.
+        boolean really = SystemProperties.getInt("persist.sys.profiler_hz_REALLY", 0) > 0;
+        if (samplingProfilerHz > 0 && really) {
             snapshotWriter = Executors.newSingleThreadExecutor();
             enabled = true;
             Log.i(TAG, "Profiler is enabled. Sampling Profiler Hz: " + samplingProfilerHz);
diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl
index ca1cd59..7592e8b 100644
--- a/core/java/com/android/internal/view/IInputMethodManager.aidl
+++ b/core/java/com/android/internal/view/IInputMethodManager.aidl
@@ -57,7 +57,7 @@
     void updateStatusIcon(in IBinder token, String packageName, int iconId);
     void setIMEButtonVisible(in IBinder token, boolean visible);
     InputMethodSubtype getCurrentInputMethodSubtype();
-    
+    boolean setCurrentInputMethodSubtype(in InputMethodSubtype subtype);
+    boolean switchToLastInputMethod(in IBinder token);
     boolean setInputMethodEnabled(String id, boolean enabled);
 }
-
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 7ff75b3..d6684fe 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -345,6 +345,18 @@
              because there will be no such interaction coming. -->
         <attr name="windowNoDisplay" format="boolean" />
 
+        <!-- Flag indicating that this window should allow touches to be split
+             across other windows that also support split touch.
+             The default value is true for applications with a targetSdkVersion
+             of Honeycomb or newer; false otherwise.
+             When this flag is false, the first pointer that goes down determines
+             the window to which all subsequent touches go until all pointers go up.
+             When this flag is true, each pointer (not necessarily the first) that
+             goes down determines the window to which all subsequent touches of that
+             pointer will go until that pointers go up thereby enabling touches
+             with multiple pointers to be split across multiple windows. -->
+        <attr name="windowEnableSplitTouch" format="boolean" />
+
         <!-- ============ -->
         <!-- Alert Dialog styles -->
         <!-- ============ -->
@@ -635,6 +647,10 @@
     <!-- Height of a line of text. -->
     <attr name="textLineHeight" format="dimension" />
 
+    <!-- Indicates that the content of a non-editable TextView can be selected.
+     Default value is false. EditText content is always selectable. -->
+    <attr name="textIsSelectable" format="boolean" />
+
     <!-- Where to ellipsize text. -->
     <attr name="ellipsize">
         <enum name="none" value="0" />
@@ -1223,6 +1239,7 @@
         <attr name="windowActionBar" />
         <attr name="windowActionModeOverlay" />
         <attr name="windowActionBarOverlay" />
+        <attr name="windowEnableSplitTouch" />
     </declare-styleable>
 
     <!-- The set of attributes that describe a AlertDialog's theme. -->
@@ -2477,6 +2494,9 @@
 
         <!-- Height of a line of text. -->
         <attr name="textLineHeight" />
+        <!-- Indicates that a non-editable text can be selected. -->
+        <attr name="textIsSelectable" />
+
     </declare-styleable>
     <!-- An <code>input-extras</code> is a container for extra data to supply to
          an input method.  Contains
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index bf0ac47..28df995 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1365,12 +1365,13 @@
   <public type="attr" name="selectableItemBackground" />
   <public type="attr" name="autoAdvanceViewId" />
   <public type="attr" name="useIntrinsicSizeAsMinimum" />
-
   <public type="attr" name="actionModeCutDrawable" />
   <public type="attr" name="actionModeCopyDrawable" />
   <public type="attr" name="actionModePasteDrawable" />
   <public type="attr" name="textEditPasteWindowLayout" />
   <public type="attr" name="textEditNoPasteWindowLayout" />
+  <public type="attr" name="textIsSelectable" />
+  <public type="attr" name="windowEnableSplitTouch" />
 
   <public type="anim" name="animator_fade_in" />
   <public type="anim" name="animator_fade_out" />
diff --git a/graphics/java/android/renderscript/BaseObj.java b/graphics/java/android/renderscript/BaseObj.java
index 026f7de..78b5617 100644
--- a/graphics/java/android/renderscript/BaseObj.java
+++ b/graphics/java/android/renderscript/BaseObj.java
@@ -41,6 +41,13 @@
         mID = id;
     }
 
+    /**
+     * Lookup the native object ID for this object.  Primarily used by the
+     * generated reflected code.
+     *
+     *
+     * @return int
+     */
     public int getID() {
         if (mDestroyed) {
             throw new RSInvalidStateException("using a destroyed object.");
@@ -53,8 +60,15 @@
     private String mName;
     RenderScript mRS;
 
-    public void setName(String s) {
-        if(s.length() < 1) {
+    /**
+     * setName assigns a name to an object.  This object can later be looked up
+     * by this name.  This name will also be retained if the object is written
+     * to an A3D file.
+     *
+     * @param name The name to assign to the object.
+     */
+    public void setName(String name) {
+        if(name.length() < 1) {
             throw new RSIllegalArgumentException("setName does not accept a zero length string.");
         }
         if(mName != null) {
@@ -62,9 +76,9 @@
         }
 
         try {
-            byte[] bytes = s.getBytes("UTF-8");
+            byte[] bytes = name.getBytes("UTF-8");
             mRS.nAssignName(mID, bytes);
-            mName = s;
+            mName = name;
         } catch (java.io.UnsupportedEncodingException e) {
             throw new RuntimeException(e);
         }
@@ -84,6 +98,12 @@
         super.finalize();
     }
 
+    /**
+     * destroy disconnects the object from the native object effectivly
+     * rendering this java object dead.  The primary use is to force immediate
+     * cleanup of resources when its believed the GC will not respond quickly
+     * enough.
+     */
     synchronized public void destroy() {
         if(mDestroyed) {
             throw new RSInvalidStateException("Object already destroyed.");
@@ -92,8 +112,10 @@
         mRS.nObjDestroy(mID);
     }
 
-    // If an object came from an a3d file, java fields need to be
-    // created with objects from the native layer
+    /**
+     * If an object came from an a3d file, java fields need to be
+     * created with objects from the native layer
+     */
     void updateFromNative() {
         mRS.validate();
         mName = mRS.nGetName(getID());
diff --git a/graphics/java/android/renderscript/Element.java b/graphics/java/android/renderscript/Element.java
index 8907cd2..4b007f2 100644
--- a/graphics/java/android/renderscript/Element.java
+++ b/graphics/java/android/renderscript/Element.java
@@ -22,6 +22,25 @@
 /**
  * @hide
  *
+ * Element is the basic data type of RenderScript.  An element can be of 2
+ * forms.  Basic elements contain a single component of data.  This can be of
+ * any of the legal RS types.  Examples of basic element types.
+ * Single float value
+ * 4 element float vector
+ * single RGB-565 color
+ * single unsigned int 16
+ *
+ * Complex elements will contain a list of sub-elements and names.  This in
+ * effect represents a structure of data.  The fields can be accessed by name
+ * from a script or shader.  The memory layout is defined and ordered.  Data
+ * alignment is determinied by the most basic primitive type.  i.e. a float4
+ * vector will be alligned to sizeof(float) and not sizeof(float4).  The
+ * ordering of elements in memory will be the order in which they were added
+ * with each component aligned as necessary. No re-ordering will be done.
+ *
+ * The primary source of elements will be from scripts.  A script that exports a
+ * bind point for a data structure will generate a RS element to represent the
+ * data exported by the script.
  **/
 public class Element extends BaseObj {
     int mSize;
@@ -36,6 +55,21 @@
 
     int getSizeBytes() {return mSize;}
 
+
+    /**
+     * DataType represents the basic type information for a basic element.  The
+     * naming convention follows.  For numeric types its FLOAT, SIGNED, UNSIGNED
+     * followed by the _BITS where BITS is the size of the data.  BOOLEAN is a
+     * true / false (1,0) represented in an 8 bit container.  The UNSIGNED
+     * variants with multiple bit definitions are for packed graphical data
+     * formats and represents vectors with per vector member sizes which are
+     * treated as a single unit for packing and alignment purposes.
+     *
+     * MATRIX the three matrix types contain FLOAT_32 elements and are treated
+     * as 32 bits for alignment purposes.
+     *
+     * RS_* objects.  32 bit opaque handles.
+     */
     public enum DataType {
         //FLOAT_16 (1, 2),
         FLOAT_32 (2, 4),
@@ -78,6 +112,12 @@
         }
     }
 
+    /**
+     * The special interpretation of the data if required.  This is primarly
+     * useful for graphical data.  USER indicates no special interpretation is
+     * expected.  PIXEL is used in conjunction with the standard data types for
+     * representing texture formats.
+     */
     public enum DataKind {
         USER (0),
 
@@ -93,6 +133,12 @@
         }
     }
 
+    /**
+     * Return if a element is too complex for use as a data source for a Mesh or
+     * a Program.
+     *
+     * @return boolean
+     */
     public boolean isComplex() {
         if (mElements == null) {
             return false;
@@ -105,6 +151,13 @@
         return false;
     }
 
+    /**
+     * Utility function for returning an Element containing a single Boolean.
+     *
+     * @param rs Context to which the element will belong.
+     *
+     * @return Element
+     */
     public static Element BOOLEAN(RenderScript rs) {
         if(rs.mElement_BOOLEAN == null) {
             rs.mElement_BOOLEAN = createUser(rs, DataType.BOOLEAN);
@@ -112,6 +165,13 @@
         return rs.mElement_BOOLEAN;
     }
 
+    /**
+     * Utility function for returning an Element containing a single UNSIGNED_8.
+     *
+     * @param rs Context to which the element will belong.
+     *
+     * @return Element
+     */
     public static Element U8(RenderScript rs) {
         if(rs.mElement_U8 == null) {
             rs.mElement_U8 = createUser(rs, DataType.UNSIGNED_8);
@@ -119,6 +179,13 @@
         return rs.mElement_U8;
     }
 
+    /**
+     * Utility function for returning an Element containing a single SIGNED_8.
+     *
+     * @param rs Context to which the element will belong.
+     *
+     * @return Element
+     */
     public static Element I8(RenderScript rs) {
         if(rs.mElement_I8 == null) {
             rs.mElement_I8 = createUser(rs, DataType.SIGNED_8);
@@ -414,7 +481,14 @@
         super.destroy();
     }
 
-    /////////////////////////////////////////
+    /**
+     * Create a custom Element of the specified DataType.  The DataKind will be
+     * set to USER and the vector size to 1 indicating non-vector.
+     *
+     * @param rs The context associated with the new Element.
+     * @param dt The DataType for the new element.
+     * @return Element
+     */
     public static Element createUser(RenderScript rs, DataType dt) {
         DataKind dk = DataKind.USER;
         boolean norm = false;
@@ -423,6 +497,17 @@
         return new Element(id, rs, dt, dk, norm, vecSize);
     }
 
+    /**
+     * Create a custom vector element of the specified DataType and vector size.
+     *  DataKind will be set to USER.
+     *
+     * @param rs The context associated with the new Element.
+     * @param dt The DataType for the new element.
+     * @param size Vector size for the new Element.  Range 2-4 inclusive
+     *             supported.
+     *
+     * @return Element
+     */
     public static Element createVector(RenderScript rs, DataType dt, int size) {
         if (size < 2 || size > 4) {
             throw new RSIllegalArgumentException("Vector size out of rance 2-4.");
@@ -433,6 +518,18 @@
         return new Element(id, rs, dt, dk, norm, size);
     }
 
+    /**
+     * Create a new pixel Element type.  A matching DataType and DataKind must
+     * be provided.  The DataType and DataKind must contain the same number of
+     * components.  Vector size will be set to 1.
+     *
+     * @param rs The context associated with the new Element.
+     * @param dt The DataType for the new element.
+     * @param dk The DataKind to specify the mapping of each component in the
+     *           DataType.
+     *
+     * @return Element
+     */
     public static Element createPixel(RenderScript rs, DataType dt, DataKind dk) {
         if (!(dk == DataKind.PIXEL_L ||
               dk == DataKind.PIXEL_A ||
@@ -473,6 +570,12 @@
         return new Element(id, rs, dt, dk, norm, size);
     }
 
+    /**
+     * Builder class for producing complex elements with matching field and name
+     * pairs.  The builder starts empty.  The order in which elements are added
+     * is retained for the layout in memory.
+     *
+     */
     public static class Builder {
         RenderScript mRS;
         Element[] mElements;
@@ -480,6 +583,11 @@
         int[] mArraySizes;
         int mCount;
 
+        /**
+         * Create a builder object.
+         *
+         * @param rs
+         */
         public Builder(RenderScript rs) {
             mRS = rs;
             mCount = 0;
@@ -488,6 +596,13 @@
             mArraySizes = new int[8];
         }
 
+        /**
+         * Add an array of elements to this element.
+         *
+         * @param element
+         * @param name
+         * @param arraySize
+         */
         public void add(Element element, String name, int arraySize) {
             if (arraySize < 1) {
                 throw new RSIllegalArgumentException("Array size cannot be less than 1.");
@@ -509,10 +624,22 @@
             mCount++;
         }
 
+        /**
+         * Add a single element to this Element.
+         *
+         * @param element
+         * @param name
+         */
         public void add(Element element, String name) {
             add(element, name, 1);
         }
 
+        /**
+         * Create the element from this builder.
+         *
+         *
+         * @return Element
+         */
         public Element create() {
             mRS.validate();
             Element[] ein = new Element[mCount];
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index 64afb6f..df03e13 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -28,6 +28,13 @@
 /**
  * @hide
  *
+ * RenderScript base master class.  An instance of this class creates native
+ * worker threads for processing commands from this object.  This base class
+ * does not provide any extended capabilities beyond simple data processing.
+ * For extended capabilities use derived classes such as RenderScriptGL.
+ *
+ *
+ *
  **/
 public class RenderScript {
     static final String LOG_TAG = "RenderScript_jni";
@@ -581,6 +588,14 @@
     ///////////////////////////////////////////////////////////////////////////////////
     //
 
+    /**
+     * Base class application should derive from for handling RS messages
+     * comming from their scripts.  When a script calls sendToClient the data
+     * fields will be filled in and then the run method called by a message
+     * handling thread.  This will occur some time after sendToClient completes
+     * in the script.
+     *
+     */
     public static class RSMessage implements Runnable {
         protected int[] mData;
         protected int mID;
@@ -588,16 +603,42 @@
         public void run() {
         }
     }
+    /**
+     * If an application is expecting messages it should set this field to an
+     * instance of RSMessage.  This instance will receive all the user messages
+     * sent from sendToClient by scripts from this context.
+     *
+     */
     public RSMessage mMessageCallback = null;
 
+    /**
+     * Runtime error base class.  An application should derive from this class
+     * if it wishes to install an error handler.  When errors occur at runtime
+     * the fields in this class will be filled and the run method called.
+     *
+     */
     public static class RSAsyncError implements Runnable {
         protected String mErrorMessage;
         protected int mErrorNum;
         public void run() {
         }
     }
+
+    /**
+     * Application Error handler.  All runtime errors will be dispatched to the
+     * instance of RSAsyncError set here.  If this field is null a
+     * RSRuntimeException will instead be thrown with details about the error.
+     * This will cause program termaination.
+     *
+     */
     public RSAsyncError mErrorCallback = null;
 
+    /**
+     * RenderScript worker threads priority enumeration.  The default value is
+     * NORMAL.  Applications wishing to do background processing such as
+     * wallpapers should set their priority to LOW to avoid starving forground
+     * processes.
+     */
     public enum Priority {
         LOW (5),     //ANDROID_PRIORITY_BACKGROUND + 5
         NORMAL (-4);  //ANDROID_PRIORITY_DISPLAY
@@ -614,6 +655,12 @@
         }
     }
 
+
+    /**
+     * Change the priority of the worker threads for this context.
+     *
+     * @param p New priority to be set.
+     */
     public void contextSetPriority(Priority p) {
         validate();
         nContextSetPriority(p.mID);
@@ -690,9 +737,15 @@
         }
     }
 
-    protected RenderScript() {
+    RenderScript() {
     }
 
+    /**
+     * Create a basic RenderScript context.
+     *
+     *
+     * @return RenderScript
+     */
     public static RenderScript create() {
         RenderScript rs = new RenderScript();
 
@@ -704,15 +757,32 @@
         return rs;
     }
 
+    /**
+     * Print the currently available debugging information about the state of
+     * the RS context to the log.
+     *
+     *
+     * @param bits Currently ignored.
+     */
     public void contextDump(int bits) {
         validate();
         nContextDump(bits);
     }
 
+    /**
+     * Wait for any commands in the fifo between the java bindings and native to
+     * be processed.
+     *
+     */
     public void finish() {
         nContextFinish();
     }
 
+    /**
+     * Destroy this renderscript context.  Once this function is called its no
+     * longer legal to use this or any objects created by this context.
+     *
+     */
     public void destroy() {
         validate();
         nContextDeinitToClient(mContext);
@@ -733,9 +803,6 @@
         return mContext != 0;
     }
 
-    ///////////////////////////////////////////////////////////////////////////////////
-    // Root state
-
     protected int safeID(BaseObj o) {
         if(o != null) {
             return o.getID();
diff --git a/graphics/java/android/renderscript/RenderScriptGL.java b/graphics/java/android/renderscript/RenderScriptGL.java
index cace063..181d4bd 100644
--- a/graphics/java/android/renderscript/RenderScriptGL.java
+++ b/graphics/java/android/renderscript/RenderScriptGL.java
@@ -30,12 +30,22 @@
 /**
  * @hide
  *
+ * The Graphics derivitive of RenderScript.  Extends the basic context to add a
+ * root script which is the display window for graphical output.  When the
+ * system needs to update the display the currently bound root script will be
+ * called.  This script is expected to issue the rendering commands to repaint
+ * the screen.
  **/
 public class RenderScriptGL extends RenderScript {
     private Surface mSurface;
     int mWidth;
     int mHeight;
 
+    /**
+     * Class which is used to describe a pixel format for a graphical buffer.
+     * This is used to describe the intended format of the display surface.
+     *
+     */
     public static class SurfaceConfig {
         int mDepthMin       = 0;
         int mDepthPref      = 0;
diff --git a/graphics/java/android/renderscript/Type.java b/graphics/java/android/renderscript/Type.java
index ad933b8..44aee63 100644
--- a/graphics/java/android/renderscript/Type.java
+++ b/graphics/java/android/renderscript/Type.java
@@ -23,6 +23,20 @@
 /**
  * @hide
  *
+ * Type is an allocation template.  It consists of an Element and one or more
+ * dimensions.  It describes only the layout of memory but does not allocate and
+ * storage for the data thus described.
+ *
+ * A Type consists of several dimensions.  Those are X, Y, Z, LOD (level of
+ * detail), Faces (faces of a cube map).  The X,Y,Z dimensions can be assigned
+ * any positive integral value within the constraints of available memory.  A
+ * single dimension allocation would have an X dimension of greater than zero
+ * while the Y and Z dimensions would be zero to indicate not present.  In this
+ * regard an allocation of x=10, y=1 would be considered 2 dimensionsal while
+ * x=10, y=0 would be considered 1 dimensional.
+ *
+ * The LOD and Faces dimensions are booleans to indicate present or not present.
+ *
  **/
 public class Type extends BaseObj {
     int mDimX;
@@ -33,25 +47,65 @@
     int mElementCount;
     Element mElement;
 
+    /**
+     * Return the element associated with this Type.
+     *
+     * @return Element
+     */
     public Element getElement() {
         return mElement;
     }
 
+    /**
+     * Return the value of the X dimension.
+     *
+     * @return int
+     */
     public int getX() {
         return mDimX;
     }
+
+    /**
+     * Return the value of the Y dimension or 0 for a 1D allocation.
+     *
+     * @return int
+     */
     public int getY() {
         return mDimY;
     }
+
+    /**
+     * Return the value of the Z dimension or 0 for a 1D or 2D allocation.
+     *
+     * @return int
+     */
     public int getZ() {
         return mDimZ;
     }
+
+    /**
+     * Return if the Type has a mipmap chain.
+     *
+     * @return boolean
+     */
     public boolean getLOD() {
         return mDimLOD;
     }
+
+    /**
+     * Return if the Type is a cube map.
+     *
+     * @return boolean
+     */
     public boolean getFaces() {
         return mDimFaces;
     }
+
+    /**
+     * Return the total number of accessable cells in the Type.
+     *
+     * @return int
+     */
     public int getElementCount() {
         return mElementCount;
     }
@@ -122,6 +176,10 @@
         calcElementCount();
     }
 
+    /**
+     * Builder class for Type.
+     *
+     */
     public static class Builder {
         RenderScript mRS;
         Dimension[] mDimensions;
@@ -134,6 +192,12 @@
             int mValue;
         }
 
+        /**
+         * Create a new builder object.
+         *
+         * @param rs
+         * @param e The element for the type to be created.
+         */
         public Builder(RenderScript rs, Element e) {
             if(e.getID() == 0) {
                 throw new RSIllegalArgumentException("Invalid element.");
@@ -145,6 +209,13 @@
             mElement = e;
         }
 
+        /**
+         * Add a dimension to the Type.
+         *
+         *
+         * @param d
+         * @param value
+         */
         public void add(Dimension d, int value) {
             if(value < 1) {
                 throw new RSIllegalArgumentException("Values of less than 1 for Dimensions are not valid.");
@@ -163,6 +234,11 @@
             mEntryCount++;
         }
 
+        /**
+         * Validate structure and create a new type.
+         *
+         * @return Type
+         */
         public Type create() {
             int dims[] = new int[mEntryCount];
             for (int ct=0; ct < mEntryCount; ct++) {
@@ -190,6 +266,26 @@
                     t.mDimFaces = mDimensionValues[ct] != 0;
                 }
             }
+
+            if (t.mDimZ > 0) {
+                if ((t.mDimX < 1) || (t.mDimY < 1)) {
+                    throw new RSInvalidStateException("Both X and Y dimension required when Z is present.");
+                }
+                if (t.mDimFaces) {
+                    throw new RSInvalidStateException("Cube maps not supported with 3D types.");
+                }
+            }
+            if (t.mDimY > 0) {
+                if (t.mDimX < 1) {
+                    throw new RSInvalidStateException("X dimension required when Y is present.");
+                }
+            }
+            if (t.mDimFaces) {
+                if (t.mDimY < 1) {
+                    throw new RSInvalidStateException("Cube maps require 2D Types.");
+                }
+            }
+
             t.calcElementCount();
             return t;
         }
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
index 1081c35..cce2400 100644
--- a/include/media/AudioSystem.h
+++ b/include/media/AudioSystem.h
@@ -472,7 +472,7 @@
     AudioParameter(const String8& keyValuePairs);
     virtual ~AudioParameter();
 
-    // reserved parameter keys for changeing standard parameters with setParameters() function.
+    // reserved parameter keys for changing standard parameters with setParameters() function.
     // Using these keys is mandatory for AudioFlinger to properly monitor audio output/input
     // configuration changes and act accordingly.
     //  keyRouting: to change audio routing, value is an int in AudioSystem::audio_devices
@@ -480,11 +480,14 @@
     //  keyFormat: to change audio format, value is an int in AudioSystem::audio_format
     //  keyChannels: to change audio channel configuration, value is an int in AudioSystem::audio_channels
     //  keyFrameCount: to change audio output frame count, value is an int
+    //  keyInputSource: to change audio input source, value is an int in audio_source
+    //     (defined in media/mediarecorder.h)
     static const char *keyRouting;
     static const char *keySamplingRate;
     static const char *keyFormat;
     static const char *keyChannels;
     static const char *keyFrameCount;
+    static const char *keyInputSource;
 
     String8 toString();
 
diff --git a/include/media/stagefright/MetaData.h b/include/media/stagefright/MetaData.h
index b4c5d3c..295b127 100644
--- a/include/media/stagefright/MetaData.h
+++ b/include/media/stagefright/MetaData.h
@@ -37,7 +37,8 @@
     kKeyStride            = 'strd',  // int32_t
     kKeySliceHeight       = 'slht',  // int32_t
     kKeyChannelCount      = '#chn',  // int32_t
-    kKeySampleRate        = 'srte',  // int32_t (also video frame rate)
+    kKeySampleRate        = 'srte',  // int32_t (audio sampling rate Hz)
+    kKeyFrameRate         = 'frmR',  // int32_t (video frame rate fps)
     kKeyBitRate           = 'brte',  // int32_t (bps)
     kKeyESDS              = 'esds',  // raw data
     kKeyAVCC              = 'avcc',  // raw data
diff --git a/include/ui/InputDispatcher.h b/include/ui/InputDispatcher.h
index d09ff41..15a3925 100644
--- a/include/ui/InputDispatcher.h
+++ b/include/ui/InputDispatcher.h
@@ -219,6 +219,8 @@
      * motion events to be delivered to them with AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED.
      */
     bool isTrustedOverlay() const;
+
+    bool supportsSplitTouch() const;
 };
 
 
@@ -946,7 +948,7 @@
     struct TouchedWindow {
         const InputWindow* window;
         int32_t targetFlags;
-        BitSet32 pointerIds;
+        BitSet32 pointerIds;        // zero unless target flag FLAG_SPLIT is set
         sp<InputChannel> channel;
     };
     struct TouchState {
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 9c845aa..359f334 100644
--- a/libs/rs/java/Balls/src/com/android/balls/BallsRS.java
+++ b/libs/rs/java/Balls/src/com/android/balls/BallsRS.java
@@ -30,7 +30,8 @@
     private RenderScriptGL mRS;
     private ScriptC_balls mScript;
     private ScriptC_ball_physics mPhysicsScript;
-    private ProgramFragment mPF;
+    private ProgramFragment mPFLines;
+    private ProgramFragment mPFPoints;
     private ProgramVertex mPV;
     private ProgramRaster mPR;
     private ProgramStore mPS;
@@ -89,10 +90,13 @@
         pfb.setTexture(ProgramFragment.Builder.EnvMode.MODULATE,
                            ProgramFragment.Builder.Format.RGBA, 0);
         pfb.setVaryingColor(true);
-        mPF = pfb.create();
-        rs.contextBindProgramFragment(mPF);
+        mPFPoints = pfb.create();
 
-        mPF.bindTexture(loadTexture(R.drawable.flares), 0);
+        pfb = new ProgramFragment.Builder(rs);
+        pfb.setVaryingColor(true);
+        mPFLines = pfb.create();
+
+        mPFPoints.bindTexture(loadTexture(R.drawable.flares), 0);
 
         mPoints = new ScriptField_Point(mRS, PART_COUNT);
         mArcs = new ScriptField_Point(mRS, PART_COUNT * 2);
@@ -118,7 +122,8 @@
         mScript.bind_balls1(new ScriptField_Ball(mRS, PART_COUNT));
         mScript.bind_balls2(new ScriptField_Ball(mRS, PART_COUNT));
 
-        mScript.set_gPF(mPF);
+        mScript.set_gPFLines(mPFLines);
+        mScript.set_gPFPoints(mPFPoints);
         createProgramVertex();
         createProgramRaster();
 
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 493633b..bbd03cf 100644
--- a/libs/rs/java/Balls/src/com/android/balls/balls.rs
+++ b/libs/rs/java/Balls/src/com/android/balls/balls.rs
@@ -6,7 +6,8 @@
 
 #pragma stateFragment(parent)
 
-rs_program_fragment gPF;
+rs_program_fragment gPFPoints;
+rs_program_fragment gPFLines;
 rs_program_vertex gPV;
 rs_program_raster gPR;
 rs_program_store gPS;
@@ -93,11 +94,12 @@
     }
 
     frame++;
-    rsgBindProgramFragment(gPF);
+    rsgBindProgramFragment(gPFLines);
     rsgBindProgramVertex(gPV);
     rsgBindProgramRaster(gPR);
     rsgBindProgramStore(gPS);
     rsgDrawMesh(arcMesh, 0, 0, arcIdx);
+    rsgBindProgramFragment(gPFPoints);
     rsgDrawMesh(partMesh);
     rsClearObject(&bc.ain);
     rsClearObject(&bc.aout);
diff --git a/libs/ui/InputDispatcher.cpp b/libs/ui/InputDispatcher.cpp
index 7ddb3c7..db7d448 100644
--- a/libs/ui/InputDispatcher.cpp
+++ b/libs/ui/InputDispatcher.cpp
@@ -157,6 +157,10 @@
             || layoutParamsType == TYPE_SECURE_SYSTEM_OVERLAY;
 }
 
+bool InputWindow::supportsSplitTouch() const {
+    return layoutParamsFlags & InputWindow::FLAG_SPLIT_TOUCH;
+}
+
 
 // --- InputDispatcher ---
 
@@ -1110,8 +1114,7 @@
         }
 
         // Figure out whether splitting will be allowed for this window.
-        if (newTouchedWindow
-                && (newTouchedWindow->layoutParamsFlags & InputWindow::FLAG_SPLIT_TOUCH)) {
+        if (newTouchedWindow && newTouchedWindow->supportsSplitTouch()) {
             // New window supports splitting.
             isSplit = true;
         } else if (isSplit) {
@@ -2648,13 +2651,8 @@
 
                 mTouchState.windows.removeAt(i);
 
-                int32_t newTargetFlags = 0;
-                if (oldTargetFlags & InputTarget::FLAG_FOREGROUND) {
-                    newTargetFlags |= InputTarget::FLAG_FOREGROUND;
-                    if (toWindow->layoutParamsFlags & InputWindow::FLAG_SPLIT_TOUCH) {
-                        newTargetFlags |= InputTarget::FLAG_SPLIT;
-                    }
-                }
+                int32_t newTargetFlags = oldTargetFlags
+                        & (InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_SPLIT);
                 mTouchState.addOrUpdateWindow(toWindow, newTargetFlags, pointerIds);
 
                 found = true;
diff --git a/media/java/android/media/videoeditor/MediaImageItem.java b/media/java/android/media/videoeditor/MediaImageItem.java
index a969ac1..a4b0770 100755
--- a/media/java/android/media/videoeditor/MediaImageItem.java
+++ b/media/java/android/media/videoeditor/MediaImageItem.java
@@ -162,62 +162,41 @@
      * @param durationMs The duration of the image in the storyboard timeline

      */

     public void setDuration(long durationMs) {

-        // Invalidate the beginning and end transitions if necessary

-        if (mBeginTransition != null) {

-            final long transitionDurationMs = mBeginTransition.getDuration();

-

-            // The begin transition must be invalidated if it overlaps with

-            // an effect. To optimize this code we could invalidate the

-            // begin transition only for a Ken Burns effect (color effects

-            // should not affect the begin transition) however when new effects

-            // will be added this code would have to be modified... so we

-            // opted to always invalidate the transition if there is an

-            // overlap.

-            final List<Effect> effects = getAllEffects();

-            for (Effect effect : effects) {

-                // Check if the effect overlaps with the begin transition

-                if (effect.getStartTime() < transitionDurationMs) {

-                    mBeginTransition.invalidate();

-                    break;

-                }

-            }

+        if (durationMs == mDurationMs) {

+            return;

         }

 

-        if (mEndTransition != null) {

-            final long transitionDurationMs = mEndTransition.getDuration();

+        // Invalidate the end transitions if necessary.

+        // This invalidation is necessary for the case in which an effect or

+        // an overlay is overlapping with the end transition

+        // (before the duration is changed) and it no longer overlaps with the

+        // transition after the duration is increased.

 

-            // The end transition must be invalidated if it overlaps with

-            // an effect

-            final List<Effect> effects = getAllEffects();

-            for (Effect effect : effects) {

-                // Check if the effect overlaps with the end transition

-                if (effect.getStartTime() + effect.getDuration() >

-                            mDurationMs - transitionDurationMs) {

-                    mEndTransition.invalidate();

-                    break;

-                }

-            }

+        // The beginning transition does not need to be invalidated at this time

+        // because an effect or an overlay overlaps with the beginning

+        // transition, the begin transition is unaffected by a media item

+        // duration change.

+        invalidateEndTransition();

 

-            if (mEndTransition.isGenerated()) {

-                // The end transition must be invalidated if it overlaps with

-                // an overlay

-                final List<Overlay> overlays = getAllOverlays();

-                for (Overlay overlay : overlays) {

-                    // Check if the overlay overlaps with the end transition

-                    if (overlay.getStartTime() + overlay.getDuration() >

-                                mDurationMs - transitionDurationMs) {

-                        mEndTransition.invalidate();

-                        break;

-                    }

-                }

-            }

-        }

-

+        final long oldDurationMs = mDurationMs;

         mDurationMs = durationMs;

 

         adjustTransitions();

         adjustOverlays();

         adjustEffects();

+

+        // Invalidate the beginning and end transitions after adjustments.

+        // This invalidation is necessary for the case in which an effect or

+        // an overlay was not overlapping with the beginning or end transitions

+        // before the setDuration reduces the duration of the media item and

+        // causes an overlap of the beginning and/or end transition with the

+        // effect.

+        // If the duration is growing, the begin transition does not need to

+        // be invalidated since the effects, overlays are not adjusted.

+        if (mDurationMs < oldDurationMs) {

+            invalidateBeginTransition();

+        }

+        invalidateEndTransition();

     }

 

     /*

@@ -278,6 +257,76 @@
     }

 

     /**

+     * Invalidate the begin transition if any effects and overlays overlap

+     * with the begin transition.

+     */

+    private void invalidateBeginTransition() {

+        if (mBeginTransition != null && mBeginTransition.isGenerated()) {

+            final long transitionDurationMs = mBeginTransition.getDuration();

+

+            // The begin transition must be invalidated if it overlaps with

+            // an effect.

+            final List<Effect> effects = getAllEffects();

+            for (Effect effect : effects) {

+                // Check if the effect overlaps with the begin transition

+                if (effect.getStartTime() < transitionDurationMs) {

+                    mBeginTransition.invalidate();

+                    break;

+                }

+            }

+

+            if (mBeginTransition.isGenerated()) {

+                // The end transition must be invalidated if it overlaps with

+                // an overlay.

+                final List<Overlay> overlays = getAllOverlays();

+                for (Overlay overlay : overlays) {

+                    // Check if the overlay overlaps with the end transition

+                    if (overlay.getStartTime() < transitionDurationMs) {

+                        mBeginTransition.invalidate();

+                        break;

+                    }

+                }

+            }

+        }

+    }

+

+    /**

+     * Invalidate the end transition if any effects and overlays overlap

+     * with the end transition.

+     */

+    private void invalidateEndTransition() {

+        if (mEndTransition != null && mEndTransition.isGenerated()) {

+            final long transitionDurationMs = mEndTransition.getDuration();

+

+            // The end transition must be invalidated if it overlaps with

+            // an effect.

+            final List<Effect> effects = getAllEffects();

+            for (Effect effect : effects) {

+                // Check if the effect overlaps with the end transition

+                if (effect.getStartTime() + effect.getDuration() >

+                            mDurationMs - transitionDurationMs) {

+                    mEndTransition.invalidate();

+                    break;

+                }

+            }

+

+            if (mEndTransition.isGenerated()) {

+                // The end transition must be invalidated if it overlaps with

+                // an overlay.

+                final List<Overlay> overlays = getAllOverlays();

+                for (Overlay overlay : overlays) {

+                    // Check if the overlay overlaps with the end transition

+                    if (overlay.getStartTime() + overlay.getDuration() >

+                                mDurationMs - transitionDurationMs) {

+                        mEndTransition.invalidate();

+                        break;

+                    }

+                }

+            }

+        }

+    }

+

+    /**

      * Adjust the start time and/or duration of effects.

      */

     private void adjustEffects() {

diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
index 9c2a8ba..1a3fcd6 100644
--- a/media/libmedia/AudioSystem.cpp
+++ b/media/libmedia/AudioSystem.cpp
@@ -835,6 +835,7 @@
 const char *AudioParameter::keyFormat = "format";
 const char *AudioParameter::keyChannels = "channels";
 const char *AudioParameter::keyFrameCount = "frame_count";
+const char *AudioParameter::keyInputSource = "input_source";
 
 AudioParameter::AudioParameter(const String8& keyValuePairs)
 {
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 5f9b6e6..dadd1db 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -1078,7 +1078,7 @@
     if (mFrameRate == -1) {
         int32_t frameRate = 0;
         CHECK ((*cameraSource)->getFormat()->findInt32(
-                    kKeySampleRate, &frameRate));
+                    kKeyFrameRate, &frameRate));
         LOGI("Frame rate is not explicitly set. Use the current frame "
              "rate (%d fps)", frameRate);
         mFrameRate = frameRate;
@@ -1100,7 +1100,7 @@
 
     sp<MetaData> enc_meta = new MetaData;
     enc_meta->setInt32(kKeyBitRate, videoBitRate);
-    enc_meta->setInt32(kKeySampleRate, mFrameRate);
+    enc_meta->setInt32(kKeyFrameRate, mFrameRate);
 
     switch (mVideoEncoder) {
         case VIDEO_ENCODER_H263:
diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp
index 159d937..b8450fb 100644
--- a/media/libstagefright/CameraSource.cpp
+++ b/media/libstagefright/CameraSource.cpp
@@ -531,7 +531,7 @@
     mMeta->setInt32(kKeyHeight,      mVideoSize.height);
     mMeta->setInt32(kKeyStride,      mVideoSize.width);
     mMeta->setInt32(kKeySliceHeight, mVideoSize.height);
-    mMeta->setInt32(kKeySampleRate,  mVideoFrameRate);
+    mMeta->setInt32(kKeyFrameRate,   mVideoFrameRate);
     return OK;
 }
 
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 3d490c9..8edcd12 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -935,7 +935,7 @@
     int32_t width, height, frameRate, bitRate, stride, sliceHeight;
     bool success = meta->findInt32(kKeyWidth, &width);
     success = success && meta->findInt32(kKeyHeight, &height);
-    success = success && meta->findInt32(kKeySampleRate, &frameRate);
+    success = success && meta->findInt32(kKeyFrameRate, &frameRate);
     success = success && meta->findInt32(kKeyBitRate, &bitRate);
     success = success && meta->findInt32(kKeyStride, &stride);
     success = success && meta->findInt32(kKeySliceHeight, &sliceHeight);
@@ -1155,7 +1155,7 @@
 status_t OMXCodec::setupH263EncoderParameters(const sp<MetaData>& meta) {
     int32_t iFramesInterval, frameRate, bitRate;
     bool success = meta->findInt32(kKeyBitRate, &bitRate);
-    success = success && meta->findInt32(kKeySampleRate, &frameRate);
+    success = success && meta->findInt32(kKeyFrameRate, &frameRate);
     success = success && meta->findInt32(kKeyIFramesInterval, &iFramesInterval);
     CHECK(success);
     OMX_VIDEO_PARAM_H263TYPE h263type;
@@ -1202,7 +1202,7 @@
 status_t OMXCodec::setupMPEG4EncoderParameters(const sp<MetaData>& meta) {
     int32_t iFramesInterval, frameRate, bitRate;
     bool success = meta->findInt32(kKeyBitRate, &bitRate);
-    success = success && meta->findInt32(kKeySampleRate, &frameRate);
+    success = success && meta->findInt32(kKeyFrameRate, &frameRate);
     success = success && meta->findInt32(kKeyIFramesInterval, &iFramesInterval);
     CHECK(success);
     OMX_VIDEO_PARAM_MPEG4TYPE mpeg4type;
@@ -1254,7 +1254,7 @@
 status_t OMXCodec::setupAVCEncoderParameters(const sp<MetaData>& meta) {
     int32_t iFramesInterval, frameRate, bitRate;
     bool success = meta->findInt32(kKeyBitRate, &bitRate);
-    success = success && meta->findInt32(kKeySampleRate, &frameRate);
+    success = success && meta->findInt32(kKeyFrameRate, &frameRate);
     success = success && meta->findInt32(kKeyIFramesInterval, &iFramesInterval);
     CHECK(success);
 
diff --git a/media/libstagefright/codecs/avc/enc/AVCEncoder.cpp b/media/libstagefright/codecs/avc/enc/AVCEncoder.cpp
index a6b179e..e6a0976 100644
--- a/media/libstagefright/codecs/avc/enc/AVCEncoder.cpp
+++ b/media/libstagefright/codecs/avc/enc/AVCEncoder.cpp
@@ -207,7 +207,7 @@
     LOGV("initCheck");
     CHECK(meta->findInt32(kKeyWidth, &mVideoWidth));
     CHECK(meta->findInt32(kKeyHeight, &mVideoHeight));
-    CHECK(meta->findInt32(kKeySampleRate, &mVideoFrameRate));
+    CHECK(meta->findInt32(kKeyFrameRate, &mVideoFrameRate));
     CHECK(meta->findInt32(kKeyBitRate, &mVideoBitRate));
 
     // XXX: Add more color format support
@@ -322,7 +322,7 @@
     mFormat->setInt32(kKeyWidth, mVideoWidth);
     mFormat->setInt32(kKeyHeight, mVideoHeight);
     mFormat->setInt32(kKeyBitRate, mVideoBitRate);
-    mFormat->setInt32(kKeySampleRate, mVideoFrameRate);
+    mFormat->setInt32(kKeyFrameRate, mVideoFrameRate);
     mFormat->setInt32(kKeyColorFormat, mVideoColorFormat);
     mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
     mFormat->setCString(kKeyDecoderComponent, "AVCEncoder");
diff --git a/media/libstagefright/codecs/m4v_h263/enc/M4vH263Encoder.cpp b/media/libstagefright/codecs/m4v_h263/enc/M4vH263Encoder.cpp
index 72611cf..c7a475b 100644
--- a/media/libstagefright/codecs/m4v_h263/enc/M4vH263Encoder.cpp
+++ b/media/libstagefright/codecs/m4v_h263/enc/M4vH263Encoder.cpp
@@ -200,7 +200,7 @@
     LOGV("initCheck");
     CHECK(meta->findInt32(kKeyWidth, &mVideoWidth));
     CHECK(meta->findInt32(kKeyHeight, &mVideoHeight));
-    CHECK(meta->findInt32(kKeySampleRate, &mVideoFrameRate));
+    CHECK(meta->findInt32(kKeyFrameRate, &mVideoFrameRate));
     CHECK(meta->findInt32(kKeyBitRate, &mVideoBitRate));
 
     // XXX: Add more color format support
@@ -299,7 +299,7 @@
     mFormat->setInt32(kKeyWidth, mVideoWidth);
     mFormat->setInt32(kKeyHeight, mVideoHeight);
     mFormat->setInt32(kKeyBitRate, mVideoBitRate);
-    mFormat->setInt32(kKeySampleRate, mVideoFrameRate);
+    mFormat->setInt32(kKeyFrameRate, mVideoFrameRate);
     mFormat->setInt32(kKeyColorFormat, mVideoColorFormat);
 
     mFormat->setCString(kKeyMIMEType, mime);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/PhoneStatusBarService.java b/packages/SystemUI/src/com/android/systemui/statusbar/PhoneStatusBarService.java
index b174973..d3d2285 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/PhoneStatusBarService.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/PhoneStatusBarService.java
@@ -298,7 +298,8 @@
                     | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
                     | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                     | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
-                    | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
+                    | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
+                    | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
                 PixelFormat.TRANSLUCENT);
         lp.gravity = Gravity.TOP | Gravity.FILL_HORIZONTAL;
         lp.y += height * 1.5; // FIXME
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java
index 00b39c5..776b59c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java
@@ -109,7 +109,8 @@
                 height,
                 WindowManager.LayoutParams.TYPE_STATUS_BAR,
                 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
-                    | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING,
+                    | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
+                    | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
                 PixelFormat.RGBX_8888);
         lp.gravity = getStatusBarGravity();
         lp.setTitle("StatusBar");
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/ShirtPocket.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/ShirtPocket.java
index 7ee3c19..09c8cd2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/ShirtPocket.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/ShirtPocket.java
@@ -197,7 +197,8 @@
                 250,
                 WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
                 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
-                    | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
+                    | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
+                    | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
                 PixelFormat.TRANSLUCENT);
         lp.gravity = Gravity.BOTTOM | Gravity.RIGHT;
 //        int pos[] = new int[2];
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java
index 29f0fe2..da44f43 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java
@@ -153,7 +153,8 @@
                 ViewGroup.LayoutParams.WRAP_CONTENT,
                 WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
                 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
-                    | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
+                    | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
+                    | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
                 PixelFormat.TRANSLUCENT);
         lp.gravity = Gravity.BOTTOM | Gravity.RIGHT;
         lp.setTitle("NotificationPanel");
@@ -188,7 +189,8 @@
                 ViewGroup.LayoutParams.WRAP_CONTENT,
                 WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
                 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
-                    | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
+                    | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
+                    | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
                 PixelFormat.TRANSLUCENT);
         lp.gravity = Gravity.BOTTOM | Gravity.RIGHT;
         lp.setTitle("NotificationPeekWindow");
@@ -208,7 +210,8 @@
                 ViewGroup.LayoutParams.WRAP_CONTENT,
                 WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
                 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
-                    | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
+                    | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
+                    | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
                 PixelFormat.TRANSLUCENT);
         lp.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
         lp.setTitle("SystemPanel");
@@ -232,7 +235,8 @@
                     ViewGroup.LayoutParams.WRAP_CONTENT,
                     WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
                     WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
-                        | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
+                        | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
+                        | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
                     PixelFormat.TRANSLUCENT);
             lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
             lp.setTitle("RecentsPanel");
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index 1bded54..71bf956 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -22,6 +22,7 @@
 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
 import static android.view.WindowManager.LayoutParams.FLAG_NEEDS_MENU_KEY;
+import static android.view.WindowManager.LayoutParams.FLAG_SPLIT_TOUCH;
 
 import com.android.internal.view.BaseSurfaceHolder;
 import com.android.internal.view.RootViewSurfaceTaker;
@@ -497,7 +498,8 @@
                 WRAP_CONTENT, WRAP_CONTENT,
                 st.x, st.y, WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG,
                 WindowManager.LayoutParams.FLAG_DITHER
-                | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
+                | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
+                | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
                 st.decorView.mDefaultOpacity);
 
         lp.gravity = st.gravity;
@@ -2164,6 +2166,12 @@
             setFlags(FLAG_SHOW_WALLPAPER, FLAG_SHOW_WALLPAPER&(~getForcedWindowFlags()));
         }
 
+        if (a.getBoolean(com.android.internal.R.styleable.Window_windowEnableSplitTouch,
+                getContext().getApplicationInfo().targetSdkVersion
+                        >= android.os.Build.VERSION_CODES.HONEYCOMB)) {
+            setFlags(FLAG_SPLIT_TOUCH, FLAG_SPLIT_TOUCH&(~getForcedWindowFlags()));
+        }
+
         if (getContext().getApplicationInfo().targetSdkVersion
                 < android.os.Build.VERSION_CODES.HONEYCOMB) {
             addFlags(WindowManager.LayoutParams.FLAG_NEEDS_MENU_KEY);
diff --git a/services/audioflinger/AudioPolicyManagerBase.cpp b/services/audioflinger/AudioPolicyManagerBase.cpp
index edea2c5..b17584a 100644
--- a/services/audioflinger/AudioPolicyManagerBase.cpp
+++ b/services/audioflinger/AudioPolicyManagerBase.cpp
@@ -760,10 +760,8 @@
     AudioParameter param = AudioParameter();
     param.addInt(String8(AudioParameter::keyRouting), (int)inputDesc->mDevice);
 
-    // use Voice Recognition mode or not for this input based on input source
-    int vr_enabled = inputDesc->mInputSource == AUDIO_SOURCE_VOICE_RECOGNITION ? 1 : 0;
-    param.addInt(String8("vr_mode"), vr_enabled);
-    LOGV("AudioPolicyManager::startInput(%d), setting vr_mode to %d", inputDesc->mInputSource, vr_enabled);
+    param.addInt(String8(AudioParameter::keyInputSource), (int)inputDesc->mInputSource);
+    LOGV("AudioPolicyManager::startInput() input source = %d", inputDesc->mInputSource);
 
     mpClientInterface->setParameters(input, param.toString());
 
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index 0d3cfde..4f8862c 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -961,7 +961,12 @@
         // enabled.
         String id = Settings.Secure.getString(mContext.getContentResolver(),
                 Settings.Secure.DEFAULT_INPUT_METHOD);
-        if (id != null && id.length() > 0) {
+        // There is no input method selected, try to choose new applicable input method.
+        if (TextUtils.isEmpty(id) && chooseNewDefaultIMELocked()) {
+            id = Settings.Secure.getString(mContext.getContentResolver(),
+                    Settings.Secure.DEFAULT_INPUT_METHOD);
+        }
+        if (!TextUtils.isEmpty(id)) {
             try {
                 setInputMethodLocked(id, getSelectedInputMethodSubtypeId(id));
             } catch (IllegalArgumentException e) {
@@ -983,8 +988,9 @@
         }
 
         if (id.equals(mCurMethodId)) {
-            if (subtypeId != NOT_A_SUBTYPE_ID) {
-                InputMethodSubtype subtype = info.getSubtypes().get(subtypeId);
+            ArrayList<InputMethodSubtype> subtypes = info.getSubtypes();
+            if (subtypeId >= 0 && subtypeId < subtypes.size()) {
+                InputMethodSubtype subtype = subtypes.get(subtypeId);
                 if (subtype != mCurrentSubtype) {
                     synchronized (mMethodMap) {
                         if (mCurMethod != null) {
@@ -1279,6 +1285,21 @@
         setInputMethodWithSubtype(token, id, NOT_A_SUBTYPE_ID);
     }
 
+    public boolean switchToLastInputMethod(IBinder token) {
+        synchronized (mMethodMap) {
+            Pair<String, String> lastIme = mSettings.getLastInputMethodAndSubtypeLocked();
+            if (lastIme != null) {
+                InputMethodInfo imi = mMethodMap.get(lastIme.first);
+                if (imi != null) {
+                    setInputMethodWithSubtype(token, lastIme.first, getSubtypeIdFromHashCode(
+                            imi, Integer.valueOf(lastIme.second)));
+                    return true;
+                }
+            }
+            return false;
+        }
+    }
+
     private void setInputMethodWithSubtype(IBinder token, String id, int subtypeId) {
         synchronized (mMethodMap) {
             if (token == null) {
@@ -1482,6 +1503,9 @@
                 }
             }
             InputMethodInfo imi = enabled.get(i);
+            if (DEBUG) {
+                Slog.d(TAG, "New default IME was selected: " + imi.getId());
+            }
             resetSelectedInputMethodAndSubtypeLocked(imi.getId());
             return true;
         }
@@ -1785,9 +1809,9 @@
                 // Disabled input method is currently selected, switch to another one.
                 String selId = Settings.Secure.getString(mContext.getContentResolver(),
                         Settings.Secure.DEFAULT_INPUT_METHOD);
-                if (id.equals(selId)) {
-                    resetSelectedInputMethodAndSubtypeLocked(enabledInputMethodsList.size() > 0
-                            ? enabledInputMethodsList.get(0).first : "");
+                if (id.equals(selId) && !chooseNewDefaultIMELocked()) {
+                    Slog.i(TAG, "Can't find new IME, unsetting the current input method.");
+                    resetSelectedInputMethodAndSubtypeLocked("");
                 }
                 // Previous state was enabled.
                 return true;
@@ -1911,7 +1935,7 @@
         // The first subtype applicable to the system locale will be defined as the most applicable
         // subtype.
         if (DEBUG) {
-            Slog.d(TAG, "Applicable InputMethodSubtype was found: " + applicableSubtypeId
+            Slog.d(TAG, "Applicable InputMethodSubtype was found: " + applicableSubtypeId + ","
                     + subtypes.get(applicableSubtypeId).getLocale());
         }
         return applicableSubtypeId;
@@ -1941,6 +1965,20 @@
         return mCurrentSubtype;
     }
 
+    public boolean setCurrentInputMethodSubtype(InputMethodSubtype subtype) {
+        synchronized (mMethodMap) {
+            if (subtype != null && mCurMethodId != null) {
+                InputMethodInfo imi = mMethodMap.get(mCurMethodId);
+                int subtypeId = getSubtypeIdFromHashCode(imi, subtype.hashCode());
+                if (subtypeId != NOT_A_SUBTYPE_ID) {
+                    setInputMethodLocked(mCurMethodId, subtypeId);
+                    return true;
+                }
+            }
+            return false;
+        }
+    }
+
     /**
      * Utility class for putting and getting settings for InputMethod
      * TODO: Move all putters and getters of settings to this class.
diff --git a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
index 374bbb4..a5f3456 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
@@ -480,13 +480,9 @@
             graphics.setTransform(new AffineTransform());
 
             // set the color
-            graphics.setColor(new Color(color));
+            graphics.setColor(new Color(color, true /*alpha*/));
 
-            // set the mode and alpha.
-            int alpha = color >>> 24;
-            float falpha = alpha / 255.f;
-
-            setModeInGraphics(graphics, mode, falpha);
+            setModeInGraphics(graphics, mode);
 
             graphics.fillRect(0, 0, canvasDelegate.mBufferedImage.getWidth(),
                     canvasDelegate.mBufferedImage.getHeight());
@@ -996,15 +992,8 @@
             }
         }
 
-        // need to get the alpha to set it in the composite.
-        float falpha = 1.f;
-
         if (useColorPaint) {
-            g.setColor(new Color(paint.getColor()));
-
-            // the alpha is taken from the alpha channel of the color
-            int alpha = paint.getAlpha();
-            falpha = alpha / 255.f;
+            g.setColor(new Color(paint.getColor(), true /*hasAlpha*/));
         }
 
         int style = paint.getStyle();
@@ -1036,10 +1025,10 @@
         if (xfermodeDelegate instanceof PorterDuffXfermode_Delegate) {
             int mode = ((PorterDuffXfermode_Delegate)xfermodeDelegate).getMode();
 
-            setModeInGraphics(g, mode, falpha);
+            setModeInGraphics(g, mode);
         } else {
             // default mode is src_over
-            g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, falpha));
+            g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
 
             // if xfermode wasn't null, then it's something we don't support. log it.
             if (mLogger != null && xfermodeDelegate != null) {
@@ -1052,36 +1041,36 @@
         return g;
     }
 
-    private static void setModeInGraphics(Graphics2D g, int mode, float falpha) {
+    private static void setModeInGraphics(Graphics2D g, int mode) {
         for (PorterDuff.Mode m : PorterDuff.Mode.values()) {
             if (m.nativeInt == mode) {
-                setModeInGraphics(g, m, falpha);
+                setModeInGraphics(g, m);
                 return;
             }
         }
     }
 
-    private static void setModeInGraphics(Graphics2D g, PorterDuff.Mode mode, float falpha) {
+    private static void setModeInGraphics(Graphics2D g, PorterDuff.Mode mode) {
         switch (mode) {
             case CLEAR:
-                g.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR, falpha));
+                g.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR, 1.0f /*alpha*/));
                 break;
             case DARKEN:
                 break;
             case DST:
-                g.setComposite(AlphaComposite.getInstance(AlphaComposite.DST, falpha));
+                g.setComposite(AlphaComposite.getInstance(AlphaComposite.DST, 1.0f /*alpha*/));
                 break;
             case DST_ATOP:
-                g.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_ATOP, falpha));
+                g.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_ATOP, 1.0f /*alpha*/));
                 break;
             case DST_IN:
-                g.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_IN, falpha));
+                g.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_IN, 1.0f /*alpha*/));
                 break;
             case DST_OUT:
-                g.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_OUT, falpha));
+                g.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_OUT, 1.0f /*alpha*/));
                 break;
             case DST_OVER:
-                g.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_OVER, falpha));
+                g.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_OVER, 1.0f /*alpha*/));
                 break;
             case LIGHTEN:
                 break;
@@ -1090,22 +1079,22 @@
             case SCREEN:
                 break;
             case SRC:
-                g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC, falpha));
+                g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC, 1.0f /*alpha*/));
                 break;
             case SRC_ATOP:
-                g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, falpha));
+                g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 1.0f /*alpha*/));
                 break;
             case SRC_IN:
-                g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_IN, falpha));
+                g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_IN, 1.0f /*alpha*/));
                 break;
             case SRC_OUT:
-                g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OUT, falpha));
+                g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OUT, 1.0f /*alpha*/));
                 break;
             case SRC_OVER:
-                g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, falpha));
+                g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.0f /*alpha*/));
                 break;
             case XOR:
-                g.setComposite(AlphaComposite.getInstance(AlphaComposite.XOR, falpha));
+                g.setComposite(AlphaComposite.getInstance(AlphaComposite.XOR, 1.0f /*alpha*/));
                 break;
         }
     }
@@ -1156,12 +1145,6 @@
                 g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                         RenderingHints.VALUE_INTERPOLATION_BILINEAR);
             }
-
-            if (paintDelegate.getAlpha() != 0xFF) {
-                c = g.getComposite();
-                g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
-                        paintDelegate.getAlpha()/255.f));
-            }
         }
 
         g.drawImage(image, dleft, dtop, dright, dbottom,
diff --git a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
index d83a33b..93f757a 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
@@ -114,10 +114,6 @@
         return mColor;
     }
 
-    public int getAlpha() {
-        return mColor >>> 24;
-    }
-
     public int getTextAlign() {
         return mTextAlign;
     }
@@ -260,7 +256,7 @@
             return 0;
         }
 
-        return delegate.getAlpha();
+        return delegate.mColor >>> 24;
     }
 
     /*package*/ static void setAlpha(Paint thisPaint, int a) {
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeLayoutScene.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeLayoutScene.java
index 5fcb9ff..8b67166 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeLayoutScene.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeLayoutScene.java
@@ -22,6 +22,7 @@
 import com.android.layoutlib.bridge.impl.LayoutSceneImpl;
 
 import java.awt.image.BufferedImage;
+import java.util.Map;
 
 /**
  * An implementation of {@link LayoutScene}.
@@ -52,6 +53,11 @@
     }
 
     @Override
+    public Map<String, String> getDefaultViewPropertyValues(Object viewObject) {
+        return mScene.getDefaultViewPropertyValues(viewObject);
+    }
+
+    @Override
     public SceneResult render() {
 
         synchronized (mBridge) {
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index 79aecff..02db2cf 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -63,6 +63,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.HashMap;
+import java.util.IdentityHashMap;
 import java.util.Map;
 import java.util.TreeMap;
 import java.util.Map.Entry;
@@ -82,6 +83,9 @@
     private final Map<String, Map<String, IResourceValue>> mFrameworkResources;
     private final Map<IStyleResourceValue, IStyleResourceValue> mStyleInheritanceMap;
 
+    private final Map<Object, Map<String, String>> mDefaultPropMaps =
+        new IdentityHashMap<Object, Map<String,String>>();
+
     // maps for dynamically generated id representing style objects (IStyleResourceValue)
     private Map<Integer, IStyleResourceValue> mDynamicIdToStyleMap;
     private Map<IStyleResourceValue, Integer> mStyleToDynamicIdMap;
@@ -180,6 +184,9 @@
         return mLogger;
     }
 
+    public Map<String, String> getDefaultPropMap(Object key) {
+        return mDefaultPropMaps.get(key);
+    }
 
     // ------------- Activity Methods
 
@@ -285,13 +292,16 @@
             return null;
         }
 
-        Object key = null;
+        Map<String, String> defaultPropMap = null;
         if (parser != null) {
-            key = parser.getViewKey();
-        }
-        if (key != null) {
-            String attrs_name = Bridge.resolveResourceValue(attrs);
-            System.out.println("KEY: " + key.toString() + "(" + attrs_name + ")");
+            Object key = parser.getViewKey();
+            if (key != null) {
+                defaultPropMap = mDefaultPropMaps.get(key);
+                if (defaultPropMap == null) {
+                    defaultPropMap = new HashMap<String, String>();
+                    mDefaultPropMaps.put(key, defaultPropMap);
+                }
+            }
         }
 
         boolean[] frameworkAttributes = new boolean[1];
@@ -309,9 +319,6 @@
             customStyle = parser.getAttributeValue(null /* namespace*/, "style");
         }
         if (customStyle != null) {
-            if (key != null) {
-                print("style", customStyle, false);
-            }
             IResourceValue item = findResValue(customStyle, false /*forceFrameworkOnly*/);
 
             if (item instanceof IStyleResourceValue) {
@@ -323,8 +330,8 @@
             // get the name from the int.
             String defStyleName = searchAttr(defStyleAttr);
 
-            if (key != null) {
-                print("style", defStyleName, true);
+            if (defaultPropMap != null) {
+                defaultPropMap.put("style", defStyleName);
             }
 
             // look for the style in the current theme, and its parent:
@@ -385,20 +392,16 @@
                     // if we found a value, we make sure this doesn't reference another value.
                     // So we resolve it.
                     if (resValue != null) {
-                        if (key != null) {
-                            print(name, resValue.getValue(), true);
+                        // put the first default value, before the resolution.
+                        if (defaultPropMap != null) {
+                            defaultPropMap.put(name, resValue.getValue());
                         }
 
                         resValue = resolveResValue(resValue);
-                    } else if (key != null) {
-                        print(name, "<unknown>", true);
                     }
 
                     ta.bridgeSetValue(index, name, resValue);
                 } else {
-                    if (key != null) {
-                        print(name, value, false);
-                    }
                     // there is a value in the XML, but we need to resolve it in case it's
                     // referencing another resource or a theme value.
                     ta.bridgeSetValue(index, name, resolveValue(null, name, value));
@@ -411,15 +414,6 @@
         return ta;
     }
 
-    private void print(String name, String value, boolean isDefault) {
-        System.out.print("\t" + name + " : " + value);
-        if (isDefault) {
-            System.out.println(" (default)");
-        } else {
-            System.out.println("");
-        }
-    }
-
     @Override
     public Looper getMainLooper() {
         return Looper.myLooper();
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutSceneImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutSceneImpl.java
index d8a59ce..b0316a3 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutSceneImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutSceneImpl.java
@@ -665,7 +665,8 @@
 
         ViewInfo result = new ViewInfo(view.getClass().getName(),
                 context.getViewKey(view),
-                view.getLeft(), view.getTop(), view.getRight(), view.getBottom());
+                view.getLeft(), view.getTop(), view.getRight(), view.getBottom(),
+                view, view.getLayoutParams());
 
         if (view instanceof ViewGroup) {
             ViewGroup group = ((ViewGroup) view);
@@ -686,4 +687,8 @@
     public ViewInfo getViewInfo() {
         return mViewInfo;
     }
+
+    public Map<String, String> getDefaultViewPropertyValues(Object viewObject) {
+        return mContext.getDefaultPropMap(viewObject);
+    }
 }