Merge changes I22d9e018,Ib0701fcc,Ibc637918,I9eb7e002,I4adcec73

* changes:
  audioflinger: don't do work in constructor, instead do it in onFirstRef
  audioflinger: enumerate all the possible audio interfaces
  audio/media: convert to using the audio HAL and new audio defs
  libmedia: move AudioParameter out of AudioSystem
  audioflinger: move legacy audio hw/policy out to libhardware_legacy
diff --git a/api/current.txt b/api/current.txt
index ebf3893..c76627f 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -17115,14 +17115,32 @@
 
 package android.speech.tts {
 
+  public abstract class SynthesisRequest {
+    ctor public SynthesisRequest(java.lang.String);
+    method public abstract int audioAvailable(byte[], int, int);
+    method public abstract int completeAudioAvailable(int, int, int, byte[], int, int);
+    method public abstract int done();
+    method public abstract void error();
+    method public java.lang.String getCountry();
+    method public java.lang.String getLanguage();
+    method public abstract int getMaxBufferSize();
+    method public int getPitch();
+    method public int getSpeechRate();
+    method public java.lang.String getText();
+    method public java.lang.String getVariant();
+    method public abstract int start(int, int, int);
+  }
+
   public class TextToSpeech {
     ctor public TextToSpeech(android.content.Context, android.speech.tts.TextToSpeech.OnInitListener);
+    ctor public TextToSpeech(android.content.Context, android.speech.tts.TextToSpeech.OnInitListener, java.lang.String);
     method public int addEarcon(java.lang.String, java.lang.String, int);
     method public int addEarcon(java.lang.String, java.lang.String);
     method public int addSpeech(java.lang.String, java.lang.String, int);
     method public int addSpeech(java.lang.String, java.lang.String);
     method public boolean areDefaultsEnforced();
     method public java.lang.String getDefaultEngine();
+    method public java.util.List<android.speech.tts.TextToSpeech.EngineInfo> getEngines();
     method public java.util.Locale getLanguage();
     method public int isLanguageAvailable(java.util.Locale);
     method public boolean isSpeaking();
@@ -17167,12 +17185,20 @@
     field public static final java.lang.String EXTRA_VOICE_DATA_FILES = "dataFiles";
     field public static final java.lang.String EXTRA_VOICE_DATA_FILES_INFO = "dataFilesInfo";
     field public static final java.lang.String EXTRA_VOICE_DATA_ROOT_DIRECTORY = "dataRoot";
+    field public static final java.lang.String INTENT_ACTION_TTS_SERVICE = "android.intent.action.TTS_SERVICE";
     field public static final java.lang.String KEY_PARAM_PAN = "pan";
     field public static final java.lang.String KEY_PARAM_STREAM = "streamType";
     field public static final java.lang.String KEY_PARAM_UTTERANCE_ID = "utteranceId";
     field public static final java.lang.String KEY_PARAM_VOLUME = "volume";
   }
 
+  public static class TextToSpeech.EngineInfo {
+    ctor public TextToSpeech.EngineInfo();
+    field public int icon;
+    field public java.lang.String label;
+    field public java.lang.String name;
+  }
+
   public static abstract interface TextToSpeech.OnInitListener {
     method public abstract void onInit(int);
   }
@@ -17181,6 +17207,16 @@
     method public abstract void onUtteranceCompleted(java.lang.String);
   }
 
+  public abstract class TextToSpeechService extends android.app.Service {
+    ctor public TextToSpeechService();
+    method public android.os.IBinder onBind(android.content.Intent);
+    method protected abstract java.lang.String[] onGetLanguage();
+    method protected abstract int onIsLanguageAvailable(java.lang.String, java.lang.String, java.lang.String);
+    method protected abstract int onLoadLanguage(java.lang.String, java.lang.String, java.lang.String);
+    method protected abstract void onStop();
+    method protected abstract void onSynthesizeText(android.speech.tts.SynthesisRequest);
+  }
+
 }
 
 package android.telephony {
diff --git a/core/java/android/speech/tts/SynthesisRequest.java b/core/java/android/speech/tts/SynthesisRequest.java
index 515218b..6df9af2 100644
--- a/core/java/android/speech/tts/SynthesisRequest.java
+++ b/core/java/android/speech/tts/SynthesisRequest.java
@@ -24,8 +24,6 @@
  *
  * Alternatively, the engine can provide all the audio at once, by using
  * {@link #completeAudioAvailable}.
- *
- * @hide Pending approval
  */
 public abstract class SynthesisRequest {
 
@@ -92,16 +90,14 @@
     }
 
     /**
-     * Gets the speech rate to use. {@link TextToSpeech.Engine#DEFAULT_RATE} (100)
-     * is the normal rate.
+     * Gets the speech rate to use. The normal rate is 100.
      */
     public int getSpeechRate() {
         return mSpeechRate;
     }
 
     /**
-     * Gets the pitch to use. {@link TextToSpeech.Engine#DEFAULT_PITCH} (100)
-     * is the normal pitch.
+     * Gets the pitch to use. The normal pitch is 100.
      */
     public int getPitch() {
         return mPitch;
diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index e247df8..1d26c22 100755
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -220,8 +220,6 @@
          * extend {@link TextToSpeechService}. Normal applications should not use this intent
          * directly, instead they should talk to the TTS service using the the methods in this
          * class.
-         *
-         * @hide Pending API council approval
          */
         @SdkConstant(SdkConstantType.SERVICE_ACTION)
         public static final String INTENT_ACTION_TTS_SERVICE =
@@ -428,7 +426,7 @@
     private final Bundle mParams = new Bundle();
 
     /**
-     * The constructor for the TextToSpeech class.
+     * The constructor for the TextToSpeech class, using the default TTS engine.
      * This will also initialize the associated TextToSpeech engine if it isn't already running.
      *
      * @param context
@@ -442,7 +440,15 @@
     }
 
     /**
-     * @hide pending approval
+     * The constructor for the TextToSpeech class, using the given TTS engine.
+     * This will also initialize the associated TextToSpeech engine if it isn't already running.
+     *
+     * @param context
+     *            The context this instance is running in.
+     * @param listener
+     *            The {@link TextToSpeech.OnInitListener} that will be called when the
+     *            TextToSpeech engine has initialized.
+     * @param engine Package name of the TTS engine to use.
      */
     public TextToSpeech(Context context, OnInitListener listener, String engine) {
         mContext = context;
@@ -1060,8 +1066,6 @@
      * Gets a list of all installed TTS engines.
      *
      * @return A list of engine info objects. The list can be empty, but will never by {@code null}.
-     *
-     * @hide Pending approval
      */
     public List<EngineInfo> getEngines() {
         PackageManager pm = mContext.getPackageManager();
@@ -1144,7 +1148,6 @@
      * Information about an installed text-to-speech engine.
      *
      * @see TextToSpeech#getEngines
-     * @hide Pending approval
      */
     public static class EngineInfo {
         /**
diff --git a/core/java/android/speech/tts/TextToSpeechService.java b/core/java/android/speech/tts/TextToSpeechService.java
index da97fb4..590e2ef 100644
--- a/core/java/android/speech/tts/TextToSpeechService.java
+++ b/core/java/android/speech/tts/TextToSpeechService.java
@@ -41,8 +41,6 @@
 
 /**
  * Abstract base class for TTS engine implementations.
- *
- * @hide Pending approval
  */
 public abstract class TextToSpeechService extends Service {
 
diff --git a/core/java/android/text/style/TextAppearanceSpan.java b/core/java/android/text/style/TextAppearanceSpan.java
index de929e3..deed713 100644
--- a/core/java/android/text/style/TextAppearanceSpan.java
+++ b/core/java/android/text/style/TextAppearanceSpan.java
@@ -51,10 +51,9 @@
      * to determine the color.  The <code>appearance</code> should be,
      * for example, <code>android.R.style.TextAppearance_Small</code>,
      * and the <code>colorList</code> should be, for example,
-     * <code>android.R.styleable.Theme_textColorDim</code>.
+     * <code>android.R.styleable.Theme_textColorPrimary</code>.
      */
-    public TextAppearanceSpan(Context context, int appearance,
-                              int colorList) {
+    public TextAppearanceSpan(Context context, int appearance, int colorList) {
         ColorStateList textColor;
         
         TypedArray a =
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 7b404b4..1a84175 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -2203,10 +2203,10 @@
     }
 
     /**
-     * Perform dispatching of a {@link #saveHierarchyState freeze()} to only this view,
-     * not to its children.  For use when overriding
-     * {@link #dispatchSaveInstanceState dispatchFreeze()} to allow subclasses to freeze
-     * their own state but not the state of their children.
+     * Perform dispatching of a {@link #saveHierarchyState(android.util.SparseArray)}  freeze()}
+     * to only this view, not to its children.  For use when overriding
+     * {@link #dispatchSaveInstanceState(android.util.SparseArray)}  dispatchFreeze()} to allow
+     * subclasses to freeze their own state but not the state of their children.
      *
      * @param container the container
      */
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index f02daba..20503b7 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -1926,6 +1926,7 @@
     void dispatchDetachedFromWindow() {
         if (mView != null && mView.mAttachInfo != null) {
             mView.dispatchDetachedFromWindow();
+            mAttached = false;
         }
 
         mView = null;
diff --git a/core/java/android/view/inputmethod/InputMethodSubtype.java b/core/java/android/view/inputmethod/InputMethodSubtype.java
index 25f2229..807f6ce 100644
--- a/core/java/android/view/inputmethod/InputMethodSubtype.java
+++ b/core/java/android/view/inputmethod/InputMethodSubtype.java
@@ -60,8 +60,7 @@
         mSubtypeLocale = locale != null ? locale : "";
         mSubtypeMode = mode != null ? mode : "";
         mSubtypeExtraValue = extraValue != null ? extraValue : "";
-        mSubtypeHashCode = hashCodeInternal(mSubtypeNameResId, mSubtypeIconResId, mSubtypeLocale,
-                mSubtypeMode, mSubtypeExtraValue);
+        mSubtypeHashCode = hashCodeInternal(mSubtypeLocale, mSubtypeMode, mSubtypeExtraValue);
     }
 
     InputMethodSubtype(Parcel source) {
@@ -74,8 +73,7 @@
         mSubtypeMode = s != null ? s : "";
         s = source.readString();
         mSubtypeExtraValue = s != null ? s : "";
-        mSubtypeHashCode = hashCodeInternal(mSubtypeNameResId, mSubtypeIconResId, mSubtypeLocale,
-                mSubtypeMode, mSubtypeExtraValue);
+        mSubtypeHashCode = hashCodeInternal(mSubtypeLocale, mSubtypeMode, mSubtypeExtraValue);
     }
 
     /**
@@ -195,9 +193,8 @@
         }
     };
 
-    private static int hashCodeInternal(int nameResId, int iconResId, String locale,
-            String mode, String extraValue) {
-        return Arrays.hashCode(new Object[] {nameResId, iconResId, locale, mode, extraValue});
+    private static int hashCodeInternal(String locale, String mode, String extraValue) {
+        return Arrays.hashCode(new Object[] {locale, mode, extraValue});
     }
 
     /**
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index 71d6080..3e11197 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -219,6 +219,7 @@
     private boolean         mAllowContentAccess = true;
     private boolean         mLoadWithOverviewMode = false;
     private boolean         mEnableSmoothTransition = false;
+    private boolean         mForceUserScalable = false;
 
     // AutoFill Profile data
     /**
@@ -1658,6 +1659,23 @@
         }
     }
 
+    /**
+     * Returns whether the viewport metatag can disable zooming
+     * @hide
+     */
+    public boolean forceUserScalable() {
+        return mForceUserScalable;
+    }
+
+    /**
+     * Sets whether viewport metatag can disable zooming.
+     * @param flag Whether or not to forceably enable user scalable.
+     * @hide
+     */
+    public synchronized void setForceUserScalable(boolean flag) {
+        mForceUserScalable = flag;
+    }
+
     synchronized void setSyntheticLinksEnabled(boolean flag) {
         if (mSyntheticLinksEnabled != flag) {
             mSyntheticLinksEnabled = flag;
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 0271695..09205a5 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -2253,6 +2253,27 @@
         // set the viewport settings from WebKit
         setViewportSettingsFromNative();
 
+        if (mSettings.forceUserScalable()) {
+            mViewportUserScalable = true;
+            if (mViewportInitialScale > 0) {
+                if (mViewportMinimumScale > 0) {
+                    mViewportMinimumScale = Math.min(mViewportMinimumScale,
+                            mViewportInitialScale / 2);
+                }
+                if (mViewportMaximumScale > 0) {
+                    mViewportMaximumScale = Math.max(mViewportMaximumScale,
+                            mViewportInitialScale * 2);
+                }
+            } else {
+                if (mViewportMinimumScale > 0) {
+                    mViewportMinimumScale = Math.min(mViewportMinimumScale, 50);
+                }
+                if (mViewportMaximumScale > 0) {
+                    mViewportMaximumScale = Math.max(mViewportMaximumScale, 200);
+                }
+            }
+        }
+
         // adjust the default scale to match the densityDpi
         float adjust = 1.0f;
         if (mViewportDensityDpi == -1) {
@@ -2589,11 +2610,11 @@
 
     // called by JNI
     private Class<?> getPluginClass(String libName, String clsName) {
-        
+
         if (mWebView == null) {
             return null;
         }
-        
+
         PluginManager pluginManager = PluginManager.getInstance(null);
 
         String pkgName = pluginManager.getPluginsAPKName(libName);
@@ -2601,7 +2622,7 @@
             Log.w(LOGTAG, "Unable to resolve " + libName + " to a plugin APK");
             return null;
         }
-        
+
         try {
             return pluginManager.getPluginClass(pkgName, clsName);
         } catch (NameNotFoundException e) {
@@ -2656,7 +2677,7 @@
         view.mView = pluginView;
         return view;
     }
-    
+
     // called by JNI.  PluginWidget functions for creating an embedded View for
     // the surface drawing model.
     private ViewManager.ChildView addSurface(View pluginView, int x, int y,
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index 1fe6f4b..d8068f9 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -218,15 +218,16 @@
     
     /**
      * An optional argument to supply a maximum width for this view. Only valid if
-     * {@link #setAdjustViewBounds} has been set to true. To set an image to be a maximum of 100 x
-     * 100 while preserving the original aspect ratio, do the following: 1) set adjustViewBounds to
-     * true 2) set maxWidth and maxHeight to 100 3) set the height and width layout params to
-     * WRAP_CONTENT.
+     * {@link #setAdjustViewBounds(boolean)} has been set to true. To set an image to be a maximum
+     * of 100 x 100 while preserving the original aspect ratio, do the following: 1) set
+     * adjustViewBounds to true 2) set maxWidth and maxHeight to 100 3) set the height and width
+     * layout params to WRAP_CONTENT.
      * 
      * <p>
      * Note that this view could be still smaller than 100 x 100 using this approach if the original
      * image is small. To set an image to a fixed size, specify that size in the layout params and
-     * then use {@link #setScaleType} to determine how to fit the image within the bounds.
+     * then use {@link #setScaleType(android.widget.ImageView.ScaleType)} to determine how to fit
+     * the image within the bounds.
      * </p>
      * 
      * @param maxWidth maximum width for this view
@@ -240,15 +241,16 @@
     
     /**
      * An optional argument to supply a maximum height for this view. Only valid if
-     * {@link #setAdjustViewBounds} has been set to true. To set an image to be a maximum of 100 x
-     * 100 while preserving the original aspect ratio, do the following: 1) set adjustViewBounds to
-     * true 2) set maxWidth and maxHeight to 100 3) set the height and width layout params to
-     * WRAP_CONTENT.
+     * {@link #setAdjustViewBounds(boolean)} has been set to true. To set an image to be a
+     * maximum of 100 x 100 while preserving the original aspect ratio, do the following: 1) set
+     * adjustViewBounds to true 2) set maxWidth and maxHeight to 100 3) set the height and width
+     * layout params to WRAP_CONTENT.
      * 
      * <p>
      * Note that this view could be still smaller than 100 x 100 using this approach if the original
      * image is small. To set an image to a fixed size, specify that size in the layout params and
-     * then use {@link #setScaleType} to determine how to fit the image within the bounds.
+     * then use {@link #setScaleType(android.widget.ImageView.ScaleType)} to determine how to fit
+     * the image within the bounds.
      * </p>
      * 
      * @param maxHeight maximum height for this view
@@ -272,8 +274,8 @@
      *
      * <p class="note">This does Bitmap reading and decoding on the UI
      * thread, which can cause a latency hiccup.  If that's a concern,
-     * consider using {@link #setImageDrawable} or
-     * {@link #setImageBitmap} and
+     * consider using {@link #setImageDrawable(android.graphics.drawable.Drawable)} or
+     * {@link #setImageBitmap(android.graphics.Bitmap)} and
      * {@link android.graphics.BitmapFactory} instead.</p>
      *
      * @param resId the resource identifier of the the drawable
@@ -297,8 +299,8 @@
      *
      * <p class="note">This does Bitmap reading and decoding on the UI
      * thread, which can cause a latency hiccup.  If that's a concern,
-     * consider using {@link #setImageDrawable} or
-     * {@link #setImageBitmap} and
+     * consider using {@link #setImageDrawable(android.graphics.drawable.Drawable)} or
+     * {@link #setImageBitmap(android.graphics.Bitmap)} and
      * {@link android.graphics.BitmapFactory} instead.</p>
      *
      * @param uri The Uri of an image
@@ -902,12 +904,12 @@
 
     /**
      * <p>Set the offset of the widget's text baseline from the widget's top
-     * boundary.  This value is overridden by the {@link #setBaselineAlignBottom}
+     * boundary.  This value is overridden by the {@link #setBaselineAlignBottom(boolean)}
      * property.</p>
      *
      * @param baseline The baseline to use, or -1 if none is to be provided.
      *
-     * @see #setBaseline
+     * @see #setBaseline(int) 
      * @attr ref android.R.styleable#ImageView_baseline
      */
     public void setBaseline(int baseline) {
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 4d3aa68..6c5d117 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -60,6 +60,7 @@
 import android.text.SpanWatcher;
 import android.text.Spannable;
 import android.text.SpannableString;
+import android.text.SpannableStringBuilder;
 import android.text.Spanned;
 import android.text.SpannedString;
 import android.text.StaticLayout;
@@ -80,10 +81,13 @@
 import android.text.method.TextKeyListener;
 import android.text.method.TimeKeyListener;
 import android.text.method.TransformationMethod;
+import android.text.method.WordIterator;
 import android.text.style.ClickableSpan;
 import android.text.style.ParagraphStyle;
 import android.text.style.SuggestionSpan;
+import android.text.style.TextAppearanceSpan;
 import android.text.style.URLSpan;
+import android.text.style.UnderlineSpan;
 import android.text.style.UpdateAppearance;
 import android.text.util.Linkify;
 import android.util.AttributeSet;
@@ -127,6 +131,7 @@
 
 import java.io.IOException;
 import java.lang.ref.WeakReference;
+import java.text.BreakIterator;
 import java.util.ArrayList;
 
 /**
@@ -314,6 +319,7 @@
     private int mTextEditSuggestionsBottomWindowLayout, mTextEditSuggestionsTopWindowLayout;
     private int mTextEditSuggestionItemLayout;
     private SuggestionsPopupWindow mSuggestionsPopupWindow;
+    private SuggestionRangeSpan mSuggestionRangeSpan;
 
     private int mCursorDrawableRes;
     private final Drawable[] mCursorDrawable = new Drawable[2];
@@ -8225,13 +8231,20 @@
         return ((minOffset >= selectionStart) && (maxOffset < selectionEnd));
     }
 
+    private static class SuggestionRangeSpan extends UnderlineSpan {
+        // TODO themable, would be nice to make it a child class of TextAppearanceSpan, but
+        // there is no way to have underline and TextAppearanceSpan.
+    }
+
     private class SuggestionsPopupWindow implements OnClickListener {
         private static final int MAX_NUMBER_SUGGESTIONS = 5;
-        private static final long NO_SUGGESTIONS = -1L;
+        private static final int NO_SUGGESTIONS = -1;
         private final PopupWindow mContainer;
         private final ViewGroup[] mSuggestionViews = new ViewGroup[2];
         private final int[] mSuggestionViewLayouts = new int[] {
                 mTextEditSuggestionsBottomWindowLayout, mTextEditSuggestionsTopWindowLayout};
+        private WordIterator mWordIterator;
+        private TextAppearanceSpan[] mHighlightSpans = new TextAppearanceSpan[0];
 
         public SuggestionsPopupWindow() {
             mContainer = new PopupWindow(TextView.this.mContext, null,
@@ -8244,6 +8257,11 @@
             mContainer.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
         }
 
+        private class SuggestionInfo {
+            int suggestionStart, suggestionEnd; // range of suggestion item with replacement text
+            int spanStart, spanEnd; // range in TextView where text should be inserted
+        }
+
         private ViewGroup getViewGroup(boolean under) {
             final int viewIndex = under ? 0 : 1;
             ViewGroup viewGroup = mSuggestionViews[viewIndex];
@@ -8277,6 +8295,7 @@
                                "Inflated TextEdit suggestion item is not a TextView: " + childView);
                     }
 
+                    childView.setTag(new SuggestionInfo());
                     viewGroup.addView(childView);
                     childView.setOnClickListener(this);
                 }
@@ -8299,21 +8318,28 @@
             mContainer.setContentView(viewGroup);
 
             int totalNbSuggestions = 0;
+            int spanUnionStart = mText.length();
+            int spanUnionEnd = 0;
+
             for (int spanIndex = 0; spanIndex < nbSpans; spanIndex++) {
                 SuggestionSpan suggestionSpan = suggestionSpans[spanIndex];
                 final int spanStart = spannable.getSpanStart(suggestionSpan);
                 final int spanEnd = spannable.getSpanEnd(suggestionSpan);
-                final Long spanRange = packRangeInLong(spanStart, spanEnd);
+                spanUnionStart = Math.min(spanStart, spanUnionStart);
+                spanUnionEnd = Math.max(spanEnd, spanUnionEnd);
 
                 String[] suggestions = suggestionSpan.getSuggestions();
                 int nbSuggestions = suggestions.length;
                 for (int suggestionIndex = 0; suggestionIndex < nbSuggestions; suggestionIndex++) {
                     TextView textView = (TextView) viewGroup.getChildAt(totalNbSuggestions);
                     textView.setText(suggestions[suggestionIndex]);
-                    textView.setTag(spanRange);
+                    SuggestionInfo suggestionInfo = (SuggestionInfo) textView.getTag();
+                    suggestionInfo.spanStart = spanStart;
+                    suggestionInfo.spanEnd = spanEnd;
 
                     totalNbSuggestions++;
-                    if (totalNbSuggestions == MAX_NUMBER_SUGGESTIONS) {
+                    if (totalNbSuggestions > MAX_NUMBER_SUGGESTIONS) {
+                        // Also end outer for loop
                         spanIndex = nbSpans;
                         break;
                     }
@@ -8324,8 +8350,18 @@
                 // TODO Replace by final text, use a dedicated layout, add a fade out timer...
                 TextView textView = (TextView) viewGroup.getChildAt(0);
                 textView.setText("No suggestions available");
-                textView.setTag(NO_SUGGESTIONS);
+                SuggestionInfo suggestionInfo = (SuggestionInfo) textView.getTag();
+                suggestionInfo.spanStart = NO_SUGGESTIONS;
                 totalNbSuggestions++;
+            } else {
+                if (mSuggestionRangeSpan == null) mSuggestionRangeSpan = new SuggestionRangeSpan();
+                ((Editable) mText).setSpan(mSuggestionRangeSpan, spanUnionStart, spanUnionEnd,
+                        Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+
+                for (int i = 0; i < totalNbSuggestions; i++) {
+                    final TextView textView = (TextView) viewGroup.getChildAt(i);
+                    highlightTextDifferences(textView, spanUnionStart, spanUnionEnd);
+                }
             }
 
             for (int i = 0; i < MAX_NUMBER_SUGGESTIONS; i++) {
@@ -8338,7 +8374,158 @@
             positionAtCursor();
         }
 
+        private long[] getWordLimits(CharSequence text) {
+            if (mWordIterator == null) mWordIterator = new WordIterator(); // TODO locale
+            mWordIterator.setCharSequence(text);
+
+            // First pass will simply count the number of words to be able to create an array
+            // Not too expensive since previous break positions are cached by the BreakIterator
+            int nbWords = 0;
+            int position = mWordIterator.following(0);
+            while (position != BreakIterator.DONE) {
+                nbWords++;
+                position = mWordIterator.following(position);
+            }
+
+            int index = 0;
+            long[] result = new long[nbWords];
+
+            position = mWordIterator.following(0);
+            while (position != BreakIterator.DONE) {
+                int wordStart = mWordIterator.getBeginning(position);
+                result[index++] = packRangeInLong(wordStart, position);
+                position = mWordIterator.following(position);
+            }
+
+            return result;
+        }
+
+        private TextAppearanceSpan highlightSpan(int index) {
+            final int length = mHighlightSpans.length;
+            if (index < length) {
+                return mHighlightSpans[index];
+            }
+
+            // Assumes indexes are requested in sequence: simply append one more item
+            TextAppearanceSpan[] newArray = new TextAppearanceSpan[length + 1];
+            System.arraycopy(mHighlightSpans, 0, newArray, 0, length);
+            TextAppearanceSpan highlightSpan = new TextAppearanceSpan(mContext,
+                    android.R.style.TextAppearance_SuggestionHighlight);
+            newArray[length] = highlightSpan;
+            mHighlightSpans = newArray;
+            return highlightSpan;
+        }
+
+        private void highlightTextDifferences(TextView textView, int unionStart, int unionEnd) {
+            SuggestionInfo suggestionInfo = (SuggestionInfo) textView.getTag();
+            final int spanStart = suggestionInfo.spanStart;
+            final int spanEnd = suggestionInfo.spanEnd;
+
+            // Remove all text formating by converting to Strings
+            final String text = textView.getText().toString();
+            final String sourceText = mText.subSequence(spanStart, spanEnd).toString();
+
+            long[] sourceWordLimits = getWordLimits(sourceText);
+            long[] wordLimits = getWordLimits(text);
+
+            SpannableStringBuilder ssb = new SpannableStringBuilder();
+            // span [spanStart, spanEnd] is included in union [spanUnionStart, int spanUnionEnd]
+            // The final result is made of 3 parts: the text before, between and after the span
+            // This is the text before, provided for context
+            ssb.append(mText.subSequence(unionStart, spanStart).toString());
+
+            // shift is used to offset spans positions wrt span's beginning
+            final int shift = spanStart - unionStart;
+            suggestionInfo.suggestionStart = shift;
+            suggestionInfo.suggestionEnd = shift + text.length();
+
+            // This is the actual suggestion text, which will be highlighted by the following code
+            ssb.append(text);
+
+            String[] words = new String[wordLimits.length];
+            for (int i = 0; i < wordLimits.length; i++) {
+                int wordStart = extractRangeStartFromLong(wordLimits[i]);
+                int wordEnd = extractRangeEndFromLong(wordLimits[i]);
+                words[i] = text.substring(wordStart, wordEnd);
+            }
+
+            // Highlighted word algorithm is bases on word matching between source and text
+            // Matching words are found from left to right. TODO: change for RTL languages
+            // Characters between matching words are highlighted
+            int previousCommonWordIndex = -1;
+            int nbHighlightSpans = 0;
+            for (int i = 0; i < sourceWordLimits.length; i++) {
+                int wordStart = extractRangeStartFromLong(sourceWordLimits[i]);
+                int wordEnd = extractRangeEndFromLong(sourceWordLimits[i]);
+                String sourceWord = sourceText.substring(wordStart, wordEnd);
+
+                for (int j = previousCommonWordIndex + 1; j < words.length; j++) {
+                    if (sourceWord.equals(words[j])) {
+                        if (j != previousCommonWordIndex + 1) {
+                            int firstDifferentPosition = previousCommonWordIndex < 0 ? 0 :
+                                extractRangeEndFromLong(wordLimits[previousCommonWordIndex]);
+                            int lastDifferentPosition = extractRangeStartFromLong(wordLimits[j]);
+                            ssb.setSpan(highlightSpan(nbHighlightSpans++),
+                                    shift + firstDifferentPosition, shift + lastDifferentPosition,
+                                    Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+                        } else {
+                            // Compare characters between words
+                            int previousSourceWordEnd = i == 0 ? 0 :
+                                extractRangeEndFromLong(sourceWordLimits[i - 1]);
+                            int sourceWordStart = extractRangeStartFromLong(sourceWordLimits[i]);
+                            String sourceSpaces = sourceText.substring(previousSourceWordEnd,
+                                    sourceWordStart);
+
+                            int previousWordEnd = j == 0 ? 0 :
+                                extractRangeEndFromLong(wordLimits[j - 1]);
+                            int currentWordStart = extractRangeStartFromLong(wordLimits[j]);
+                            String textSpaces = text.substring(previousWordEnd, currentWordStart);
+
+                            if (!sourceSpaces.equals(textSpaces)) {
+                                ssb.setSpan(highlightSpan(nbHighlightSpans++),
+                                        shift + previousWordEnd, shift + currentWordStart,
+                                        Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+                            }
+                        }
+                        previousCommonWordIndex = j;
+                        break;
+                    }
+                }
+            }
+
+            // Finally, compare ends of Strings
+            if (previousCommonWordIndex < words.length - 1) {
+                int firstDifferentPosition = previousCommonWordIndex < 0 ? 0 :
+                    extractRangeEndFromLong(wordLimits[previousCommonWordIndex]);
+                int lastDifferentPosition = textView.length();
+                ssb.setSpan(highlightSpan(nbHighlightSpans++),
+                        shift + firstDifferentPosition, shift + lastDifferentPosition,
+                        Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+            } else {
+                int lastSourceWordEnd = sourceWordLimits.length == 0 ? 0 :
+                    extractRangeEndFromLong(sourceWordLimits[sourceWordLimits.length - 1]);
+                String sourceSpaces = sourceText.substring(lastSourceWordEnd, sourceText.length());
+
+                int lastCommonTextWordEnd = previousCommonWordIndex < 0 ? 0 :
+                    extractRangeEndFromLong(wordLimits[previousCommonWordIndex]);
+                String textSpaces = text.substring(lastCommonTextWordEnd, textView.length());
+
+                if (!sourceSpaces.equals(textSpaces) && textSpaces.length() > 0) {
+                    ssb.setSpan(highlightSpan(nbHighlightSpans++),
+                            shift + lastCommonTextWordEnd, shift + textView.length(),
+                            Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+                }
+            }
+
+            // Final part, text after the current suggestion range.
+            ssb.append(mText.subSequence(spanEnd, unionEnd).toString());
+            textView.setText(ssb);
+        }
+
         public void hide() {
+            if ((mText instanceof Editable) && mSuggestionRangeSpan != null) {
+                ((Editable) mText).removeSpan(mSuggestionRangeSpan);
+            }
             mContainer.dismiss();
         }
 
@@ -8346,11 +8533,15 @@
         public void onClick(View view) {
             if (view instanceof TextView) {
                 TextView textView = (TextView) view;
-                Long range = ((Long) view.getTag());
-                if (range != NO_SUGGESTIONS) {
-                    final int spanStart = extractRangeStartFromLong(range);
-                    final int spanEnd = extractRangeEndFromLong(range);
-                    ((Editable) mText).replace(spanStart, spanEnd, textView.getText());
+                SuggestionInfo suggestionInfo = (SuggestionInfo) textView.getTag();
+                final int spanStart = suggestionInfo.spanStart;
+                final int spanEnd = suggestionInfo.spanEnd;
+                if (spanStart != NO_SUGGESTIONS) {
+                    final int suggestionStart = suggestionInfo.suggestionStart;
+                    final int suggestionEnd = suggestionInfo.suggestionEnd;
+                    final String suggestion = textView.getText().subSequence(
+                            suggestionStart, suggestionEnd).toString();
+                    ((Editable) mText).replace(spanStart, spanEnd, suggestion);
                 }
             }
             hide();
diff --git a/core/res/res/drawable-hdpi/text_edit_suggestions_bottom_window.9.png b/core/res/res/drawable-hdpi/text_edit_suggestions_bottom_window.9.png
new file mode 100644
index 0000000..c97514f
--- /dev/null
+++ b/core/res/res/drawable-hdpi/text_edit_suggestions_bottom_window.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/text_edit_suggestions_top_window.9.png b/core/res/res/drawable-hdpi/text_edit_suggestions_top_window.9.png
new file mode 100644
index 0000000..ff6b34a
--- /dev/null
+++ b/core/res/res/drawable-hdpi/text_edit_suggestions_top_window.9.png
Binary files differ
diff --git a/core/res/res/layout/text_edit_suggestion_item.xml b/core/res/res/layout/text_edit_suggestion_item.xml
index a54cad2..ef537d9 100644
--- a/core/res/res/layout/text_edit_suggestion_item.xml
+++ b/core/res/res/layout/text_edit_suggestion_item.xml
@@ -21,7 +21,7 @@
           android:paddingRight="16dip"
           android:paddingTop="8dip"
           android:paddingBottom="8dip"
-          android:layout_gravity="center"
+          android:layout_gravity="left|center_vertical"
           android:textAppearance="?android:attr/textAppearanceMedium"
-          android:textColor="@android:color/black" />
+          android:textColor="@android:color/dim_foreground_light" />
 
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index 9c59cb6..39d2329 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -60,6 +60,7 @@
     <color name="highlighted_text_light">#9983CC39</color>
     <color name="link_text_dark">#5c5cff</color>
     <color name="link_text_light">#0000ee</color>
+    <color name="suggestion_highlight_text">#177bbd</color>
 
     <drawable name="stat_notify_sync_noanim">@drawable/stat_notify_sync_anim0</drawable>
     <drawable name="stat_sys_download_done">@drawable/stat_sys_download_anim0</drawable>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 778d934..501d478 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1659,6 +1659,7 @@
   <public type="attr" name="stopWithTask" />
 
   <public type="style" name="Theme.Holo.Light.NoActionBar" />
+  <public type="style" name="TextAppearance.SuggestionHighlight" />
 
   <public type="attr" name="textSuggestionsWindowStyle" />
   <public type="attr" name="textEditSuggestionsBottomWindowLayout" />
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 8ce35f8..e666698 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -876,6 +876,13 @@
         <item name="android:textSize">30sp</item>
     </style>
 
+     <!-- @hide -->
+     <style name="TextAppearance.SuggestionHighlight">
+         <item name="android:textSize">18sp</item>
+         <item name="android:textColor">@android:color/suggestion_highlight_text</item>
+         <item name="android:textStyle">bold</item>
+     </style>
+
     <!-- Preference Styles -->
 
     <style name="Preference">
diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml
index 4be6995..010e3c3 100644
--- a/core/tests/coretests/AndroidManifest.xml
+++ b/core/tests/coretests/AndroidManifest.xml
@@ -100,6 +100,12 @@
 
     <application android:theme="@style/Theme">
         <uses-library android:name="android.test.runner" />
+        <activity android:name="android.view.ViewAttachTestActivity" android:label="View Attach Test">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
         <activity android:name="StubTestBrowserActivity" android:label="Stubbed Test Browser">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN"/>
diff --git a/core/tests/coretests/res/layout/attach_view_test.xml b/core/tests/coretests/res/layout/attach_view_test.xml
new file mode 100644
index 0000000..42841cb
--- /dev/null
+++ b/core/tests/coretests/res/layout/attach_view_test.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent">
+    <android.view.ViewAttachView
+    android:id="@+id/view_attach_view"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:keepScreenOn="true"/>
+</LinearLayout>
diff --git a/core/tests/coretests/src/android/view/ViewAttachTest.java b/core/tests/coretests/src/android/view/ViewAttachTest.java
new file mode 100644
index 0000000..cff66e4
--- /dev/null
+++ b/core/tests/coretests/src/android/view/ViewAttachTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import android.content.pm.ActivityInfo;
+import android.os.SystemClock;
+import android.test.ActivityInstrumentationTestCase2;
+
+public class ViewAttachTest extends
+        ActivityInstrumentationTestCase2<ViewAttachTestActivity> {
+
+    public ViewAttachTest() {
+        super(ViewAttachTestActivity.class);
+    }
+
+    /**
+     * Make sure that onAttachedToWindow and onDetachedToWindow is called in the
+     * correct order The ViewAttachTestActivity contains a view that will throw
+     * an RuntimeException if onDetachedToWindow and onAttachedToWindow is
+     * called in the wrong order.
+     *
+     * 1. Initiate the activity 2. Perform a series of orientation changes to
+     * the activity (this will force the View hierarchy to be rebuild,
+     * generating onAttachedToWindow and onDetachedToWindow)
+     *
+     * Expected result: No RuntimeException is thrown from the TestView in
+     * ViewFlipperTestActivity.
+     *
+     * @throws Throwable
+     */
+    public void testAttached() throws Throwable {
+        final ViewAttachTestActivity activity = getActivity();
+        for (int i = 0; i < 20; i++) {
+            activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
+            SystemClock.sleep(250);
+            activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
+            SystemClock.sleep(250);
+        }
+    }
+}
diff --git a/core/tests/coretests/src/android/view/ViewAttachTestActivity.java b/core/tests/coretests/src/android/view/ViewAttachTestActivity.java
new file mode 100644
index 0000000..59e25ae
--- /dev/null
+++ b/core/tests/coretests/src/android/view/ViewAttachTestActivity.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import com.android.frameworks.coretests.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class ViewAttachTestActivity extends Activity {
+    public static final String TAG = "OnAttachedTest";
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.attach_view_test);
+    }
+}
diff --git a/core/tests/coretests/src/android/view/ViewAttachView.java b/core/tests/coretests/src/android/view/ViewAttachView.java
new file mode 100644
index 0000000..5af2d8f
--- /dev/null
+++ b/core/tests/coretests/src/android/view/ViewAttachView.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.os.SystemClock;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.View;
+
+/**
+ * A View that will throw a RuntimeException if onAttachedToWindow and
+ * onDetachedFromWindow is called in the wrong order for ViewAttachTest
+ */
+public class ViewAttachView extends View {
+    public static final String TAG = "OnAttachedTest";
+    private boolean attached;
+
+    public ViewAttachView(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        init(attrs, defStyle);
+    }
+
+    public ViewAttachView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init(attrs, 0);
+    }
+
+    public ViewAttachView(Context context) {
+        super(context);
+        init(null, 0);
+    }
+
+    private void init(AttributeSet attrs, int defStyle) {
+        SystemClock.sleep(2000);
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        Log.d(TAG, "onAttachedToWindow");
+        super.onAttachedToWindow();
+        if (attached) {
+            throw new RuntimeException("OnAttachedToWindow called more than once in a row");
+        }
+        attached = true;
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        Log.d(TAG, "onDetachedFromWindow");
+        super.onDetachedFromWindow();
+        if (!attached) {
+            throw new RuntimeException(
+                    "onDetachedFromWindowcalled without prior call to OnAttachedToWindow");
+        }
+        attached = false;
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        super.onDraw(canvas);
+        canvas.drawColor(Color.BLUE);
+    }
+}
diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp
index b752850..c3f2360 100644
--- a/graphics/jni/android_renderscript_RenderScript.cpp
+++ b/graphics/jni/android_renderscript_RenderScript.cpp
@@ -237,7 +237,11 @@
 
     size_t receiveLen;
     uint32_t subID;
-    int id = rsContextGetMessage(con, buf, &receiveLen, &subID, sizeof(buf), true);
+    int id = rsContextGetMessage(con,
+                                 buf, sizeof(buf),
+                                 &receiveLen, sizeof(receiveLen),
+                                 &subID, sizeof(subID),
+                                 true);
     if (!id && receiveLen) {
         LOGV("message receive buffer too small.  %i", receiveLen);
     }
@@ -252,7 +256,11 @@
     jint *ptr = _env->GetIntArrayElements(data, NULL);
     size_t receiveLen;
     uint32_t subID;
-    int id = rsContextGetMessage(con, ptr, &receiveLen, &subID, len * 4, true);
+    int id = rsContextGetMessage(con,
+                                 ptr, len * 4,
+                                 &receiveLen, sizeof(receiveLen),
+                                 &subID, sizeof(subID),
+                                 true);
     if (!id && receiveLen) {
         LOGV("message receive buffer too small.  %i", receiveLen);
     }
@@ -266,7 +274,8 @@
     jint *auxDataPtr = _env->GetIntArrayElements(auxData, NULL);
     size_t receiveLen;
     uint32_t subID;
-    int id = rsContextPeekMessage(con, &receiveLen, &subID, wait);
+    int id = rsContextPeekMessage(con, &receiveLen, sizeof(receiveLen),
+                                  &subID, sizeof(subID), wait);
     auxDataPtr[0] = (jint)subID;
     auxDataPtr[1] = (jint)receiveLen;
     _env->ReleaseIntArrayElements(auxData, auxDataPtr, 0);
@@ -426,7 +435,9 @@
 
     bitmap.lockPixels();
     const void* ptr = bitmap.getPixels();
-    jint id = (jint)rsaAllocationCreateFromBitmap(con, (RsType)type, (RsAllocationMipmapControl)mip, ptr, usage);
+    jint id = (jint)rsaAllocationCreateFromBitmap(con,
+                                                  (RsType)type, (RsAllocationMipmapControl)mip,
+                                                  ptr, bitmap.getSize(), usage);
     bitmap.unlockPixels();
     return id;
 }
@@ -440,7 +451,9 @@
 
     bitmap.lockPixels();
     const void* ptr = bitmap.getPixels();
-    jint id = (jint)rsaAllocationCubeCreateFromBitmap(con, (RsType)type, (RsAllocationMipmapControl)mip, ptr, usage);
+    jint id = (jint)rsaAllocationCubeCreateFromBitmap(con,
+                                                      (RsType)type, (RsAllocationMipmapControl)mip,
+                                                      ptr, bitmap.getSize(), usage);
     bitmap.unlockPixels();
     return id;
 }
diff --git a/include/media/stagefright/MediaErrors.h b/include/media/stagefright/MediaErrors.h
index 6df4d86..1a6d548 100644
--- a/include/media/stagefright/MediaErrors.h
+++ b/include/media/stagefright/MediaErrors.h
@@ -42,6 +42,17 @@
     INFO_DISCONTINUITY     = MEDIA_ERROR_BASE - 13,
 
     ERROR_NO_LICENSE       = MEDIA_ERROR_BASE - 14,
+
+    // Heartbeat Error Codes
+    HEARTBEAT_ERROR_BASE = -3000,
+
+    ERROR_HEARTBEAT_AUTHENTICATION_FAILURE                  = HEARTBEAT_ERROR_BASE,
+    ERROR_HEARTBEAT_NO_ACTIVE_PURCHASE_AGREEMENT            = HEARTBEAT_ERROR_BASE - 1,
+    ERROR_HEARTBEAT_CONCURRENT_PLAYBACK                     = HEARTBEAT_ERROR_BASE - 2,
+    ERROR_HEARTBEAT_UNUSUAL_ACTIVITY                        = HEARTBEAT_ERROR_BASE - 3,
+    ERROR_HEARTBEAT_STREAMING_UNAVAILABLE                   = HEARTBEAT_ERROR_BASE - 4,
+    ERROR_HEARTBEAT_CANNOT_ACTIVATE_RENTAL                  = HEARTBEAT_ERROR_BASE - 5,
+    ERROR_HEARTBEAT_TERMINATE_REQUESTED                     = HEARTBEAT_ERROR_BASE - 6,
 };
 
 }  // namespace android
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index 26e240f..6c4a2a9 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -53,6 +53,23 @@
     }
 
     /**
+     * Sets this layer's region to a rectangle. Computes the appropriate
+     * texture coordinates.
+     */
+    void setRegionAsRect() {
+        const android::Rect& bounds = region.getBounds();
+        regionRect.set(bounds.leftTop().x, bounds.leftTop().y,
+               bounds.rightBottom().x, bounds.rightBottom().y);
+
+        const float texX = 1.0f / float(width);
+        const float texY = 1.0f / float(height);
+        const float height = layer.getHeight();
+        texCoords.set(
+               regionRect.left * texX, (height - regionRect.top) * texY,
+               regionRect.right * texX, (height - regionRect.bottom) * texY);
+    }
+
+    /**
      * Bounds of the layer.
      */
     Rect layer;
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index ba110ec..ca1e7ae 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -102,19 +102,7 @@
             mLayer->meshElementCount = 0;
         }
 
-        const android::Rect& bounds = mLayer->region.getBounds();
-        mLayer->regionRect.set(bounds.leftTop().x, bounds.leftTop().y,
-                bounds.rightBottom().x, bounds.rightBottom().y);
-
-        const float texX = 1.0f / float(mLayer->width);
-        const float texY = 1.0f / float(mLayer->height);
-        const float height = mLayer->layer.getHeight();
-        mLayer->texCoords.set(
-                mLayer->regionRect.left * texX,
-                (height - mLayer->regionRect.top) * texY,
-                mLayer->regionRect.right * texX,
-                (height - mLayer->regionRect.bottom) * texY);
-
+        mLayer->setRegionAsRect();
         return;
     }
 
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index dd0cca22..ea42838 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -647,10 +647,10 @@
 void OpenGLRenderer::composeLayerRegion(Layer* layer, const Rect& rect) {
 #if RENDER_LAYERS_AS_REGIONS
     if (layer->region.isRect()) {
-        const android::Rect& bounds = layer->region.getBounds();
-        layer->regionRect.set(bounds.leftTop().x, bounds.leftTop().y,
-                bounds.rightBottom().x, bounds.rightBottom().y);
+        layer->setRegionAsRect();
+
         composeLayerRect(layer, layer->regionRect);
+
         layer->region.clear();
         return;
     }
@@ -979,8 +979,8 @@
     }
 }
 
-void OpenGLRenderer::setupDrawModelViewIdentity() {
-    mCaches.currentProgram->set(mOrthoMatrix, mIdentity, *mSnapshot->transform);
+void OpenGLRenderer::setupDrawModelViewIdentity(bool offset) {
+    mCaches.currentProgram->set(mOrthoMatrix, mIdentity, *mSnapshot->transform, offset);
 }
 
 void OpenGLRenderer::setupDrawModelView(float left, float top, float right, float bottom,
@@ -1389,13 +1389,46 @@
     }
 }
 
-void OpenGLRenderer::drawLinesAsQuads(float *points, int count, bool isAA, bool isHairline,
-        float strokeWidth) {
+void OpenGLRenderer::drawLines(float* points, int count, SkPaint* paint) {
+    if (mSnapshot->isIgnored()) return;
+
+    const bool isAA = paint->isAntiAlias();
+    float strokeWidth = paint->getStrokeWidth() * 0.5f;
+    // A stroke width of 0 has a special meaning in Skia:
+    // it draws a line 1 px wide regardless of current transform
+    bool isHairLine = paint->getStrokeWidth() == 0.0f;
+    int alpha;
+    SkXfermode::Mode mode;
+    int generatedVerticesCount = 0;
     int verticesCount = count;
     if (count > 4) {
         // Polyline: account for extra vertices needed for continous tri-strip
         verticesCount += (count -4);
     }
+
+    getAlphaAndMode(paint, &alpha, &mode);
+    setupDraw();
+    if (isAA) {
+        setupDrawAALine();
+    }
+    setupDrawColor(paint->getColor(), alpha);
+    setupDrawColorFilter();
+    setupDrawShader();
+    if (isAA) {
+        setupDrawBlending(true, mode);
+    } else {
+        setupDrawBlending(mode);
+    }
+    setupDrawProgram();
+    setupDrawModelViewIdentity(true);
+    setupDrawColorUniforms();
+    setupDrawColorFilterUniforms();
+    setupDrawShaderIdentityUniforms();
+
+    if (isHairLine) {
+        // Set a real stroke width to be used in quad construction
+        strokeWidth = .5;
+    }
     if (isAA) {
         // Expand boundary to enable AA calculations on the quad border
         strokeWidth += .5f;
@@ -1407,25 +1440,22 @@
     if (!isAA) {
         setupDrawVertices(vertices);
     } else {
-        AlphaVertex* alphaCoords = aaVertices + gVertexAlphaOffset;
+        void* alphaCoords = ((GLbyte*) aaVertices) + gVertexAlphaOffset;
         // innerProportion is the ratio of the inner (non-AA) port of the line to the total
         // AA stroke width (the base stroke width expanded by a half pixel on either side).
         // This value is used in the fragment shader to determine how to fill fragments.
         float innerProportion = fmax(strokeWidth - 1.0f, 0) / (strokeWidth + .5f);
-        setupDrawAALine((void*) aaVertices, (void*) alphaCoords, innerProportion);
+        setupDrawAALine((void*) aaVertices, alphaCoords, innerProportion);
     }
 
-    int generatedVerticesCount = 0;
     AlphaVertex *prevAAVertex = NULL;
     Vertex *prevVertex = NULL;
     float inverseScaleX = 1.0f;
     float inverseScaleY = 1.0f;
 
-    if (isHairline) {
+    if (isHairLine) {
         // The quad that we use for AA hairlines needs to account for scaling because the line
         // should always be one pixel wide regardless of scale.
-        inverseScaleX = 1.0f;
-        inverseScaleY = 1.0f;
         if (!mSnapshot->transform->isPureTranslate()) {
             Matrix4 *mat = mSnapshot->transform;
             float m00 = mat->data[Matrix4::kScaleX];
@@ -1446,22 +1476,19 @@
         vec2 a(points[i], points[i + 1]);
         vec2 b(points[i + 2], points[i + 3]);
 
-        // Bias to snap to the same pixels as Skia
-        a += 0.375;
-        b += 0.375;
-
         // Find the normal to the line
         vec2 n = (b - a).copyNormalized() * strokeWidth;
-        if (isHairline) {
-            float wideningFactor;
-            if (fabs(n.x) >= fabs(n.y)) {
-                wideningFactor = fabs(1.0f / n.x);
-            } else {
-                wideningFactor = fabs(1.0f / n.y);
+        if (isHairLine) {
+            n *= inverseScaleX;
+            if (isAA) {
+                float wideningFactor;
+                if (fabs(n.x) >= fabs(n.y)) {
+                    wideningFactor = fabs(1.0f / n.x);
+                } else {
+                    wideningFactor = fabs(1.0f / n.y);
+                }
+                n *= wideningFactor;
             }
-            n.x *= inverseScaleX;
-            n.y *= inverseScaleY;
-            n *= wideningFactor;
         }
         float x = n.x;
         n.x = -n.y;
@@ -1525,69 +1552,6 @@
     }
 }
 
-void OpenGLRenderer::drawLines(float* points, int count, SkPaint* paint) {
-    if (mSnapshot->isIgnored()) return;
-
-    const bool isAA = paint->isAntiAlias();
-    const float strokeWidth = paint->getStrokeWidth() * 0.5f;
-    // A stroke width of 0 has a special meaning in Skia:
-    // it draws a line 1 px wide regardless of current transform
-    bool isHairLine = paint->getStrokeWidth() == 0.0f;
-
-    int alpha;
-    SkXfermode::Mode mode;
-    getAlphaAndMode(paint, &alpha, &mode);
-    int generatedVerticesCount = 0;
-
-    setupDraw();
-    if (isAA) {
-        setupDrawAALine();
-    }
-    setupDrawColor(paint->getColor(), alpha);
-    setupDrawColorFilter();
-    setupDrawShader();
-    if (isAA) {
-        setupDrawBlending(true, mode);
-    } else {
-        setupDrawBlending(mode);
-    }
-    setupDrawProgram();
-    setupDrawModelViewIdentity();
-    setupDrawColorUniforms();
-    setupDrawColorFilterUniforms();
-    setupDrawShaderIdentityUniforms();
-
-    if (!isHairLine) {
-        drawLinesAsQuads(points, count, isAA, isHairLine, strokeWidth);
-    } else {
-        if (isAA) {
-            drawLinesAsQuads(points, count, isAA, isHairLine, .5f);
-        } else {
-            int verticesCount = count >> 1;
-            Vertex lines[verticesCount];
-            Vertex* vertices = &lines[0];
-            setupDrawVertices(vertices);
-            for (int i = 0; i < count; i += 4) {
-
-                const float left = fmin(points[i], points[i + 2]);
-                const float right = fmax(points[i], points[i + 2]);
-                const float top = fmin(points[i + 1], points[i + 3]);
-                const float bottom = fmax(points[i + 1], points[i + 3]);
-
-                Vertex::set(vertices++, points[i], points[i + 1]);
-                Vertex::set(vertices++, points[i + 2], points[i + 3]);
-                generatedVerticesCount += 2;
-                dirtyLayer(left, top,
-                        right == left ? left + 1 : right, bottom == top ? top + 1 : bottom,
-                        *mSnapshot->transform);
-            }
-
-            glLineWidth(1.0f);
-            glDrawArrays(GL_LINES, 0, generatedVerticesCount);
-        }
-    }
-}
-
 void OpenGLRenderer::drawPoints(float* points, int count, SkPaint* paint) {
     if (mSnapshot->isIgnored()) return;
 
@@ -1596,8 +1560,13 @@
 
     // A stroke width of 0 has a special meaning in Skia:
     // it draws an unscaled 1px point
+    float strokeWidth = paint->getStrokeWidth();
     const bool isHairLine = paint->getStrokeWidth() == 0.0f;
-
+    if (isHairLine) {
+        // Now that we know it's hairline, we can set the effective width, to be used later
+        strokeWidth = 1.0f;
+    }
+    const float halfWidth = strokeWidth / 2;
     int alpha;
     SkXfermode::Mode mode;
     getAlphaAndMode(paint, &alpha, &mode);
@@ -1609,13 +1578,13 @@
     TextureVertex* vertex = &pointsData[0];
 
     setupDraw();
-    setupDrawPoint(isHairLine ? 1.0f : paint->getStrokeWidth());
+    setupDrawPoint(strokeWidth);
     setupDrawColor(paint->getColor(), alpha);
     setupDrawColorFilter();
     setupDrawShader();
     setupDrawBlending(mode);
     setupDrawProgram();
-    setupDrawModelViewIdentity();
+    setupDrawModelViewIdentity(true);
     setupDrawColorUniforms();
     setupDrawColorFilterUniforms();
     setupDrawPointUniforms();
@@ -1625,6 +1594,11 @@
     for (int i = 0; i < count; i += 2) {
         TextureVertex::set(vertex++, points[i], points[i + 1], 0.0f, 0.0f);
         generatedVerticesCount++;
+        float left = points[i] - halfWidth;
+        float right = points[i] + halfWidth;
+        float top = points[i + 1] - halfWidth;
+        float bottom = points [i + 1] + halfWidth;
+        dirtyLayer(left, top, right, bottom, *mSnapshot->transform);
     }
 
     glDrawArrays(GL_POINTS, 0, generatedVerticesCount);
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 0276095..918e1fb 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -283,19 +283,6 @@
     void drawAlphaBitmap(Texture* texture, float left, float top, SkPaint* paint);
 
     /**
-     * Draws a line as a quad. Called by drawLines() for all cases except hairline without AA.
-     *
-     * @param points The vertices of the lines. Every four entries specifies the x/y points
-     * of a single line segment.
-     * @param count The number of entries in the points array.
-     * @param isAA Whether the line is anti-aliased
-     * @param isHairline Whether the line has strokeWidth==0, which results in the line being
-     * one pixel wide on the display regardless of scale.
-     */
-    void drawLinesAsQuads(float *points, int count, bool isAA, bool isHairline,
-            float strokeWidth);
-
-    /**
      * Draws a textured rectangle with the specified texture. The specified coordinates
      * are transformed by the current snapshot's transform matrix.
      *
@@ -453,7 +440,7 @@
             bool swapSrcDst = false);
     void setupDrawProgram();
     void setupDrawDirtyRegionsDisabled();
-    void setupDrawModelViewIdentity();
+    void setupDrawModelViewIdentity(bool offset = false);
     void setupDrawModelView(float left, float top, float right, float bottom,
             bool ignoreTransform = false, bool ignoreModelView = false);
     void setupDrawModelViewTranslate(float left, float top, float right, float bottom,
diff --git a/libs/hwui/Program.cpp b/libs/hwui/Program.cpp
index 2187f24..972dd87 100644
--- a/libs/hwui/Program.cpp
+++ b/libs/hwui/Program.cpp
@@ -124,8 +124,15 @@
 }
 
 void Program::set(const mat4& projectionMatrix, const mat4& modelViewMatrix,
-        const mat4& transformMatrix) {
+        const mat4& transformMatrix, bool offset) {
     mat4 t(projectionMatrix);
+    if (offset) {
+        // offset screenspace xy by an amount that compensates for typical precision issues
+        // in GPU hardware that tends to paint hor/vert lines in pixels shifted up and to the left.
+        // This offset value is based on an assumption that some hardware may use as little
+        // as 12.4 precision, so we offset by slightly more than 1/16.
+        t.translate(.375, .375, 0);
+    }
     t.multiply(transformMatrix);
     t.multiply(modelViewMatrix);
 
diff --git a/libs/hwui/Program.h b/libs/hwui/Program.h
index afc6f3d..764cb05 100644
--- a/libs/hwui/Program.h
+++ b/libs/hwui/Program.h
@@ -81,7 +81,7 @@
      * transform matrices.
      */
     void set(const mat4& projectionMatrix, const mat4& modelViewMatrix,
-             const mat4& transformMatrix);
+             const mat4& transformMatrix, bool offset = false);
 
     /**
      * Sets the color associated with this shader.
diff --git a/libs/rs/RenderScript.h b/libs/rs/RenderScript.h
index cb6d7e0..f4e3f57 100644
--- a/libs/rs/RenderScript.h
+++ b/libs/rs/RenderScript.h
@@ -26,20 +26,6 @@
 
 #include "RenderScriptDefines.h"
 
-RsDevice rsDeviceCreate();
-void rsDeviceDestroy(RsDevice);
-void rsDeviceSetConfig(RsDevice, RsDeviceParam, int32_t value);
-
-RsContext rsContextCreate(RsDevice, uint32_t version);
-RsContext rsContextCreateGL(RsDevice, uint32_t version,
-                            RsSurfaceConfig sc, uint32_t dpi);
-void rsContextDestroy(RsContext);
-
-RsMessageToClientType rsContextGetMessage(RsContext vrsc, void *data, size_t *receiveLen, uint32_t *subID, size_t bufferLen, bool wait);
-RsMessageToClientType rsContextPeekMessage(RsContext vrsc, size_t *receiveLen, uint32_t *subID, bool wait);
-void rsContextInitToClient(RsContext);
-void rsContextDeinitToClient(RsContext);
-
 //
 // A3D loading and object update code.
 // Should only be called at object creation, not thread safe
@@ -63,18 +49,8 @@
 void rsaElementGetNativeData(RsContext, RsElement, uint32_t *elemData, uint32_t elemDataSize);
 void rsaElementGetSubElements(RsContext, RsElement, uint32_t *ids, const char **names, uint32_t dataSize);
 
-// Async commands for returning new IDS
-RsType rsaTypeCreate(RsContext, RsElement, uint32_t dimX, uint32_t dimY,
-                     uint32_t dimZ, bool mips, bool faces);
-RsAllocation rsaAllocationCreateTyped(RsContext rsc, RsType vtype,
-                                      RsAllocationMipmapControl mips,
-                                      uint32_t usages);
-RsAllocation rsaAllocationCreateFromBitmap(RsContext con, RsType vtype,
-                                           RsAllocationMipmapControl mips,
-                                           const void *data, uint32_t usages);
-RsAllocation rsaAllocationCubeCreateFromBitmap(RsContext con, RsType vtype,
-                                               RsAllocationMipmapControl mips,
-                                               const void *data, uint32_t usages);
+
+
 #ifdef ANDROID_RS_SERIALIZE
 #define NO_RS_FUNCS
 #endif
diff --git a/libs/rs/rs.spec b/libs/rs/rs.spec
index dac5cec..998296b 100644
--- a/libs/rs/rs.spec
+++ b/libs/rs/rs.spec
@@ -1,4 +1,110 @@
 
+DeviceCreate {
+    direct
+    nocontext
+    ret RsDevice
+}
+
+DeviceDestroy {
+    direct
+    nocontext
+    param RsDevice dev
+}
+
+DeviceSetConfig {
+    direct
+    nocontext
+    param RsDevice dev
+    param RsDeviceParam p
+    param int32_t value
+}
+
+ContextCreate {
+    direct
+    nocontext
+    param RsDevice dev
+    param uint32_t version
+    ret RsContext
+}
+
+ContextCreateGL {
+    direct
+    nocontext
+    param RsDevice dev
+    param uint32_t version
+    param RsSurfaceConfig sc
+    param uint32_t dpi
+    ret RsContext
+}
+
+ContextDestroy {
+    direct
+}
+
+ContextGetMessage {
+    direct
+    param void *data
+    param size_t *receiveLen
+    param uint32_t *subID
+    param bool wait
+    ret RsMessageToClientType
+}
+
+ContextPeekMessage {
+    direct
+    param size_t *receiveLen
+    param uint32_t *subID
+    param bool wait
+    ret RsMessageToClientType
+}
+
+ContextInitToClient {
+    direct
+}
+
+ContextDeinitToClient {
+    direct
+}
+
+aTypeCreate {
+    direct
+    param RsElement e
+    param uint32_t dimX
+    param uint32_t dimY
+    param uint32_t dimZ
+    param bool mips
+    param bool faces
+    ret RsType
+}
+
+aAllocationCreateTyped {
+    direct
+    param RsType vtype
+    param RsAllocationMipmapControl mips
+    param uint32_t usages
+    ret RsAllocation
+}
+
+aAllocationCreateFromBitmap {
+    direct
+    param RsType vtype
+    param RsAllocationMipmapControl mips
+    param const void *data
+    param uint32_t usages
+    ret RsAllocation
+}
+
+aAllocationCubeCreateFromBitmap {
+    direct
+    param RsType vtype
+    param RsAllocationMipmapControl mips
+    param const void *data
+    param uint32_t usages
+    ret RsAllocation
+}
+
+
+
 ContextFinish {
 	handcodeApi
 	}
@@ -82,23 +188,21 @@
 
 
 Allocation1DData {
+	handcodeApi
 	param RsAllocation va
 	param uint32_t xoff
 	param uint32_t lod
 	param uint32_t count
 	param const void *data
-	handcodeApi
-	togglePlay
 	}
 
 Allocation1DElementData {
+	handcodeApi
 	param RsAllocation va
 	param uint32_t x
 	param uint32_t lod
 	param const void *data
 	param uint32_t comp_offset
-	handcodeApi
-	togglePlay
 	}
 
 Allocation2DData {
@@ -186,11 +290,10 @@
 	}
 
 ScriptInvokeV {
+	handcodeApi
 	param RsScript s
 	param uint32_t slot
 	param const void * data
-	handcodeApi
-	togglePlay
 	}
 
 ScriptSetVarI {
@@ -224,11 +327,10 @@
 	}
 
 ScriptSetVarV {
+	handcodeApi
 	param RsScript s
 	param uint32_t slot
 	param const void * data
-	handcodeApi
-	togglePlay
 	}
 
 
@@ -330,3 +432,4 @@
 MeshInitVertexAttribs {
 	param RsMesh mesh
 	}
+
diff --git a/libs/rs/rsAllocation.cpp b/libs/rs/rsAllocation.cpp
index a759004..743b2c4 100644
--- a/libs/rs/rsAllocation.cpp
+++ b/libs/rs/rsAllocation.cpp
@@ -833,7 +833,7 @@
 
 RsAllocation rsaAllocationCreateFromBitmap(RsContext con, RsType vtype,
                                            RsAllocationMipmapControl mips,
-                                           const void *data, uint32_t usages) {
+                                           const void *data, size_t data_length, uint32_t usages) {
     Context *rsc = static_cast<Context *>(con);
     Type *t = static_cast<Type *>(vtype);
 
@@ -855,7 +855,7 @@
 
 RsAllocation rsaAllocationCubeCreateFromBitmap(RsContext con, RsType vtype,
                                                RsAllocationMipmapControl mips,
-                                               const void *data, uint32_t usages) {
+                                               const void *data, size_t data_length, uint32_t usages) {
     Context *rsc = static_cast<Context *>(con);
     Type *t = static_cast<Type *>(vtype);
 
diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp
index 0ca892d..50f5f55 100644
--- a/libs/rs/rsContext.cpp
+++ b/libs/rs/rsContext.cpp
@@ -768,14 +768,20 @@
     return rsc;
 }
 
-RsMessageToClientType rsContextPeekMessage(RsContext vrsc, size_t *receiveLen, uint32_t *subID, bool wait) {
+RsMessageToClientType rsContextPeekMessage(RsContext vrsc,
+                                           size_t * receiveLen, size_t receiveLen_length,
+                                           uint32_t * subID, size_t subID_length, bool wait) {
     Context * rsc = static_cast<Context *>(vrsc);
     return rsc->peekMessageToClient(receiveLen, subID, wait);
 }
 
-RsMessageToClientType rsContextGetMessage(RsContext vrsc, void *data, size_t *receiveLen, uint32_t *subID, size_t bufferLen, bool wait) {
+RsMessageToClientType rsContextGetMessage(RsContext vrsc, void * data, size_t data_length,
+                                          size_t * receiveLen, size_t receiveLen_length,
+                                          uint32_t * subID, size_t subID_length, bool wait) {
     Context * rsc = static_cast<Context *>(vrsc);
-    return rsc->getMessageToClient(data, receiveLen, subID, bufferLen, wait);
+    rsAssert(subID_length == sizeof(uint32_t));
+    rsAssert(receiveLen_length == sizeof(size_t));
+    return rsc->getMessageToClient(data, receiveLen, subID, data_length, wait);
 }
 
 void rsContextInitToClient(RsContext vrsc) {
diff --git a/libs/rs/rsg_generator.c b/libs/rs/rsg_generator.c
index 4ac5b7f..14b380a 100644
--- a/libs/rs/rsg_generator.c
+++ b/libs/rs/rsg_generator.c
@@ -4,7 +4,7 @@
 
 void printFileHeader(FILE *f) {
     fprintf(f, "/*\n");
-    fprintf(f, " * Copyright (C) 2010 The Android Open Source Project\n");
+    fprintf(f, " * Copyright (C) 2011 The Android Open Source Project\n");
     fprintf(f, " *\n");
     fprintf(f, " * Licensed under the Apache License, Version 2.0 (the \"License\");\n");
     fprintf(f, " * you may not use this file except in compliance with the License.\n");
@@ -96,12 +96,14 @@
 void printFuncDecl(FILE *f, const ApiEntry *api, const char *prefix, int addContext) {
     printVarType(f, &api->ret);
     fprintf(f, " %s%s (", prefix, api->name);
-    if (addContext) {
-        fprintf(f, "Context *");
-    } else {
-        fprintf(f, "RsContext rsc");
+    if (!api->nocontext) {
+        if (addContext) {
+            fprintf(f, "Context *");
+        } else {
+            fprintf(f, "RsContext rsc");
+        }
     }
-    printArgList(f, api, 1);
+    printArgList(f, api, !api->nocontext);
     fprintf(f, ")");
 }
 
@@ -117,6 +119,10 @@
 void printPlaybackFuncs(FILE *f, const char *prefix) {
     int ct;
     for (ct=0; ct < apiCount; ct++) {
+        if (apis[ct].direct) {
+            continue;
+        }
+
         fprintf(f, "void %s%s (Context *, const void *);\n", prefix, apis[ct].name);
     }
 }
@@ -140,6 +146,10 @@
         int needFlush = 0;
         const ApiEntry * api = &apis[ct];
 
+        if (api->direct) {
+            continue;
+        }
+
         printFuncDecl(f, api, "rs", 0);
         fprintf(f, "\n{\n");
         if (api->handcodeApi) {
@@ -198,31 +208,37 @@
     for (ct=0; ct < apiCount; ct++) {
         const ApiEntry * api = &apis[ct];
 
+        if (api->direct) {
+            continue;
+        }
+
         fprintf(f, "void rsp_%s(Context *con, const void *vp)\n", api->name);
         fprintf(f, "{\n");
-        if (api->handcodePlay) {
-            fprintf(f, "    rsHCPLAY_%s(con, vp);\n", api->name);
-        } else {
-            //fprintf(f, "    LOGE(\"play command %s\\n\");\n", api->name);
-            fprintf(f, "    const RS_CMD_%s *cmd = static_cast<const RS_CMD_%s *>(vp);\n", api->name, api->name);
-            fprintf(f, "    ");
-            if (api->ret.typeName[0]) {
-                fprintf(f, "con->mIO.mToCoreRet = (intptr_t)");
-            }
-            fprintf(f, "rsi_%s(con", api->name);
-            for (ct2=0; ct2 < api->paramCount; ct2++) {
-                const VarType *vt = &api->params[ct2];
-                fprintf(f, ",\n           cmd->%s", vt->name);
-            }
-            fprintf(f, ");\n");
+
+        //fprintf(f, "    LOGE(\"play command %s\\n\");\n", api->name);
+        fprintf(f, "    const RS_CMD_%s *cmd = static_cast<const RS_CMD_%s *>(vp);\n", api->name, api->name);
+        fprintf(f, "    ");
+        if (api->ret.typeName[0]) {
+            fprintf(f, "con->mIO.mToCoreRet = (intptr_t)");
         }
+        fprintf(f, "rsi_%s(con", api->name);
+        for (ct2=0; ct2 < api->paramCount; ct2++) {
+            const VarType *vt = &api->params[ct2];
+            fprintf(f, ",\n           cmd->%s", vt->name);
+        }
+        fprintf(f, ");\n");
+
         fprintf(f, "};\n\n");
     }
 
     fprintf(f, "RsPlaybackFunc gPlaybackFuncs[%i] = {\n", apiCount + 1);
     fprintf(f, "    NULL,\n");
     for (ct=0; ct < apiCount; ct++) {
-        fprintf(f, "    %s%s,\n", "rsp_", apis[ct].name);
+        if (apis[ct].direct) {
+            fprintf(f, "    NULL,\n");
+        } else {
+            fprintf(f, "    %s%s,\n", "rsp_", apis[ct].name);
+        }
     }
     fprintf(f, "};\n");
 
diff --git a/libs/rs/spec.h b/libs/rs/spec.h
index 82650a7..ecc5cc7 100644
--- a/libs/rs/spec.h
+++ b/libs/rs/spec.h
@@ -25,7 +25,8 @@
   char name[256];
   int sync;
   int handcodeApi;
-  int handcodePlay;
+  int direct;
+  int nocontext;
   int paramCount;
   VarType ret;
   VarType params[16];
diff --git a/libs/rs/spec.l b/libs/rs/spec.l
index c8af891..dcd4435 100644
--- a/libs/rs/spec.l
+++ b/libs/rs/spec.l
@@ -44,6 +44,7 @@
 <comment>"*"+"/"        BEGIN(INITIAL);
 
 <*>" "   //printf("found ' '\n");
+<*>"\t"   //printf("found ' '\n");
 <*>"\n"  ++num_lines; //printf("found lf \n");
 
 {ID} {
@@ -64,8 +65,12 @@
     apis[apiCount].handcodeApi = 1;
     }
 
-<api_entry2>"handcodePlay" {
-    apis[apiCount].handcodePlay = 1;
+<api_entry2>"direct" {
+    apis[apiCount].direct = 1;
+    }
+
+<api_entry2>"nocontext" {
+    apis[apiCount].nocontext = 1;
     }
 
 <api_entry2>"ret" {
diff --git a/media/libstagefright/SampleTable.cpp b/media/libstagefright/SampleTable.cpp
index 08db902..ef4d3d0 100644
--- a/media/libstagefright/SampleTable.cpp
+++ b/media/libstagefright/SampleTable.cpp
@@ -453,6 +453,10 @@
     }
 
     if (left == mNumSampleSizes) {
+        if (flags == kFlagAfter) {
+            return ERROR_OUT_OF_RANGE;
+        }
+
         --left;
     }
 
diff --git a/media/libstagefright/omx/tests/OMXHarness.cpp b/media/libstagefright/omx/tests/OMXHarness.cpp
index 4f28855..54c0d77 100644
--- a/media/libstagefright/omx/tests/OMXHarness.cpp
+++ b/media/libstagefright/omx/tests/OMXHarness.cpp
@@ -487,14 +487,12 @@
         { "audio/3gpp",
           "file:///sdcard/media_api/video/H263_500_AMRNB_12.3gp" },
         { "audio/amr-wb",
-          "file:///sdcard/media_api/music_perf/AMRWB/"
-          "NIN_AMR-WB_15.85kbps_16kbps.amr" },
+          "file:///sdcard/media_api/music/"
+          "AI_AMR-WB_12.65kbps(13kbps)_16khz_mono_NMC.awb" },
         { "audio/mp4a-latm",
-          "file:///sdcard/media_api/music_perf/AAC/"
-          "WC_AAC_80kbps_32khz_Stereo_1pCBR_SSE.mp4" },
+          "file:///sdcard/media_api/video/H264_AAC.3gp" },
         { "audio/mpeg",
-          "file:///sdcard/media_api/music_perf/MP3/"
-          "WC_256kbps_44.1khz_mono_CBR_DPA.mp3" }
+          "file:///sdcard/media_api/music/MP3CBR.mp3" }
     };
 
     for (size_t i = 0; i < sizeof(kMimeToURL) / sizeof(kMimeToURL[0]); ++i) {
@@ -626,8 +624,10 @@
                      requestedSeekTimeUs, requestedSeekTimeUs / 1E6);
             }
 
-            MediaBuffer *buffer;
-            options.setSeekTo(requestedSeekTimeUs);
+            MediaBuffer *buffer = NULL;
+            options.setSeekTo(
+                    requestedSeekTimeUs, MediaSource::ReadOptions::SEEK_NEXT_SYNC);
+
             if (seekSource->read(&buffer, &options) != OK) {
                 CHECK_EQ(buffer, NULL);
                 actualSeekTimeUs = -1;
diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
index 1ad8047..d96369b 100644
--- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -642,14 +642,16 @@
     }
 
     /**
-     * Installs or removes the accessibility input filter when accessibility is enabled
-     * or disabled.
+     * Sets the input filter state. If the filter is in enabled it is registered
+     * in the window manager, otherwise the filter is removed from the latter.
+     *
+     * @param enabled Whether the input filter is enabled.
      */
-    private void updateInputFilterLocked() {
+    private void setInputFilterEnabledLocked(boolean enabled) {
         WindowManagerService wm = (WindowManagerService)ServiceManager.getService(
                 Context.WINDOW_SERVICE);
         if (wm != null) {
-            if (mIsEnabled) {
+            if (enabled) {
                 if (mInputFilter == null) {
                     mInputFilter = new AccessibilityInputFilter(mContext);
                 }
@@ -681,7 +683,7 @@
         if (enabledServices.size() > 0
                 && service.mFeedbackType == AccessibilityServiceInfo.FEEDBACK_SPOKEN) {
             updateClientsLocked();
-            updateInputFilterLocked();
+            setInputFilterEnabledLocked(true);
         }
     }
 
@@ -697,7 +699,7 @@
         if (enabledServices.isEmpty()
                 && service.mFeedbackType == AccessibilityServiceInfo.FEEDBACK_SPOKEN) {
             updateClientsLocked();
-            updateInputFilterLocked();
+            setInputFilterEnabledLocked(false);
         }
     }
 
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index c4027e0..b2f95cd 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -986,8 +986,16 @@
     ssize_t index = mActiveBufferIndex;
     if (index >= 0) {
         if (!mFailover) {
-            Image& texture(mBufferData[index].texture);
-            err = mTextureManager.initEglImage(&texture, dpy, buffer);
+            {
+               // Without that lock, there is a chance of race condition
+               // where while composing a specific index, requestBuf
+               // with the same index can be executed and touch the same data
+               // that is being used in initEglImage.
+               // (e.g. dirty flag in texture)
+               Mutex::Autolock _l(mLock);
+               Image& texture(mBufferData[index].texture);
+               err = mTextureManager.initEglImage(&texture, dpy, buffer);
+            }
             // if EGLImage fails, we switch to regular texture mode, and we
             // free all resources associated with using EGLImages.
             if (err == NO_ERROR) {
diff --git a/tests/DumpRenderTree/assets/run_page_cycler.py b/tests/DumpRenderTree/assets/run_page_cycler.py
index 692f32e..f995086 100755
--- a/tests/DumpRenderTree/assets/run_page_cycler.py
+++ b/tests/DumpRenderTree/assets/run_page_cycler.py
@@ -33,10 +33,16 @@
   # Include all tests if none are specified.
   if not args:
     print "need a URL, e.g. file:///sdcard/webkit/page_cycler/moz/start.html\?auto=1\&iterations=10"
+    print "  or remote:android-browser-test:80/page_cycler/"
     sys.exit(1)
   else:
     path = ' '.join(args);
 
+  if path[:7] == "remote:":
+    remote_path = path[7:]
+  else:
+    remote_path = None
+
   adb_cmd = "adb ";
   if options.adb_options:
     adb_cmd += options.adb_options
@@ -56,7 +62,20 @@
   run_load_test_cmd_postfix = " -w com.android.dumprendertree/.LayoutTestsAutoRunner"
 
   # Call LoadTestsAutoTest::runTest.
-  run_load_test_cmd = run_load_test_cmd_prefix + " -e class com.android.dumprendertree.LoadTestsAutoTest#runPageCyclerTest -e path \"" + path + "\" -e timeout " + timeout_ms
+  run_load_test_cmd = run_load_test_cmd_prefix + " -e class com.android.dumprendertree.LoadTestsAutoTest#runPageCyclerTest -e timeout " + timeout_ms
+
+  if remote_path:
+    if options.suite:
+      run_load_test_cmd += " -e suite %s -e forward %s " % (options.suite,
+                                                            remote_path)
+    else:
+      print "for network mode, need to specify --suite as well."
+      sys.exit(1)
+    if options.iteration:
+      run_load_test_cmd += " -e iteration %s" % options.iteration
+  else:
+    run_load_test_cmd += " -e path \"%s\" " % path
+
 
   if options.drawtime:
     run_load_test_cmd += " -e drawtime true "
@@ -130,5 +149,15 @@
                            default=None,
                            help="stores rendered page to a location on device.")
 
+  option_parser.add_option("-u", "--suite",
+                           default=None,
+                           help="(for network mode) specify the suite to"
+                           " run by name")
+
+  option_parser.add_option("-i", "--iteration",
+                           default="5",
+                           help="(for network mode) specify how many iterations"
+                           " to run")
+
   options, args = option_parser.parse_args();
   main(options, args)
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoRunner.java b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoRunner.java
index e058f32..3ba3488 100755
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoRunner.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoRunner.java
@@ -25,7 +25,7 @@
 
 /**
  * Instrumentation Test Runner for all DumpRenderTree tests.
- * 
+ *
  * Running all tests:
  *
  * adb shell am instrument \
@@ -57,7 +57,7 @@
                 e.printStackTrace();
             }
         }
-        
+
         String delay_str = (String) icicle.get("delay");
         if(delay_str != null) {
             try {
@@ -66,30 +66,37 @@
             }
         }
 
-        String r = (String)icicle.get("rebaseline");
+        String r = icicle.getString("rebaseline");
         this.mRebaseline = (r != null && r.toLowerCase().equals("true"));
 
-        String logtime = (String) icicle.get("logtime");
+        String logtime = icicle.getString("logtime");
         this.mLogtime = (logtime != null
                 && logtime.toLowerCase().equals("true"));
 
-        String drawTime = (String) icicle.get("drawtime");
+        String drawTime = icicle.getString("drawtime");
         this.mGetDrawTime = (drawTime != null
                 && drawTime.toLowerCase().equals("true"));
 
-        mSaveImagePath = (String) icicle.get("saveimage");
+        mSaveImagePath = icicle.getString("saveimage");
 
-        mJsEngine = (String) icicle.get("jsengine");
+        mJsEngine = icicle.getString("jsengine");
+
+        mPageCyclerSuite = icicle.getString("suite");
+        mPageCyclerForwardHost = icicle.getString("forward");
+        mPageCyclerIteration = icicle.getString("iteration", "5");
 
         super.onCreate(icicle);
     }
-    
-    public String mTestPath;
-    public String mSaveImagePath;
-    public int mTimeoutInMillis;
-    public int mDelay;
-    public boolean mRebaseline;
-    public boolean mLogtime;
-    public boolean mGetDrawTime;
-    public String mJsEngine;
+
+    String mPageCyclerSuite;
+    String mPageCyclerForwardHost;
+    String mPageCyclerIteration;
+    String mTestPath;
+    String mSaveImagePath;
+    int mTimeoutInMillis;
+    int mDelay;
+    boolean mRebaseline;
+    boolean mLogtime;
+    boolean mGetDrawTime;
+    String mJsEngine;
 }
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java
index 050b779..7ac0665 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java
@@ -401,15 +401,6 @@
         activity.setDefaultDumpDataType(DumpDataType.EXT_REPR);
 
         // Run tests.
-        int addr = -1;
-        try{
-            addr = AdbUtils.resolve("android-browser-test.mtv.corp.google.com");
-        } catch (IOException ioe) {
-            Log.w(LOGTAG, "error while resolving test host name", ioe);
-        }
-        if(addr == -1) {
-            Log.w(LOGTAG, "failed to resolve test host. http tests will fail.");
-        }
         for (int i = 0; i < mTestList.size(); i++) {
             String s = mTestList.elementAt(i);
             boolean ignoreResult = mTestListIgnoreResult.elementAt(i);
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java b/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java
index 622fb0e..ee5bb5d 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java
@@ -16,6 +16,9 @@
 
 package com.android.dumprendertree;
 
+import com.android.dumprendertree.forwarder.AdbUtils;
+import com.android.dumprendertree.forwarder.ForwardServer;
+
 import android.app.Instrumentation;
 import android.content.Context;
 import android.content.Intent;
@@ -34,6 +37,8 @@
 import java.io.PrintStream;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 public class LoadTestsAutoTest extends ActivityInstrumentationTestCase2<TestShellActivity> {
 
@@ -41,13 +46,15 @@
     private final static String LOAD_TEST_RESULT =
         Environment.getExternalStorageDirectory() + "/load_test_result.txt";
     private final static int MAX_GC_WAIT_SEC = 10;
+    private final static int LOCAL_PORT = 17171;
     private boolean mFinished;
     static final String LOAD_TEST_RUNNER_FILES[] = {
         "run_page_cycler.py"
     };
+    private ForwardServer mForwardServer;
 
     public LoadTestsAutoTest() {
-        super("com.android.dumprendertree", TestShellActivity.class);
+        super(TestShellActivity.class);
     }
 
     // This function writes the result of the layout test to
@@ -59,14 +66,38 @@
         inst.sendStatus(0, bundle);
     }
 
+    private String setUpForwarding(String forwardInfo, String suite, String iteration) throws IOException {
+        // read forwarding information first
+        Pattern forwardPattern = Pattern.compile("(.*):(\\d+)/(.*)/");
+        Matcher matcher = forwardPattern.matcher(forwardInfo);
+        if (!matcher.matches()) {
+            throw new RuntimeException("Invalid forward information");
+        }
+        String host = matcher.group(1);
+        int port = Integer.parseInt(matcher.group(2));
+        mForwardServer = new ForwardServer(LOCAL_PORT, AdbUtils.resolve(host), port);
+        mForwardServer.start();
+        return String.format("http://127.0.0.1:%d/%s/%s/start.html?auto=1&iterations=%s",
+                LOCAL_PORT, matcher.group(3), suite, iteration);
+    }
+
     // Invokes running of layout tests
     // and waits till it has finished running.
-    public void runPageCyclerTest() {
+    public void runPageCyclerTest() throws IOException {
         LayoutTestsAutoRunner runner = (LayoutTestsAutoRunner) getInstrumentation();
 
+        if (runner.mPageCyclerSuite != null) {
+            // start forwarder to use page cycler suites hosted on external web server
+            if (runner.mPageCyclerForwardHost == null) {
+                throw new RuntimeException("no forwarder information provided");
+            }
+            runner.mTestPath = setUpForwarding(runner.mPageCyclerForwardHost,
+                    runner.mPageCyclerSuite, runner.mPageCyclerIteration);
+            Log.d(LOGTAG, "using path: " + runner.mTestPath);
+        }
+
         if (runner.mTestPath == null) {
-            Log.e(LOGTAG, "No test specified");
-            return;
+            throw new RuntimeException("No test specified");
         }
 
         TestShellActivity activity = (TestShellActivity) getActivity();
@@ -79,6 +110,10 @@
                 runner.mGetDrawTime, runner.mSaveImagePath);
 
         activity.clearCache();
+        if (mForwardServer != null) {
+            mForwardServer.stop();
+            mForwardServer = null;
+        }
         try {
             Thread.sleep(5000);
         } catch (InterruptedException e) {
@@ -92,7 +127,9 @@
     private void freeMem() {
         Log.v(LOGTAG, "freeMem: calling gc...");
         final CountDownLatch latch = new CountDownLatch(1);
+        @SuppressWarnings("unused")
         Object dummy = new Object() {
+            // this object instance is used to track gc
             @Override
             protected void finalize() throws Throwable {
                 latch.countDown();
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/Forwarder.java b/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/Forwarder.java
index a1f3cdf..a971e7b 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/Forwarder.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/Forwarder.java
@@ -36,6 +36,7 @@
     private Socket from, to;
 
     private static final String LOGTAG = "Forwarder";
+    private static final int BUFFER_SIZE = 16384;
 
     public Forwarder (Socket from, Socket to, ForwardServer server) {
         this.server = server;
@@ -90,7 +91,7 @@
                 int length;
                 InputStream is = in.getInputStream();
                 OutputStream os = out.getOutputStream();
-                byte[] buffer = new byte[4096];
+                byte[] buffer = new byte[BUFFER_SIZE];
                 while ((length = is.read(buffer)) > 0) {
                     os.write(buffer, 0, length);
                 }
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index c763b1d..31b2ddd 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -406,6 +406,15 @@
         </activity>
 
         <activity
+                android:name="PointsActivity"
+                android:label="_Points">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
+        <activity
                 android:name="Transform3dActivity"
                 android:label="_3d">
             <intent-filter>
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/Lines2Activity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/Lines2Activity.java
index ccf0631..55fab3f 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/Lines2Activity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/Lines2Activity.java
@@ -42,8 +42,9 @@
         swView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
         frame.addView(swView);
         final LinesView hwBothView = new LinesView(this, 850, Color.GREEN);
-        // BUG: some lines not drawn or drawn with alpha when enabling hw layers
-//        hwBothView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+        // Don't actually need to render to a hw layer, but it's a good sanity-check that
+        // we're rendering to/from layers correctly
+        hwBothView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
         frame.addView(hwBothView);
         final LinesView swBothView = new LinesView(this, 854, Color.RED);
         swBothView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/PointsActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/PointsActivity.java
new file mode 100644
index 0000000..b3fb7a1
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/PointsActivity.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.hwui;
+
+import android.animation.ObjectAnimator;
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.drawable.ColorDrawable;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.FrameLayout;
+import android.widget.LinearLayout;
+import android.widget.ProgressBar;
+import android.widget.SeekBar;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class PointsActivity extends Activity {
+
+    float mSeekValue = .5f;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        getWindow().setBackgroundDrawable(new ColorDrawable(0xff000000));
+        SeekBar slider = new SeekBar(this);
+        LinearLayout container = new LinearLayout(this);
+        container.setOrientation(LinearLayout.VERTICAL);
+        setContentView(container);
+
+        container.addView(slider);
+        slider.setMax(100);
+        slider.setProgress(50);
+        FrameLayout frame = new FrameLayout(this);
+        final RenderingView gpuView = new RenderingView(this, Color.GREEN);
+        frame.addView(gpuView);
+        final RenderingView swView = new RenderingView(this, Color.RED);
+        swView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
+        frame.addView(swView);
+        container.addView(frame);
+
+        slider.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
+            @Override
+            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+                mSeekValue = (float)progress / 100.0f;
+                float gpuAlpha = Math.min(2.0f * mSeekValue, 1f);
+                gpuView.setAlpha(gpuAlpha);
+                float swAlpha = Math.min((1 - mSeekValue) * 2.0f, 1f);
+                System.out.println("(gpuAlpha, swAlpha = " + gpuAlpha + ", " + swAlpha);
+                swView.setAlpha(swAlpha);
+            }
+
+            @Override
+            public void onStartTrackingTouch(SeekBar seekBar) {
+            }
+
+            @Override
+            public void onStopTrackingTouch(SeekBar seekBar) {
+            }
+        });
+    }
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+    }
+
+    public static class RenderingView extends View {
+
+        private int mColor;
+
+        public RenderingView(Context c, int color) {
+            super(c);
+            mColor = color;
+        }
+
+        private void drawPoints(Canvas canvas, Paint p, float xOffset, float yOffset) {
+        }
+
+        @Override
+        protected void onDraw(Canvas canvas) {
+            super.onDraw(canvas);
+            Paint p = new Paint();
+            p.setColor(mColor);
+
+            float yOffset = 0;
+            for (int i = 0; i < 2; ++i) {
+                float xOffset = 0;
+
+                p.setStrokeWidth(0f);
+                p.setStrokeCap(Paint.Cap.SQUARE);
+                canvas.drawPoint(100 + xOffset, 100 + yOffset, p);
+                xOffset += 5;
+
+                p.setStrokeWidth(1f);
+                canvas.drawPoint(100 + xOffset, 100 + yOffset, p);
+                xOffset += 15;
+
+                p.setStrokeWidth(20);
+                canvas.drawPoint(100 + xOffset, 100 + yOffset, p);
+                xOffset += 30;
+
+                p.setStrokeCap(Paint.Cap.ROUND);
+                canvas.drawPoint(100 + xOffset, 100 + yOffset, p);
+
+                p.setAntiAlias(true);
+                yOffset += 30;
+            }
+
+        }
+    }
+}
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java
index 7462701..e776463 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java
@@ -88,9 +88,8 @@
                 }
 
                 // This is a hack to work around an invalidation bug
-                mBitmapOut = Bitmap.createBitmap(mBitmapOut);
+                mBitmapOut.setPixel(0, 0, 0);
                 mOutPixelsAllocation.copyTo(mBitmapOut);
-                mDisplayView.setImageBitmap(mBitmapOut);
                 mDisplayView.invalidate();
             }
         };