Merge changes 9415,9416

* changes:
  log opengl-call-with-no-context only once per thread, instead of for each function call
  don't crash in Parcel when given a null (and therfore invalid) native_handle_t
diff --git a/core/java/android/bluetooth/BluetoothUuid.java b/core/java/android/bluetooth/BluetoothUuid.java
index f8316a5..1ec7fb38 100644
--- a/core/java/android/bluetooth/BluetoothUuid.java
+++ b/core/java/android/bluetooth/BluetoothUuid.java
@@ -30,14 +30,13 @@
      * The following 128 bit values are calculated as:
      *  uuid * 2^96 + BASE_UUID
      */
-    public static final UUID AudioSink = UUID.fromString("0000110A-0000-1000-8000-00805F9B34FB");
-    public static final UUID AudioSource = UUID.fromString("0000110B-0000-1000-8000-00805F9B34FB");
+    public static final UUID AudioSink = UUID.fromString("0000110B-0000-1000-8000-00805F9B34FB");
+    public static final UUID AudioSource = UUID.fromString("0000110A-0000-1000-8000-00805F9B34FB");
     public static final UUID AdvAudioDist = UUID.fromString("0000110D-0000-1000-8000-00805F9B34FB");
     public static final UUID HSP       = UUID.fromString("00001108-0000-1000-8000-00805F9B34FB");
-    public static final UUID HeadsetHS = UUID.fromString("00001131-0000-1000-8000-00805F9B34FB");
-    public static final UUID Handsfree  = UUID.fromString("0000111e-0000-1000-8000-00805F9B34FB");
-    public static final UUID HandsfreeAudioGateway
-                                          = UUID.fromString("0000111f-0000-1000-8000-00805F9B34FB");
+    public static final UUID Handsfree  = UUID.fromString("0000111E-0000-1000-8000-00805F9B34FB");
+    public static final UUID AvrcpController =
+                                          UUID.fromString("0000110E-0000-1000-8000-00805F9B34FB");
 
     public static boolean isAudioSource(UUID uuid) {
         return uuid.equals(AudioSource);
@@ -56,7 +55,10 @@
     }
 
     public static boolean isHeadset(UUID uuid) {
-        return uuid.equals(HSP) || uuid.equals(HeadsetHS);
+        return uuid.equals(HSP);
+    }
+
+    public static boolean isAvrcpController(UUID uuid) {
+        return uuid.equals(AvrcpController);
     }
 }
-
diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java
index dc84d1f..d982777 100644
--- a/core/java/android/server/BluetoothEventLoop.java
+++ b/core/java/android/server/BluetoothEventLoop.java
@@ -402,13 +402,14 @@
 
         boolean authorized = false;
         UUID uuid = UUID.fromString(deviceUuid);
-        if (mBluetoothService.isEnabled() && BluetoothUuid.isAudioSink(uuid)) {
+        if (mBluetoothService.isEnabled() &&
+                (BluetoothUuid.isAudioSink(uuid) || BluetoothUuid.isAvrcpController(uuid))) {
             BluetoothA2dp a2dp = new BluetoothA2dp(mContext);
             authorized = a2dp.getSinkPriority(address) > BluetoothA2dp.PRIORITY_OFF;
             if (authorized) {
-                Log.i(TAG, "Allowing incoming A2DP connection from " + address);
+                Log.i(TAG, "Allowing incoming A2DP / AVRCP connection from " + address);
             } else {
-                Log.i(TAG, "Rejecting incoming A2DP connection from " + address);
+                Log.i(TAG, "Rejecting incoming A2DP / AVRCP connection from " + address);
             }
         } else {
             Log.i(TAG, "Rejecting incoming " + deviceUuid + " connection from " + address);
diff --git a/core/java/android/webkit/WebTextView.java b/core/java/android/webkit/WebTextView.java
index 7bc154b..f22adb7 100644
--- a/core/java/android/webkit/WebTextView.java
+++ b/core/java/android/webkit/WebTextView.java
@@ -81,6 +81,10 @@
     // True if the most recent drag event has caused either the TextView to
     // scroll or the web page to scroll.  Gets reset after a touch down.
     private boolean         mScrolled;
+    // Gets set to true when the the IME jumps to the next textfield.  When this
+    // happens, the next time the user hits a key it is okay for the focus
+    // pointer to not match the WebTextView's node pointer
+    private boolean         mOkayForFocusNotToMatch;
     // Array to store the final character added in onTextChanged, so that its
     // KeyEvents may be determined.
     private char[]          mCharacter = new char[1];
@@ -99,7 +103,6 @@
         super(context);
         mWebView = webView;
         mMaxLength = -1;
-        setImeOptions(EditorInfo.IME_ACTION_NONE);
     }
 
     @Override
@@ -125,8 +128,8 @@
                 isArrowKey = true;
                 break;
         }
-
-        if (!isArrowKey && mWebView.nativeFocusNodePointer() != mNodePointer) {
+        if (!isArrowKey && !mOkayForFocusNotToMatch
+                && mWebView.nativeFocusNodePointer() != mNodePointer) {
             mWebView.nativeClearCursor();
             // Do not call remove() here, which hides the soft keyboard.  If
             // the soft keyboard is being displayed, the user will still want
@@ -135,6 +138,9 @@
             mWebView.requestFocus();
             return mWebView.dispatchKeyEvent(event);
         }
+        // After a jump to next textfield and the first key press, the cursor
+        // and focus will once again match, so reset this value.
+        mOkayForFocusNotToMatch = false;
 
         Spannable text = (Spannable) getText();
         int oldLength = text.length();
@@ -305,6 +311,36 @@
     }
 
     @Override
+    public void onEditorAction(int actionCode) {
+        switch (actionCode) {
+        case EditorInfo.IME_ACTION_NEXT:
+            mWebView.nativeMoveCursorToNextTextInput();
+            // Preemptively rebuild the WebTextView, so that the action will
+            // be set properly.
+            mWebView.rebuildWebTextView();
+            // Since the cursor will no longer be in the same place as the
+            // focus, set the focus controller back to inactive
+            mWebView.setFocusControllerInactive();
+            mOkayForFocusNotToMatch = true;
+            break;
+        case EditorInfo.IME_ACTION_DONE:
+            super.onEditorAction(actionCode);
+            break;
+        case EditorInfo.IME_ACTION_GO:
+            // Send an enter and hide the soft keyboard
+            InputMethodManager.getInstance(mContext)
+                    .hideSoftInputFromWindow(getWindowToken(), 0);
+            sendDomEvent(new KeyEvent(KeyEvent.ACTION_DOWN,
+                    KeyEvent.KEYCODE_ENTER));
+            sendDomEvent(new KeyEvent(KeyEvent.ACTION_UP,
+                    KeyEvent.KEYCODE_ENTER));
+
+        default:
+            break;
+        }
+    }
+
+    @Override
     protected void onSelectionChanged(int selStart, int selEnd) {
         if (mWebView != null) {
             if (DebugFlags.WEB_TEXT_VIEW) {
@@ -659,10 +695,26 @@
     public void setSingleLine(boolean single) {
         int inputType = EditorInfo.TYPE_CLASS_TEXT
                 | EditorInfo.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT;
-        if (!single) {
+        if (single) {
+            int action = mWebView.nativeTextFieldAction();
+            switch (action) {
+            // Keep in sync with CachedRoot::ImeAction
+            case 0: // NEXT
+                setImeOptions(EditorInfo.IME_ACTION_NEXT);
+                break;
+            case 1: // GO
+                setImeOptions(EditorInfo.IME_ACTION_GO);
+                break;
+            case -1: // FAILURE
+            case 2: // DONE
+                setImeOptions(EditorInfo.IME_ACTION_DONE);
+                break;
+            }
+        } else {
             inputType |= EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE
                     | EditorInfo.TYPE_TEXT_FLAG_CAP_SENTENCES
                     | EditorInfo.TYPE_TEXT_FLAG_AUTO_CORRECT;
+            setImeOptions(EditorInfo.IME_ACTION_NONE);
         }
         mSingle = single;
         setHorizontallyScrolling(single);
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 05a7806..3b81eed 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -2292,13 +2292,13 @@
 
     // Scale from content to view coordinates, and pin.
     // Also called by jni webview.cpp
-    private void setContentScrollBy(int cx, int cy, boolean animate) {
+    private boolean setContentScrollBy(int cx, int cy, boolean animate) {
         if (mDrawHistory) {
             // disallow WebView to change the scroll position as History Picture
             // is used in the view system.
             // TODO: as we switchOutDrawHistory when trackball or navigation
             // keys are hit, this should be safe. Right?
-            return;
+            return false;
         }
         cx = contentToView(cx);
         cy = contentToView(cy);
@@ -2315,11 +2315,9 @@
             // FIXME: Why do we only scroll horizontally if there is no
             // vertical scroll?
 //                Log.d(LOGTAG, "setContentScrollBy cy=" + cy);
-            if (cy == 0 && cx != 0) {
-                pinScrollBy(cx, 0, animate, 0);
-            }
+            return cy == 0 && cx != 0 && pinScrollBy(cx, 0, animate, 0);
         } else {
-            pinScrollBy(cx, cy, animate, 0);
+            return pinScrollBy(cx, cy, animate, 0);
         }
     }
 
@@ -3123,7 +3121,7 @@
      * mWebTextView to have the appropriate properties, such as password,
      * multiline, and what text it contains.  It also removes it if necessary.
      */
-    private void rebuildWebTextView() {
+    /* package */ void rebuildWebTextView() {
         // If the WebView does not have focus, do nothing until it gains focus.
         if (!hasFocus() && (null == mWebTextView || !mWebTextView.hasFocus())
                 || (mTouchMode >= FIRST_SCROLL_ZOOM
@@ -3385,7 +3383,8 @@
         } else if (nativeCursorIsTextInput()) {
             // This message will put the node in focus, for the DOM's notion
             // of focus, and make the focuscontroller active
-            mWebViewCore.sendMessage(EventHub.CLICK);
+            mWebViewCore.sendMessage(EventHub.CLICK, nativeCursorFramePointer(),
+                    nativeCursorNodePointer());
             // This will bring up the WebTextView and put it in focus, for
             // our view system's notion of focus
             rebuildWebTextView();
@@ -3626,7 +3625,7 @@
      * not draw the blinking cursor.  It gets set to "active" to draw the cursor
      * in WebViewCore.cpp, when the WebCore thread receives key events/clicks.
      */
-    private void setFocusControllerInactive() {
+    /* package */ void setFocusControllerInactive() {
         // Do not need to also check whether mWebViewCore is null, because
         // mNativeClass is only set if mWebViewCore is non null
         if (mNativeClass == 0) return;
@@ -3813,6 +3812,8 @@
                 } else {
                     mTouchMode = TOUCH_INIT_MODE;
                     mPreventDrag = mForwardTouchEvents;
+                    mWebViewCore.sendMessage(
+                            EventHub.UPDATE_FRAME_CACHE_IF_LOADING);
                     if (mLogEvent && eventTime - mLastTouchUpTime < 1000) {
                         EventLog.writeEvent(EVENT_LOG_DOUBLE_TAP_DURATION,
                                 (eventTime - mLastTouchUpTime), eventTime);
@@ -3983,6 +3984,7 @@
                 switch (mTouchMode) {
                     case TOUCH_DOUBLE_TAP_MODE: // double tap
                         mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS);
+                        mTouchMode = TOUCH_DONE_MODE;
                         doDoubleTap();
                         break;
                     case TOUCH_INIT_MODE: // tap
@@ -4680,7 +4682,7 @@
             // mLastTouchX and mLastTouchY are the point in the current viewport
             int contentX = viewToContent((int) mLastTouchX + mScrollX);
             int contentY = viewToContent((int) mLastTouchY + mScrollY);
-            int left = nativeGetBlockLeftEdge(contentX, contentY);
+            int left = nativeGetBlockLeftEdge(contentX, contentY, mActualScale);
             if (left != NO_LEFTEDGE) {
                 // add a 5pt padding to the left edge. Re-calculate the zoom
                 // center so that the new scroll x will be on the left edge.
@@ -5627,6 +5629,7 @@
     private native void     nativeHideCursor();
     private native String   nativeImageURI(int x, int y);
     private native void     nativeInstrumentReport();
+    /* package */ native void nativeMoveCursorToNextTextInput();
     // return true if the page has been scrolled
     private native boolean  nativeMotionUp(int x, int y, int slop);
     // returns false if it handled the key
@@ -5644,6 +5647,8 @@
     private native void     nativeSetFindIsDown();
     private native void     nativeSetFollowedLink(boolean followed);
     private native void     nativeSetHeightCanMeasure(boolean measure);
+    // Returns a value corresponding to CachedFrame::ImeAction
+    /* package */ native int  nativeTextFieldAction();
     private native int      nativeTextGeneration();
     // Never call this version except by updateCachedTextfield(String) -
     // we always want to pass in our generation number.
@@ -5652,5 +5657,5 @@
     private native void     nativeUpdatePluginReceivesEvents();
     // return NO_LEFTEDGE means failure.
     private static final int NO_LEFTEDGE = -1;
-    private native int      nativeGetBlockLeftEdge(int x, int y);
+    private native int      nativeGetBlockLeftEdge(int x, int y, float scale);
 }
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 8ec8174..2f9e153 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -648,6 +648,7 @@
     }
 
         static final String[] HandlerDebugString = {
+            "UPDATE_FRAME_CACHE_IF_LOADING", // = 98
             "SCROLL_TEXT_INPUT", // = 99
             "LOAD_URL", // = 100;
             "STOP_LOADING", // = 101;
@@ -699,6 +700,7 @@
 
     class EventHub {
         // Message Ids
+        static final int UPDATE_FRAME_CACHE_IF_LOADING = 98;
         static final int SCROLL_TEXT_INPUT = 99;
         static final int LOAD_URL = 100;
         static final int STOP_LOADING = 101;
@@ -805,10 +807,11 @@
                 @Override
                 public void handleMessage(Message msg) {
                     if (DebugFlags.WEB_VIEW_CORE) {
-                        Log.v(LOGTAG, (msg.what < SCROLL_TEXT_INPUT || msg.what
+                        Log.v(LOGTAG, (msg.what < UPDATE_FRAME_CACHE_IF_LOADING
+                                || msg.what
                                 > FREE_MEMORY ? Integer.toString(msg.what)
                                 : HandlerDebugString[msg.what
-                                        - SCROLL_TEXT_INPUT])
+                                        - UPDATE_FRAME_CACHE_IF_LOADING])
                                 + " arg1=" + msg.arg1 + " arg2=" + msg.arg2
                                 + " obj=" + msg.obj);
                     }
@@ -825,6 +828,10 @@
                             mNativeClass = 0;
                             break;
 
+                        case UPDATE_FRAME_CACHE_IF_LOADING:
+                            nativeUpdateFrameCacheIfLoading();
+                            break;
+
                         case SCROLL_TEXT_INPUT:
                             nativeScrollFocusedTextInput(msg.arg1, msg.arg2);
                             break;
@@ -1938,6 +1945,8 @@
                 WebView.CLEAR_TEXT_ENTRY).sendToTarget();
     }
 
+    private native void nativeUpdateFrameCacheIfLoading();
+
     /**
      * Scroll the focused textfield to (x, y) in document space
      */
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index 6a9bcfb..b8f0a7e 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -463,6 +463,7 @@
         if (matrix == null && !mMatrix.isIdentity() ||
                 matrix != null && !mMatrix.equals(matrix)) {
             mMatrix.set(matrix);
+            configureBounds();
             invalidate();
         }
     }
diff --git a/core/res/res/layout/preference_dialog.xml b/core/res/res/layout/preference_dialog.xml
new file mode 100644
index 0000000..5cf0f6e
--- /dev/null
+++ b/core/res/res/layout/preference_dialog.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2006 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.
+-->
+
+<!-- Layout used by DialogPreference widgets. This is inflated inside 
+        android.R.layout.preference. -->
+<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:layout_marginRight="4dip"
+    android:layout_gravity="center_vertical"
+    android:background="@drawable/btn_circle"
+    android:src="@drawable/ic_btn_round_more" />
+
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 6df8b0a..4aa4210 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -659,12 +659,12 @@
     </style>
     
     <style name="Preference.PreferenceScreen">
-        <item name="android:widgetLayout">@android:layout/preferences</item>
     </style>
 
     <style name="Preference.DialogPreference">
         <item name="android:positiveButtonText">@android:string/ok</item>
         <item name="android:negativeButtonText">@android:string/cancel</item>
+        <item name="android:widgetLayout">@android:layout/preference_dialog</item>
     </style>
     
     <style name="Preference.DialogPreference.YesNoPreference">
@@ -680,6 +680,7 @@
         <item name="android:ringtoneType">ringtone</item>
         <item name="android:showSilent">true</item>
         <item name="android:showDefault">true</item>
+        <item name="android:widgetLayout">@android:layout/preference_dialog</item>
     </style>
 
     <!-- Other Misc Styles -->
diff --git a/docs/html/guide/appendix/api-levels.jd b/docs/html/guide/appendix/api-levels.jd
new file mode 100644
index 0000000..9af0918
--- /dev/null
+++ b/docs/html/guide/appendix/api-levels.jd
@@ -0,0 +1,79 @@
+page.title=Android API Levels
+@jd:body
+
+
+<p>The Android <em>API Level</em> is an integer that indicates a set of APIs available in an Android SDK
+and on a version of the Android platform. Each version of the Android platform supports a specific set
+of APIs, which are always backward-compatible. For example, Android 1.5 supports all APIs available in
+Android 1.0, but the reverse is not true. If an application uses APIs
+available in Android 1.5 that are not available in 1.0, then the application should never be installed
+on an Android 1.0 device, because it will fail due to missing APIs. The API Level ensures this does not happen
+by comparing the minimum API Level required by the applicaiton to the API Level available on the device.</p>
+
+<p>When a new version of Android adds APIs, a new API Level is added to the platform. The new APIs
+are available only to applications that declare a minimum API Level that is equal-to or greater-than 
+the API Level in which the APIs were introduced. The API Level required by an application is declared with the
+<code>&lt;uses-sdk></code> element inside the Android manifest, like this:</p>
+
+<pre>&lt;uses-sdk android:minSdkVersion="3" /></pre>
+
+<p>The value for <code>minSdkVersion</code> is the minimum API Level required by the application.
+If this is not declared, then it is assumed that the application is compatible with all versions and defaults to 
+API Level 1. In which case, if the application actually uses APIs introduced with an API Level greater than 1, then
+the application will fail in unpredictable ways when installed on a device that only supports API Level 1 
+(such as an Android 1.0 device).  
+See the <code><a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">&lt;uses-sdk></a></code> 
+documentation for more about declaring the API Level in your manifest.</p>
+
+<p>For example, the {@link android.appwidget} package was introduced with API Level 3. If your application
+has set <code>minSdkVersion</code> to 1 or 2, then your application cannot use this package, 
+even if the device running your application uses a version of Android that supports it.
+In order to use the {@link android.appwidget} package, your application must set <code>minSdkVersion</code> 
+to 3 or higher. When the <code>minSdkVersion</code> is set to 3, the application will no longer be able to install 
+on a device running a platform version with an API Level less than 3.</p>
+
+<p>Despite the name of the manifest attribute (<code>minSdkVersion</code>), the API Level is not directly 
+associated with a specific SDK. For example, the SDK for Android 1.0 uses
+API Level 1 and the SDK for Android 1.1 uses API Level 2. So it may seem that the API Level increases consistently.
+However, it's possible that a subsequent platform
+releases will not introduce new APIs, and thus, the API Level will remain the same. In addition, there are often
+multiple SDK releases for a single platform version (there were three SDK releases for Android 1.5), and
+there's no guarantee that the API Level will remain the same between these. It's possible (but unlikely) that
+a second or third SDK for a given version of the platform will provide new APIs and add a new API Level.
+When you install a new SDK, be sure to read the SDK Contents on the install page, which specifies the API 
+Level for each platform available in the SDK. Also see the comparison of 
+<a href="#VersionsVsApiLevels">Platform Versions vs. API Levels</a>, below.</p>
+
+<p class="note"><strong>Note:</strong> During "preview" SDK releases, there may not yet be an official platform version
+or API Level number specified. In these cases, a string value equal to the
+current codename will be a valid value for <code>minSdkVersion</code>, instead of an integer. This codename value
+will only be valid while using the preview SDK. When the final SDK is released, you must update your manifest to use
+the official API Level integer.</p>
+
+<h2 id="VersionsVsApiLevels">Platform Versions vs. API Levels</h2>
+
+<p>The following table specifies the <em>maximum</em> API Level supported by each version of the Android platform.</p>
+
+<table>
+  <tr><th>Platform Version</th><th>API Level</th></tr>
+  <tr><td>Android 1.0</td><td>1</td></tr>
+  <tr><td>Android 1.1</td><td>2</td></tr>
+  <tr><td>Android 1.5</td><td>3</td></tr>
+  <tr><td>Android Donut</td><td>Donut</td></tr>
+</table>
+
+
+<h2 id="ViewingTheApiReference">Viewing the API Reference Based on API Level</h2>
+
+<p>The Android API reference includes information that specififies the minimum API Level required for each 
+package, class, and member. You can see this information on the right side of each header or label.</p>
+
+<p>By default, the reference documentation shows all APIs available with the latest SDK release.
+This means that the reference assumes you're using the latest API Level and will show you everything available
+with it. If you're developing applications for a version of Android that does not support the latest API Level, 
+then you can filter the reference to reveal only the packages, classes, and members available for that API Level.
+When viewing the reference, use the "Filter by API Level" selection box (below the search bar) to pick the API Level
+you'd like to view.</p>
+
+
+
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index 1770a7a..904361f 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -139,6 +139,7 @@
     native private void nScriptCSetClearColor(float r, float g, float b, float a);
     native private void nScriptCSetClearDepth(float depth);
     native private void nScriptCSetClearStencil(int stencil);
+    native private void nScriptCSetTimeZone(byte[] timeZone);
     native private void nScriptCAddType(int type);
     native private void nScriptCSetRoot(boolean isRoot);
     native private void nScriptCSetScript(byte[] script, int offset, int length);
@@ -670,6 +671,15 @@
         nScriptCBegin();
     }
 
+    public void scriptCSetTimeZone(String timeZone) {
+        try {
+            byte[] bytes = timeZone.getBytes("UTF-8");
+            nScriptCSetTimeZone(bytes);            
+        } catch (java.io.UnsupportedEncodingException e) {
+            throw new RuntimeException(e);
+        }
+    }
+    
     public void scriptCSetClearColor(float r, float g, float b, float a) {
         nScriptCSetClearColor(r, g, b, a);
     }
diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp
index 6f781a0..a02abca 100644
--- a/graphics/jni/android_renderscript_RenderScript.cpp
+++ b/graphics/jni/android_renderscript_RenderScript.cpp
@@ -586,7 +586,7 @@
 nScriptCSetClearDepth(JNIEnv *_env, jobject _this, jfloat d)
 {
     RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
-    LOG_API("nScriptCSetClearColor, con(%p), depth(%f)", con, d);
+    LOG_API("nScriptCSetClearDepth, con(%p), depth(%f)", con, d);
     rsScriptCSetClearDepth(d);
 }
 
@@ -599,6 +599,23 @@
 }
 
 static void
+nScriptCSetTimeZone(JNIEnv *_env, jobject _this, jbyteArray timeZone)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nScriptCSetTimeZone, con(%p), timeZone(%s)", con, timeZone);
+
+    jint length = _env->GetArrayLength(timeZone);
+    jbyte* timeZone_ptr;
+    timeZone_ptr = (jbyte *) _env->GetPrimitiveArrayCritical(timeZone, (jboolean *)0);
+
+    rsScriptCSetTimeZone((const char *)timeZone_ptr, length);
+
+    if (timeZone_ptr) {
+        _env->ReleasePrimitiveArrayCritical(timeZone, timeZone_ptr, 0);
+    }
+}
+
+static void
 nScriptCAddType(JNIEnv *_env, jobject _this, jint type)
 {
     RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
@@ -1052,6 +1069,7 @@
 {"nScriptCSetClearColor",          "(FFFF)V",                              (void*)nScriptCSetClearColor },
 {"nScriptCSetClearDepth",          "(F)V",                                 (void*)nScriptCSetClearDepth },
 {"nScriptCSetClearStencil",        "(I)V",                                 (void*)nScriptCSetClearStencil },
+{"nScriptCSetTimeZone",            "([B)V",                                (void*)nScriptCSetTimeZone },
 {"nScriptCAddType",                "(I)V",                                 (void*)nScriptCAddType },
 {"nScriptCSetRoot",                "(Z)V",                                 (void*)nScriptCSetRoot },
 {"nScriptCSetScript",              "([BII)V",                              (void*)nScriptCSetScript },
diff --git a/include/media/IOMX.h b/include/media/IOMX.h
index 5c61c50..0010d84 100644
--- a/include/media/IOMX.h
+++ b/include/media/IOMX.h
@@ -23,6 +23,7 @@
 #include <utils/String8.h>
 
 #include <OMX_Core.h>
+#include <OMX_Video.h>
 
 #define IOMX_USES_SOCKETS       0
 
@@ -30,6 +31,8 @@
 
 class IMemory;
 class IOMXObserver;
+class IOMXRenderer;
+class ISurface;
 
 class IOMX : public IInterface {
 public:
@@ -87,6 +90,13 @@
             OMX_U32 range_offset, OMX_U32 range_length,
             OMX_U32 flags, OMX_TICKS timestamp) = 0;
 #endif
+
+    virtual sp<IOMXRenderer> createRenderer(
+            const sp<ISurface> &surface,
+            const char *componentName,
+            OMX_COLOR_FORMATTYPE colorFormat,
+            size_t encodedWidth, size_t encodedHeight,
+            size_t displayWidth, size_t displayHeight) = 0;
 };
 
 struct omx_message {
@@ -155,6 +165,13 @@
     virtual void on_message(const omx_message &msg) = 0;
 };
 
+class IOMXRenderer : public IInterface {
+public:
+    DECLARE_META_INTERFACE(OMXRenderer);
+
+    virtual void render(IOMX::buffer_id buffer) = 0;
+};
+
 ////////////////////////////////////////////////////////////////////////////////
 
 class BnOMX : public BnInterface<IOMX> {
@@ -171,6 +188,13 @@
             uint32_t flags = 0);
 };
 
+class BnOMXRenderer : public BnInterface<IOMXRenderer> {
+public:
+    virtual status_t onTransact(
+            uint32_t code, const Parcel &data, Parcel *reply,
+            uint32_t flags = 0);
+};
+
 }  // namespace android
 
 #endif  // ANDROID_IOMX_H_
diff --git a/include/media/stagefright/MediaPlayerImpl.h b/include/media/stagefright/MediaPlayerImpl.h
index c48400c..e96e5e8 100644
--- a/include/media/stagefright/MediaPlayerImpl.h
+++ b/include/media/stagefright/MediaPlayerImpl.h
@@ -28,6 +28,7 @@
 namespace android {
 
 class AudioPlayer;
+class IOMXRenderer;
 class ISurface;
 class MediaExtractor;
 class MediaBuffer;
@@ -37,7 +38,6 @@
 class OMXDecoder;
 class Surface;
 class TimeSource;
-class VideoRenderer;
 
 class MediaPlayerImpl {
 public:
@@ -93,7 +93,7 @@
 
     sp<Surface> mSurface;
     sp<ISurface> mISurface;
-    VideoRenderer *mRenderer;
+    sp<IOMXRenderer> mVideoRenderer;
 
     sp<MediaPlayerBase::AudioSink> mAudioSink;
 
diff --git a/include/media/stagefright/MetaData.h b/include/media/stagefright/MetaData.h
index 04805da..2d5b8d8 100644
--- a/include/media/stagefright/MetaData.h
+++ b/include/media/stagefright/MetaData.h
@@ -44,6 +44,7 @@
     kKeyColorFormat      = 'colf',
     kKeyPlatformPrivate  = 'priv',
     kKeyDecoderComponent = 'decC',
+    kKeyBufferID         = 'bfID',
 };
 
 enum {
diff --git a/include/media/stagefright/SurfaceRenderer.h b/include/media/stagefright/SurfaceRenderer.h
deleted file mode 100644
index 298ab50..0000000
--- a/include/media/stagefright/SurfaceRenderer.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2009 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.
- */
-
-#ifndef SURFACE_RENDERER_H_
-
-#define SURFACE_RENDERER_H_
-
-#include <media/stagefright/VideoRenderer.h>
-#include <utils/RefBase.h>
-
-namespace android {
-
-class Surface;
-
-class SurfaceRenderer : public VideoRenderer {
-public:
-    SurfaceRenderer(
-            const sp<Surface> &surface,
-            size_t displayWidth, size_t displayHeight,
-            size_t decodedWidth, size_t decodedHeight);
-
-    virtual ~SurfaceRenderer();
-
-    virtual void render(
-            const void *data, size_t size, void *platformPrivate);
-
-private:
-    sp<Surface> mSurface;
-    size_t mDisplayWidth, mDisplayHeight;
-    size_t mDecodedWidth, mDecodedHeight;
-
-    SurfaceRenderer(const SurfaceRenderer &);
-    SurfaceRenderer &operator=(const SurfaceRenderer &);
-};
-
-}  // namespace android
-
-#endif  // SURFACE_RENDERER_H_
diff --git a/include/ui/Surface.h b/include/ui/Surface.h
index 156d453..5665c1f 100644
--- a/include/ui/Surface.h
+++ b/include/ui/Surface.h
@@ -36,6 +36,7 @@
 
 class BufferMapper;
 class Rect;
+class MediaPlayerImpl;
 class Surface;
 class SurfaceComposerClient;
 struct per_client_cblk_t;
@@ -180,6 +181,7 @@
     // mediaplayer needs access to ISurface for display
     friend class MediaPlayer;
     friend class Test;
+    friend class MediaPlayerImpl;
     const sp<ISurface>& getISurface() const { return mSurface; }
 
     status_t getBufferLocked(int index);
diff --git a/libs/rs/java/Grass/Android.mk b/libs/rs/java/Grass/Android.mk
new file mode 100644
index 0000000..ce5294e
--- /dev/null
+++ b/libs/rs/java/Grass/Android.mk
@@ -0,0 +1,25 @@
+#
+# Copyright (C) 2009 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+#LOCAL_STATIC_JAVA_LIBRARIES := android.renderscript
+
+LOCAL_PACKAGE_NAME := GrassRS
+
+include $(BUILD_PACKAGE)
diff --git a/libs/rs/java/Grass/AndroidManifest.xml b/libs/rs/java/Grass/AndroidManifest.xml
new file mode 100644
index 0000000..a40f378
--- /dev/null
+++ b/libs/rs/java/Grass/AndroidManifest.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.grass.rs">
+
+    <application android:label="GrassRS">
+
+        <activity
+            android:name="Grass"
+            android:theme="@android:style/Theme.NoTitleBar">
+
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+
+        </activity>
+
+    </application>
+
+</manifest>
diff --git a/libs/rs/java/Grass/res/drawable-hdpi/night.jpg b/libs/rs/java/Grass/res/drawable-hdpi/night.jpg
new file mode 100644
index 0000000..9989abf
--- /dev/null
+++ b/libs/rs/java/Grass/res/drawable-hdpi/night.jpg
Binary files differ
diff --git a/libs/rs/java/Grass/res/drawable-hdpi/sky.jpg b/libs/rs/java/Grass/res/drawable-hdpi/sky.jpg
new file mode 100644
index 0000000..a12fe20
--- /dev/null
+++ b/libs/rs/java/Grass/res/drawable-hdpi/sky.jpg
Binary files differ
diff --git a/libs/rs/java/Grass/res/drawable-hdpi/sunrise.jpg b/libs/rs/java/Grass/res/drawable-hdpi/sunrise.jpg
new file mode 100644
index 0000000..db016b2
--- /dev/null
+++ b/libs/rs/java/Grass/res/drawable-hdpi/sunrise.jpg
Binary files differ
diff --git a/libs/rs/java/Grass/res/drawable-hdpi/sunset.jpg b/libs/rs/java/Grass/res/drawable-hdpi/sunset.jpg
new file mode 100644
index 0000000..49bb0c6
--- /dev/null
+++ b/libs/rs/java/Grass/res/drawable-hdpi/sunset.jpg
Binary files differ
diff --git a/libs/rs/java/Grass/res/raw/grass.c b/libs/rs/java/Grass/res/raw/grass.c
new file mode 100644
index 0000000..b1b89f0
--- /dev/null
+++ b/libs/rs/java/Grass/res/raw/grass.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2008 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.
+ */
+ 
+#pragma version(1)
+#pragma stateVertex(default)
+#pragma stateFragment(PFBackground)
+#pragma stateFragmentStore(PFSBackground)
+
+#define WVGA_PORTRAIT_WIDTH 480.0f
+#define WVGA_PORTRAIT_HEIGHT 762.0f
+
+#define RSID_STATE 0
+#define RSID_FRAMECOUNT 0
+
+#define RSID_SKY_TEXTURES 1
+#define RSID_SKY_TEXTURE_NIGHT 0
+#define RSID_SKY_TEXTURE_SUNRISE 1
+#define RSID_SKY_TEXTURE_NOON 2
+#define RSID_SKY_TEXTURE_SUNSET 3
+
+#define MIDNIGHT 0.0f
+#define MORNING 0.375f
+#define AFTERNOON 0.6f
+#define DUSK 0.8f
+
+#define SECONDS_IN_DAY 24.0f * 3600.0f
+
+#define REAL_TIME 0
+
+float time(int frameCount) {
+    if (REAL_TIME) {
+        return (hour() * 3600.0f + minute() * 60.0f + second()) / SECONDS_IN_DAY;
+    }
+    return (frameCount % 180) / 180.0f;
+}
+
+void alpha(float a) {
+    color(1.0f, 1.0f, 1.0f, a);
+}
+
+float norm(float a, float start, float end) {
+    return (a - start) / (end - start);
+}
+
+void drawNight() {
+    bindTexture(NAMED_PFBackground, 0, loadI32(RSID_SKY_TEXTURES, RSID_SKY_TEXTURE_NIGHT));
+    // NOTE: Hacky way to draw the night sky
+    drawRect(WVGA_PORTRAIT_WIDTH - 512.0f, -32.0f, WVGA_PORTRAIT_WIDTH, 1024.0f - 32.0f, 0.0f);
+}
+
+void drawSunrise() {
+    bindTexture(NAMED_PFBackground, 0, loadI32(RSID_SKY_TEXTURES, RSID_SKY_TEXTURE_SUNRISE));
+    drawRect(0.0f, 0.0f, WVGA_PORTRAIT_WIDTH, WVGA_PORTRAIT_HEIGHT, 0.0f);
+}
+
+void drawNoon() {
+    bindTexture(NAMED_PFBackground, 0, loadI32(RSID_SKY_TEXTURES, RSID_SKY_TEXTURE_NOON));
+    drawRect(0.0f, 0.0f, WVGA_PORTRAIT_WIDTH, WVGA_PORTRAIT_HEIGHT, 0.0f);
+}
+
+void drawSunset() {
+    bindTexture(NAMED_PFBackground, 0, loadI32(RSID_SKY_TEXTURES, RSID_SKY_TEXTURE_SUNSET));
+    drawRect(0.0f, 0.0f, WVGA_PORTRAIT_WIDTH, WVGA_PORTRAIT_HEIGHT, 0.0f);
+}
+
+int main(int launchID) {
+    int frameCount = loadI32(RSID_STATE, RSID_FRAMECOUNT);
+    float now = time(frameCount);
+    alpha(1.0f);
+
+    if (now >= MIDNIGHT && now < MORNING) {
+        drawNight();
+        alpha(norm(now, MIDNIGHT, MORNING));
+        drawSunrise();
+    }
+    
+    if (now >= MORNING && now < AFTERNOON) {
+        drawSunrise();
+        alpha(norm(now, MORNING, AFTERNOON));
+        drawNoon();
+    }
+
+    if (now >= AFTERNOON && now < DUSK) {
+        drawNoon();
+        alpha(norm(now, AFTERNOON, DUSK));
+        drawSunset();
+    }
+    
+    if (now >= DUSK) {
+        drawSunset();
+        alpha(norm(now, DUSK, 1.0f));
+        drawNight();
+    }
+
+    frameCount++;
+    storeI32(RSID_STATE, RSID_FRAMECOUNT, frameCount);
+
+    return 1;
+}
diff --git a/libs/rs/java/Grass/src/com/android/grass/rs/Grass.java b/libs/rs/java/Grass/src/com/android/grass/rs/Grass.java
new file mode 100644
index 0000000..260fcee
--- /dev/null
+++ b/libs/rs/java/Grass/src/com/android/grass/rs/Grass.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2008 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.grass.rs;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class Grass extends Activity {
+    private GrassView mView;
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        mView = new GrassView(this);
+        setContentView(mView);
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        mView.onResume();
+    }
+
+    @Override
+    protected void onPause() {
+        super.onPause();
+        mView.onPause();
+
+        Runtime.getRuntime().exit(0);
+    }
+}
diff --git a/libs/rs/java/Grass/src/com/android/grass/rs/GrassRS.java b/libs/rs/java/Grass/src/com/android/grass/rs/GrassRS.java
new file mode 100644
index 0000000..bb13051
--- /dev/null
+++ b/libs/rs/java/Grass/src/com/android/grass/rs/GrassRS.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2009 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.grass.rs;
+
+import android.content.res.Resources;
+import android.renderscript.RenderScript;
+import static android.renderscript.RenderScript.ElementPredefined.*;
+import static android.renderscript.RenderScript.SamplerParam.*;
+import static android.renderscript.RenderScript.SamplerValue.*;
+import static android.renderscript.RenderScript.EnvMode.*;
+import static android.renderscript.RenderScript.DepthFunc.*;
+import static android.renderscript.RenderScript.BlendSrcFunc;
+import static android.renderscript.RenderScript.BlendDstFunc;
+
+import java.util.TimeZone;
+
+class GrassRS {
+    private static final int RSID_STATE = 0;
+    private static final int RSID_SKY_TEXTURES = 1;
+    private static final int SKY_TEXTURES_COUNT = 4;
+
+    private Resources mResources;
+    private RenderScript mRS;
+
+    @SuppressWarnings({"FieldCanBeLocal"})
+    private RenderScript.Script mScript;
+    @SuppressWarnings({"FieldCanBeLocal"})
+    private RenderScript.Sampler mSampler;
+    @SuppressWarnings({"FieldCanBeLocal"})
+    private RenderScript.ProgramFragment mPfBackground;
+    @SuppressWarnings({"FieldCanBeLocal"})
+    private RenderScript.ProgramFragmentStore mPfsBackground;
+
+    @SuppressWarnings({"FieldCanBeLocal"})
+    private RenderScript.Allocation mSkyTexturesIDs;
+    @SuppressWarnings({"FieldCanBeLocal"})
+    private RenderScript.Allocation[] mSkyTextures;
+    @SuppressWarnings({"FieldCanBeLocal"})
+    private int[] mSkyBufferIDs;
+    @SuppressWarnings({"FieldCanBeLocal"})
+    private RenderScript.Allocation mState;
+
+    public GrassRS() {
+    }
+
+    public void init(RenderScript rs, Resources res) {
+        mRS = rs;
+        mResources = res;
+        initRS();
+    }
+
+    private void initRS() {
+        createProgramVertex();
+        createProgramFragmentStore();
+        createProgramFragment();
+        createScriptStructures();
+        
+        mRS.scriptCBegin();
+        mRS.scriptCSetClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+        mRS.scriptCSetScript(mResources, R.raw.grass);
+        mRS.scriptCSetTimeZone(TimeZone.getDefault().getID());
+        mRS.scriptCSetRoot(true);
+
+        mScript = mRS.scriptCCreate();
+
+        loadSkyTextures();        
+        mScript.bindAllocation(mState, RSID_STATE);
+        mScript.bindAllocation(mSkyTexturesIDs, RSID_SKY_TEXTURES);
+
+        mRS.contextBindRootScript(mScript);        
+    }
+
+    private void createScriptStructures() {
+        mState = mRS.allocationCreatePredefSized(RenderScript.ElementPredefined.USER_I32, 1);    
+        mState.data(new int[1]);
+    }
+
+    private void loadSkyTextures() {
+        mSkyBufferIDs = new int[SKY_TEXTURES_COUNT];
+        mSkyTextures = new RenderScript.Allocation[SKY_TEXTURES_COUNT];
+        mSkyTexturesIDs = mRS.allocationCreatePredefSized(
+                USER_FLOAT, SKY_TEXTURES_COUNT);
+
+        final RenderScript.Allocation[] textures = mSkyTextures;
+        textures[0] = loadTexture(R.drawable.night, "night");
+        textures[1] = loadTexture(R.drawable.sunrise, "sunrise");
+        textures[2] = loadTexture(R.drawable.sky, "sky");
+        textures[3] = loadTexture(R.drawable.sunset, "sunset");
+
+        final int[] bufferIds = mSkyBufferIDs;
+        final int count = textures.length;
+
+        for (int i = 0; i < count; i++) {
+            final RenderScript.Allocation texture = textures[i];
+            texture.uploadToTexture(0);
+            bufferIds[i] = texture.getID();
+        }
+
+        mSkyTexturesIDs.data(bufferIds);
+    }
+
+    private RenderScript.Allocation loadTexture(int id, String name) {
+        RenderScript.Allocation allocation = mRS.allocationCreateFromBitmapResource(mResources, id,
+                RGB_565, false);
+        allocation.setName(name);
+        return allocation;
+    }
+
+    private void createProgramFragment() {
+        mRS.samplerBegin();
+        mRS.samplerSet(FILTER_MIN, LINEAR);
+        mRS.samplerSet(FILTER_MAG, LINEAR);
+        mRS.samplerSet(WRAP_MODE_S, CLAMP);
+        mRS.samplerSet(WRAP_MODE_T, CLAMP);
+        mSampler = mRS.samplerCreate();
+
+        mRS.programFragmentBegin(null, null);
+        mRS.programFragmentSetTexEnable(0, true);
+        mRS.programFragmentSetTexEnvMode(0, REPLACE);
+        mPfBackground = mRS.programFragmentCreate();
+        mPfBackground.setName("PFBackground");
+        mPfBackground.bindSampler(mSampler, 0);
+    }
+
+    private void createProgramFragmentStore() {
+        mRS.programFragmentStoreBegin(null, null);
+        mRS.programFragmentStoreDepthFunc(ALWAYS);
+        mRS.programFragmentStoreBlendFunc(BlendSrcFunc.SRC_ALPHA, BlendDstFunc.ONE_MINUS_SRC_ALPHA);
+        mRS.programFragmentStoreDitherEnable(true);
+        mRS.programFragmentStoreDepthMask(false);
+        mPfsBackground = mRS.programFragmentStoreCreate();
+        mPfsBackground.setName("PFSBackground");
+    }
+
+    private void createProgramVertex() {
+    }
+}
diff --git a/libs/rs/java/Grass/src/com/android/grass/rs/GrassView.java b/libs/rs/java/Grass/src/com/android/grass/rs/GrassView.java
new file mode 100644
index 0000000..a641e1e
--- /dev/null
+++ b/libs/rs/java/Grass/src/com/android/grass/rs/GrassView.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2008 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.grass.rs;
+
+import android.content.Context;
+import android.renderscript.RSSurfaceView;
+import android.renderscript.RenderScript;
+import android.view.SurfaceHolder;
+
+class GrassView extends RSSurfaceView {
+    public GrassView(Context context) {
+        super(context);
+    }
+
+    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
+        super.surfaceChanged(holder, format, w, h);
+
+        RenderScript RS = createRenderScript();
+        GrassRS render = new GrassRS();
+        render.init(RS, getResources());
+    }
+}
diff --git a/libs/rs/rs.spec b/libs/rs/rs.spec
index 45e6d1b..d9a6456 100644
--- a/libs/rs/rs.spec
+++ b/libs/rs/rs.spec
@@ -280,6 +280,11 @@
 	param float a
 	}
 
+ScriptCSetTimeZone {
+	param const char * timeZone
+	param uint32_t length
+	}
+
 ScriptCSetClearDepth {
 	param float depth
 	}
diff --git a/libs/rs/rsScript.h b/libs/rs/rsScript.h
index 7dd2b61..a8e04a6 100644
--- a/libs/rs/rsScript.h
+++ b/libs/rs/rsScript.h
@@ -43,6 +43,9 @@
         float mClearDepth;
         uint32_t mClearStencil;
 
+        uint32_t mStartTimeMillis;
+        const char* mTimeZone;
+
         ObjectBaseRef<ProgramVertex> mVertex;
         ObjectBaseRef<ProgramFragment> mFragment;
         //ObjectBaseRef<ProgramRaster> mRaster;
diff --git a/libs/rs/rsScriptC.cpp b/libs/rs/rsScriptC.cpp
index 842c836..3b9d27a 100644
--- a/libs/rs/rsScriptC.cpp
+++ b/libs/rs/rsScriptC.cpp
@@ -230,6 +230,12 @@
     ss->mEnviroment.mClearColor[3] = a;
 }
 
+void rsi_ScriptCSetTimeZone(Context * rsc, const char * timeZone, uint32_t length)
+{
+    ScriptCState *ss = &rsc->mScriptC;
+    ss->mEnviroment.mTimeZone = timeZone;
+}
+
 void rsi_ScriptCSetClearDepth(Context * rsc, float v)
 {
     ScriptCState *ss = &rsc->mScriptC;
diff --git a/libs/rs/rsScriptC_Lib.cpp b/libs/rs/rsScriptC_Lib.cpp
index 7db3619..21c9753 100644
--- a/libs/rs/rsScriptC_Lib.cpp
+++ b/libs/rs/rsScriptC_Lib.cpp
@@ -24,6 +24,9 @@
 #include <GLES/gl.h>
 #include <GLES/glext.h>
 
+#include <time.h>
+#include <cutils/tztime.h>
+
 using namespace android;
 using namespace android::renderscript;
 
@@ -126,14 +129,203 @@
 // Math routines
 //////////////////////////////////////////////////////////////////////////////
 
+#define PI 3.1415926f
+#define DEG_TO_RAD PI / 180.0f
+#define RAD_TO_DEG 180.0f / PI
+
 static float SC_randf(float max)
 {
     float r = (float)rand();
     return r / RAND_MAX * max;
 }
 
+static float SC_randf2(float min, float max)
+{
+    float r = (float)rand();
+    return r / RAND_MAX * (max - min) + min;
+}
 
+static float SC_clampf(float amount, float low, float high)
+{
+    return amount < low ? low : (amount > high ? high : amount);
+}
 
+static float SC_maxf(float a, float b)
+{
+    return a > b ? a : b; 
+}
+
+static float SC_minf(float a, float b)
+{
+    return a < b ? a : b; 
+}
+
+static float SC_sqrf(float v)
+{
+    return v * v; 
+}
+
+static float SC_distf2(float x1, float y1, float x2, float y2)
+{
+    float x = x2 - x1;
+    float y = y2 - y1;
+    return sqrtf(x * x + y * y); 
+}
+
+static float SC_distf3(float x1, float y1, float z1, float x2, float y2, float z2)
+{
+    float x = x2 - x1;
+    float y = y2 - y1;
+    float z = z2 - z1;
+    return sqrtf(x * x + y * y + z * z); 
+}
+
+static float SC_magf2(float a, float b)
+{
+    return sqrtf(a * a + b * b);
+}
+
+static float SC_magf3(float a, float b, float c)
+{
+    return sqrtf(a * a + b * b + c * c);
+}
+
+static float SC_radf(float degrees)
+{
+    return degrees * DEG_TO_RAD; 
+}
+
+static float SC_degf(float radians)
+{
+    return radians * RAD_TO_DEG; 
+}
+
+static float SC_lerpf(float start, float stop, float amount)
+{
+    return start + (stop - start) * amount;
+}
+
+static float SC_normf(float start, float stop, float value)
+{
+    return (value - start) / (stop - start);
+}
+
+static float SC_mapf(float minStart, float minStop, float maxStart, float maxStop, float value)
+{
+    return maxStart + (maxStart - maxStop) * ((value - minStart) / (minStop - minStart));
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Time routines
+//////////////////////////////////////////////////////////////////////////////
+
+static uint32_t SC_second()
+{
+    GET_TLS();
+
+    time_t rawtime;
+    time(&rawtime);
+
+    if (sc->mEnviroment.mTimeZone) {
+        struct tm timeinfo;
+        localtime_tz(&rawtime, &timeinfo, sc->mEnviroment.mTimeZone);
+        return timeinfo.tm_sec;
+    } else {
+        struct tm *timeinfo;
+        timeinfo = localtime(&rawtime);
+        return timeinfo->tm_sec;
+    }
+}
+
+static uint32_t SC_minute()
+{
+    GET_TLS();
+    
+    time_t rawtime;
+    time(&rawtime);
+    
+    if (sc->mEnviroment.mTimeZone) {
+        struct tm timeinfo;
+        localtime_tz(&rawtime, &timeinfo, sc->mEnviroment.mTimeZone);
+        return timeinfo.tm_min;
+    } else {
+        struct tm *timeinfo;
+        timeinfo = localtime(&rawtime);
+        return timeinfo->tm_min;
+    }
+}   
+
+static uint32_t SC_hour()
+{
+    GET_TLS();
+    
+    time_t rawtime;
+    time(&rawtime);
+    
+    if (sc->mEnviroment.mTimeZone) {
+        struct tm timeinfo;
+        localtime_tz(&rawtime, &timeinfo, sc->mEnviroment.mTimeZone);
+        return timeinfo.tm_hour;
+    } else {
+        struct tm *timeinfo;
+        timeinfo = localtime(&rawtime);
+        return timeinfo->tm_hour;
+    }
+}
+
+static uint32_t SC_day()
+{
+    GET_TLS();
+    
+    time_t rawtime;
+    time(&rawtime);
+    
+    if (sc->mEnviroment.mTimeZone) {
+        struct tm timeinfo;
+        localtime_tz(&rawtime, &timeinfo, sc->mEnviroment.mTimeZone);
+        return timeinfo.tm_mday;
+    } else {
+        struct tm *timeinfo;
+        timeinfo = localtime(&rawtime);
+        return timeinfo->tm_mday;
+    }
+}   
+
+static uint32_t SC_month()
+{
+    GET_TLS();
+    
+    time_t rawtime;
+    time(&rawtime);
+    
+    if (sc->mEnviroment.mTimeZone) {
+        struct tm timeinfo;
+        localtime_tz(&rawtime, &timeinfo, sc->mEnviroment.mTimeZone);
+        return timeinfo.tm_mon;
+    } else {
+        struct tm *timeinfo;
+        timeinfo = localtime(&rawtime);
+        return timeinfo->tm_mon;
+    }
+} 
+
+static uint32_t SC_year()
+{
+    GET_TLS();
+    
+    time_t rawtime;
+    time(&rawtime);
+    
+    if (sc->mEnviroment.mTimeZone) {
+        struct tm timeinfo;
+        localtime_tz(&rawtime, &timeinfo, sc->mEnviroment.mTimeZone);
+        return timeinfo.tm_year;
+    } else {
+        struct tm *timeinfo;
+        timeinfo = localtime(&rawtime);
+        return timeinfo->tm_year;
+    }
+}
 
 //////////////////////////////////////////////////////////////////////////////
 // Matrix routines
@@ -451,14 +643,72 @@
         "float", "(float)" },
     { "cosf", (void *)&cosf,
         "float", "(float)" },
+    { "asinf", (void *)&asinf,
+        "float", "(float)" },
+    { "acosf", (void *)&acosf,
+        "float", "(float)" },
+    { "atanf", (void *)&atanf,
+        "float", "(float)" },
+    { "atan2f", (void *)&atan2f,
+        "float", "(floatm float)" },
     { "fabsf", (void *)&fabsf,
         "float", "(float)" },
     { "randf", (void *)&SC_randf,
         "float", "(float)" },
+    { "randf2", (void *)&SC_randf2,
+        "float", "(float, float)" },
     { "floorf", (void *)&floorf,
         "float", "(float)" },
     { "ceilf", (void *)&ceilf,
         "float", "(float)" },
+    { "expf", (void *)&expf,
+        "float", "(float)" },
+    { "logf", (void *)&logf,
+        "float", "(float)" },
+    { "powf", (void *)&powf,
+        "float", "(float, float)" },
+    { "maxf", (void *)&SC_maxf,
+        "float", "(float, float)" },
+    { "minf", (void *)&SC_minf,
+        "float", "(float, float)" },
+    { "sqrtf", (void *)&sqrtf,
+        "float", "(float)" },
+    { "sqrf", (void *)&SC_sqrf,
+        "float", "(float)" },
+    { "clampf", (void *)&SC_clampf,
+        "float", "(float, float, float)" },
+    { "distf2", (void *)&SC_distf2,
+        "float", "(float, float, float, float)" },
+    { "distf3", (void *)&SC_distf3,
+        "float", "(float, float, float, float, float, float)" },
+    { "magf2", (void *)&SC_magf2,
+        "float", "(float, float)" },
+    { "magf3", (void *)&SC_magf3,
+        "float", "(float, float, float)" },
+    { "radf", (void *)&SC_radf,
+        "float", "(float)" },
+    { "degf", (void *)&SC_degf,
+        "float", "(float)" },
+    { "lerpf", (void *)&SC_lerpf,
+        "float", "(float, float, float)" },
+    { "normf", (void *)&SC_normf,
+        "float", "(float, float, float)" },
+    { "mapf", (void *)&SC_mapf,
+        "float", "(float, float, float, float, float)" },
+
+    // time
+    { "second", (void *)&SC_second,
+        "int", "()" },
+    { "minute", (void *)&SC_minute,
+        "int", "()" },
+    { "hour", (void *)&SC_hour,
+        "int", "()" },
+    { "day", (void *)&SC_day,
+        "int", "()" },
+    { "month", (void *)&SC_month,
+        "int", "()" },
+    { "year", (void *)&SC_year,
+        "int", "()" },
 
     // matrix
     { "matrixLoadIdentity", (void *)&SC_matrixLoadIdentity,
diff --git a/media/java/android/media/JetPlayer.java b/media/java/android/media/JetPlayer.java
index 2263605..1570db4 100644
--- a/media/java/android/media/JetPlayer.java
+++ b/media/java/android/media/JetPlayer.java
@@ -183,6 +183,7 @@
      */
     public void release() {
         native_release();
+        singletonRef = null;
     }
     
     
diff --git a/media/jni/soundpool/SoundPool.cpp b/media/jni/soundpool/SoundPool.cpp
index 0d07abe..b17e31b 100644
--- a/media/jni/soundpool/SoundPool.cpp
+++ b/media/jni/soundpool/SoundPool.cpp
@@ -93,7 +93,7 @@
 
 void SoundPool::addToRestartList(SoundChannel* channel)
 {
-    Mutex::Autolock lock(&mLock);
+    Mutex::Autolock lock(&mRestartLock);
     mRestart.push_back(channel);
     mCondition.signal();
 }
@@ -106,9 +106,9 @@
 
 int SoundPool::run()
 {
-    mLock.lock();
+    mRestartLock.lock();
     while (!mQuit) {
-        mCondition.wait(mLock);
+        mCondition.wait(mRestartLock);
         LOGV("awake");
         if (mQuit) break;
 
@@ -125,19 +125,19 @@
 
     mRestart.clear();
     mCondition.signal();
-    mLock.unlock();
+    mRestartLock.unlock();
     LOGV("goodbye");
     return 0;
 }
 
 void SoundPool::quit()
 {
-    mLock.lock();
+    mRestartLock.lock();
     mQuit = true;
     mCondition.signal();
-    mCondition.wait(mLock);
+    mCondition.wait(mRestartLock);
     LOGV("return from quit");
-    mLock.unlock();
+    mRestartLock.unlock();
 }
 
 bool SoundPool::startThreads()
@@ -484,11 +484,8 @@
     // if not idle, this voice is being stolen
     if (mState != IDLE) {
         LOGV("channel %d stolen - event queued for channel %d", channelID(), nextChannelID);
-        stop_l();
         mNextEvent.set(sample, nextChannelID, leftVolume, rightVolume, priority, loop, rate);
-#ifdef USE_SHARED_MEM_BUFFER
-        mSoundPool->done(this);
-#endif
+        stop();
         return;
     }
 
diff --git a/media/jni/soundpool/SoundPool.h b/media/jni/soundpool/SoundPool.h
index 7802781..ab86e90 100644
--- a/media/jni/soundpool/SoundPool.h
+++ b/media/jni/soundpool/SoundPool.h
@@ -204,6 +204,7 @@
 
     jobject                 mSoundPoolRef;
     Mutex                   mLock;
+    Mutex                   mRestartLock;
     Condition               mCondition;
     SoundPoolThread*        mDecodeThread;
     SoundChannel*           mChannelPool;
diff --git a/media/libmedia/IOMX.cpp b/media/libmedia/IOMX.cpp
index f2a657a..4661af6 100644
--- a/media/libmedia/IOMX.cpp
+++ b/media/libmedia/IOMX.cpp
@@ -5,6 +5,7 @@
 #include <binder/IMemory.h>
 #include <binder/Parcel.h>
 #include <media/IOMX.h>
+#include <ui/ISurface.h>
 
 namespace android {
 
@@ -23,7 +24,9 @@
     OBSERVE_NODE,
     FILL_BUFFER,
     EMPTY_BUFFER,
+    CREATE_RENDERER,
     OBSERVER_ON_MSG,
+    RENDERER_RENDER,
 };
 
 static void *readVoidStar(const Parcel *parcel) {
@@ -262,6 +265,28 @@
         remote()->transact(EMPTY_BUFFER, data, &reply, IBinder::FLAG_ONEWAY);
     }
 #endif
+
+    virtual sp<IOMXRenderer> createRenderer(
+            const sp<ISurface> &surface,
+            const char *componentName,
+            OMX_COLOR_FORMATTYPE colorFormat,
+            size_t encodedWidth, size_t encodedHeight,
+            size_t displayWidth, size_t displayHeight) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
+
+        data.writeStrongBinder(surface->asBinder());
+        data.writeCString(componentName);
+        data.writeInt32(colorFormat);
+        data.writeInt32(encodedWidth);
+        data.writeInt32(encodedHeight);
+        data.writeInt32(displayWidth);
+        data.writeInt32(displayHeight);
+
+        remote()->transact(CREATE_RENDERER, data, &reply);
+
+        return interface_cast<IOMXRenderer>(reply.readStrongBinder());
+    }
 };
 
 IMPLEMENT_META_INTERFACE(OMX, "android.hardware.IOMX");
@@ -513,6 +538,33 @@
         }
 #endif
 
+        case CREATE_RENDERER:
+        {
+            CHECK_INTERFACE(IOMX, data, reply);
+
+            sp<ISurface> isurface =
+                interface_cast<ISurface>(data.readStrongBinder());
+
+            const char *componentName = data.readCString();
+
+            OMX_COLOR_FORMATTYPE colorFormat =
+                static_cast<OMX_COLOR_FORMATTYPE>(data.readInt32());
+
+            size_t encodedWidth = (size_t)data.readInt32();
+            size_t encodedHeight = (size_t)data.readInt32();
+            size_t displayWidth = (size_t)data.readInt32();
+            size_t displayHeight = (size_t)data.readInt32();
+
+            sp<IOMXRenderer> renderer =
+                createRenderer(isurface, componentName, colorFormat,
+                               encodedWidth, encodedHeight,
+                               displayWidth, displayHeight);
+
+            reply->writeStrongBinder(renderer->asBinder());
+
+            return OK;
+        }
+
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
@@ -558,4 +610,44 @@
     }
 }
 
+////////////////////////////////////////////////////////////////////////////////
+
+class BpOMXRenderer : public BpInterface<IOMXRenderer> {
+public:
+    BpOMXRenderer(const sp<IBinder> &impl)
+        : BpInterface<IOMXRenderer>(impl) {
+    }
+
+    virtual void render(IOMX::buffer_id buffer) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IOMXRenderer::getInterfaceDescriptor());
+        writeVoidStar(buffer, &data);
+
+        // NOTE: Do NOT make this a ONE_WAY call, it must be synchronous
+        // so that the caller knows when to recycle the buffer.
+        remote()->transact(RENDERER_RENDER, data, &reply);
+    }
+};
+
+IMPLEMENT_META_INTERFACE(OMXRenderer, "android.hardware.IOMXRenderer");
+
+status_t BnOMXRenderer::onTransact(
+    uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
+    switch (code) {
+        case RENDERER_RENDER:
+        {
+            CHECK_INTERFACE(IOMXRenderer, data, reply);
+
+            IOMX::buffer_id buffer = readVoidStar(&data);
+
+            render(buffer);
+
+            return NO_ERROR;
+        }
+
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
 }  // namespace android
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 5be9224..0a44762 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -19,14 +19,10 @@
         MediaSource.cpp           \
         MetaData.cpp              \
         MmapSource.cpp            \
-        QComHardwareRenderer.cpp  \
         SampleTable.cpp           \
         ShoutcastSource.cpp       \
-        SoftwareRenderer.cpp      \
-        SurfaceRenderer.cpp       \
         TimeSource.cpp            \
         TimedEventQueue.cpp       \
-        TIHardwareRenderer.cpp    \
         Utils.cpp                 \
         AudioPlayer.cpp           \
         ESDS.cpp                  \
diff --git a/media/libstagefright/MediaPlayerImpl.cpp b/media/libstagefright/MediaPlayerImpl.cpp
index 04c9a11..341f002 100644
--- a/media/libstagefright/MediaPlayerImpl.cpp
+++ b/media/libstagefright/MediaPlayerImpl.cpp
@@ -35,12 +35,8 @@
 #include <media/stagefright/MetaData.h>
 #include <media/stagefright/MmapSource.h>
 #include <media/stagefright/OMXDecoder.h>
-#include <media/stagefright/QComHardwareRenderer.h>
 #include <media/stagefright/ShoutcastSource.h>
-#include <media/stagefright/SoftwareRenderer.h>
-#include <media/stagefright/SurfaceRenderer.h>
 #include <media/stagefright/TimeSource.h>
-#include <media/stagefright/TIHardwareRenderer.h>
 #include <ui/PixelFormat.h>
 #include <ui/Surface.h>
 
@@ -61,7 +57,6 @@
       mDuration(0),
       mPlaying(false),
       mPaused(false),
-      mRenderer(NULL),
       mSeeking(false),
       mFrameSize(0),
       mUseSoftwareColorConversion(false) {
@@ -121,7 +116,6 @@
       mDuration(0),
       mPlaying(false),
       mPaused(false),
-      mRenderer(NULL),
       mSeeking(false),
       mFrameSize(0),
       mUseSoftwareColorConversion(false) {
@@ -379,7 +373,7 @@
 
     {
         Mutex::Autolock autoLock(mLock);
-        if (mRenderer != NULL) {
+        if (mVideoRenderer.get() != NULL) {
             sendFrameToISurface(buffer);
         }
     }
@@ -652,52 +646,26 @@
     success = success && meta->findInt32(kKeyHeight, &decodedHeight);
     assert(success);
 
-    static const int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00;
+    const sp<ISurface> &isurface =
+        mSurface.get() != NULL ? mSurface->getISurface() : mISurface;
 
-    if (mSurface.get() != NULL) {
-        LOGW("Using SurfaceRenderer.");
-        mRenderer =
-            new SurfaceRenderer(
-                    mSurface, mVideoWidth, mVideoHeight,
-                    decodedWidth, decodedHeight);
-    } else if (format == OMX_QCOM_COLOR_FormatYVU420SemiPlanar
-        && !strncmp(component, "OMX.qcom.video.decoder.", 23)) {
-        LOGW("Using QComHardwareRenderer.");
-        mRenderer =
-            new QComHardwareRenderer(
-                    mISurface, mVideoWidth, mVideoHeight,
-                    decodedWidth, decodedHeight);
-    } else if (format == OMX_COLOR_FormatCbYCrY
-            && !strcmp(component, "OMX.TI.Video.Decoder")) {
-        LOGW("Using TIHardwareRenderer.");
-        mRenderer =
-            new TIHardwareRenderer(
-                    mISurface, mVideoWidth, mVideoHeight,
-                    decodedWidth, decodedHeight);
-    } else {
-        LOGW("Using software renderer.");
-        mRenderer = new SoftwareRenderer(
-                mISurface, mVideoWidth, mVideoHeight,
-                decodedWidth, decodedHeight);
-    }
+    mVideoRenderer =
+        mClient.interface()->createRenderer(
+                isurface, component,
+                (OMX_COLOR_FORMATTYPE)format,
+                decodedWidth, decodedHeight,
+                mVideoWidth, mVideoHeight);
 }
 
 void MediaPlayerImpl::depopulateISurface() {
-    delete mRenderer;
-    mRenderer = NULL;
+    mVideoRenderer.clear();
 }
 
 void MediaPlayerImpl::sendFrameToISurface(MediaBuffer *buffer) {
-    void *platformPrivate;
-    if (!buffer->meta_data()->findPointer(
-                kKeyPlatformPrivate, &platformPrivate)) {
-        platformPrivate = NULL;
+    void *id;
+    if (buffer->meta_data()->findPointer(kKeyBufferID, &id)) {
+        mVideoRenderer->render((IOMX::buffer_id)id);
     }
-
-    mRenderer->render(
-        (const uint8_t *)buffer->data() + buffer->range_offset(),
-        buffer->range_length(),
-        platformPrivate);
 }
 
 void MediaPlayerImpl::setAudioSink(
diff --git a/media/libstagefright/OMXDecoder.cpp b/media/libstagefright/OMXDecoder.cpp
index 5e44999..780cd2e 100644
--- a/media/libstagefright/OMXDecoder.cpp
+++ b/media/libstagefright/OMXDecoder.cpp
@@ -154,8 +154,7 @@
     if (!strncmp(codec, "OMX.qcom.video.", 15)) {
         quirks |= kRequiresLoadedToIdleAfterAllocation;
     }
-    if (!strcmp(codec, "OMX.TI.AAC.decode")
-        || !strcmp(codec, "OMX.TI.MP3.decode")) {
+    if (!strcmp(codec, "OMX.TI.MP3.decode")) {
         quirks |= kMeasuresTimeInMilliseconds;
     }
 
@@ -1551,6 +1550,10 @@
             kKeyPlatformPrivate,
             msg.u.extended_buffer_data.platform_private);
 
+    media_buffer->meta_data()->setPointer(
+            kKeyBufferID,
+            msg.u.extended_buffer_data.buffer);
+
     if (msg.u.extended_buffer_data.flags & OMX_BUFFERFLAG_EOS) {
         mErrorCondition = ERROR_END_OF_STREAM;
     }
diff --git a/media/libstagefright/SurfaceRenderer.cpp b/media/libstagefright/SurfaceRenderer.cpp
deleted file mode 100644
index e54288d..0000000
--- a/media/libstagefright/SurfaceRenderer.cpp
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2009 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.
- */
-
-#define LOG_TAG "SurfaceRenderer"
-#include <utils/Log.h>
-
-#undef NDEBUG
-#include <assert.h>
-
-#include <media/stagefright/SurfaceRenderer.h>
-#include <ui/Surface.h>
-
-namespace android {
-
-SurfaceRenderer::SurfaceRenderer(
-        const sp<Surface> &surface,
-        size_t displayWidth, size_t displayHeight,
-        size_t decodedWidth, size_t decodedHeight)
-    : mSurface(surface),
-      mDisplayWidth(displayWidth),
-      mDisplayHeight(displayHeight),
-      mDecodedWidth(decodedWidth),
-      mDecodedHeight(decodedHeight) {
-}
-
-SurfaceRenderer::~SurfaceRenderer() {
-}
-
-void SurfaceRenderer::render(
-        const void *data, size_t size, void *platformPrivate) {
-    Surface::SurfaceInfo info;
-    status_t err = mSurface->lock(&info);
-    if (err != OK) {
-        return;
-    }
-
-    const uint8_t *src = (const uint8_t *)data;
-    uint8_t *dst = (uint8_t *)info.bits;
-
-    for (size_t i = 0; i < mDisplayHeight; ++i) {
-        memcpy(dst, src, mDisplayWidth);
-        src += mDecodedWidth;
-        dst += mDisplayWidth;
-    }
-    src += (mDecodedHeight - mDisplayHeight) * mDecodedWidth;
-    
-    for (size_t i = 0; i < (mDisplayHeight + 1) / 2; ++i) {
-        memcpy(dst, src, (mDisplayWidth + 1) & ~1);
-        src += (mDecodedWidth + 1) & ~1;
-        dst += (mDisplayWidth + 1) & ~1;
-    }
-
-    mSurface->unlockAndPost();
-}
-
-}  // namespace android
diff --git a/media/libstagefright/omx/Android.mk b/media/libstagefright/omx/Android.mk
index 9c6d475..2e564e9 100644
--- a/media/libstagefright/omx/Android.mk
+++ b/media/libstagefright/omx/Android.mk
@@ -9,13 +9,17 @@
 LOCAL_CFLAGS := $(PV_CFLAGS_MINUS_VISIBILITY)
 
 LOCAL_SRC_FILES:=                 \
-	OMX.cpp
+	OMX.cpp                   \
+        QComHardwareRenderer.cpp  \
+        SoftwareRenderer.cpp      \
+        TIHardwareRenderer.cpp
 
-LOCAL_SHARED_LIBRARIES := \
-        libbinder         \
-        libmedia          \
-	libutils          \
-        libui             \
+LOCAL_SHARED_LIBRARIES :=       \
+        libbinder               \
+        libmedia                \
+	libutils                \
+        libui                   \
+        libcutils               \
         libopencore_common
 
 LOCAL_PRELINK_MODULE:= false
diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp
index daaa741..062afd4 100644
--- a/media/libstagefright/omx/OMX.cpp
+++ b/media/libstagefright/omx/OMX.cpp
@@ -24,9 +24,15 @@
 #include <assert.h>
 
 #include "OMX.h"
+#include "OMXRenderer.h"
+
 #include "pv_omxcore.h"
 
 #include <binder/IMemory.h>
+#include <media/stagefright/QComHardwareRenderer.h>
+#include <media/stagefright/SoftwareRenderer.h>
+#include <media/stagefright/TIHardwareRenderer.h>
+#include <media/stagefright/VideoRenderer.h>
 
 #include <OMX_Component.h>
 
@@ -619,5 +625,62 @@
 }
 #endif
 
+////////////////////////////////////////////////////////////////////////////////
+
+sp<IOMXRenderer> OMX::createRenderer(
+        const sp<ISurface> &surface,
+        const char *componentName,
+        OMX_COLOR_FORMATTYPE colorFormat,
+        size_t encodedWidth, size_t encodedHeight,
+        size_t displayWidth, size_t displayHeight) {
+    VideoRenderer *impl = NULL;
+
+    static const int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00;
+
+    if (colorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar
+        && !strncmp(componentName, "OMX.qcom.video.decoder.", 23)) {
+        LOGW("Using QComHardwareRenderer.");
+        impl =
+            new QComHardwareRenderer(
+                    surface,
+                    displayWidth, displayHeight,
+                    encodedWidth, encodedHeight);
+    } else if (colorFormat == OMX_COLOR_FormatCbYCrY
+            && !strcmp(componentName, "OMX.TI.Video.Decoder")) {
+        LOGW("Using TIHardwareRenderer.");
+        impl =
+            new TIHardwareRenderer(
+                    surface,
+                    displayWidth, displayHeight,
+                    encodedWidth, encodedHeight);
+    } else {
+        LOGW("Using software renderer.");
+        impl = new SoftwareRenderer(
+                surface,
+                displayWidth, displayHeight,
+                encodedWidth, encodedHeight);
+    }
+
+    return new OMXRenderer(impl);
+}
+
+OMXRenderer::OMXRenderer(VideoRenderer *impl)
+    : mImpl(impl) {
+}
+
+OMXRenderer::~OMXRenderer() {
+    delete mImpl;
+    mImpl = NULL;
+}
+
+void OMXRenderer::render(IOMX::buffer_id buffer) {
+    OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer;
+
+    mImpl->render(
+            header->pBuffer + header->nOffset,
+            header->nFilledLen,
+            header->pPlatformPrivate);
+}
+
 }  // namespace android
 
diff --git a/media/libstagefright/omx/OMX.h b/media/libstagefright/omx/OMX.h
index ed4e5dd..20430bb 100644
--- a/media/libstagefright/omx/OMX.h
+++ b/media/libstagefright/omx/OMX.h
@@ -79,6 +79,13 @@
             OMX_U32 flags, OMX_TICKS timestamp);
 #endif
 
+    virtual sp<IOMXRenderer> createRenderer(
+            const sp<ISurface> &surface,
+            const char *componentName,
+            OMX_COLOR_FORMATTYPE colorFormat,
+            size_t encodedWidth, size_t encodedHeight,
+            size_t displayWidth, size_t displayHeight);
+
 private:
     static OMX_CALLBACKTYPE kCallbacks;
 
diff --git a/media/libstagefright/omx/OMXRenderer.h b/media/libstagefright/omx/OMXRenderer.h
new file mode 100644
index 0000000..4d194ce
--- /dev/null
+++ b/media/libstagefright/omx/OMXRenderer.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+#ifndef OMX_RENDERER_H_
+
+#define OMX_RENDERER_H_
+
+#include <media/IOMX.h>
+
+namespace android {
+
+class VideoRenderer;
+
+class OMXRenderer : public BnOMXRenderer {
+public:
+    // Assumes ownership of "impl".
+    OMXRenderer(VideoRenderer *impl);
+    virtual ~OMXRenderer();
+
+    virtual void render(IOMX::buffer_id buffer);
+
+private:
+    VideoRenderer *mImpl;
+
+    OMXRenderer(const OMXRenderer &);
+    OMXRenderer &operator=(const OMXRenderer &);
+};
+
+}  // namespace android
+
+#endif  // OMX_RENDERER_H_
diff --git a/media/libstagefright/QComHardwareRenderer.cpp b/media/libstagefright/omx/QComHardwareRenderer.cpp
similarity index 100%
rename from media/libstagefright/QComHardwareRenderer.cpp
rename to media/libstagefright/omx/QComHardwareRenderer.cpp
diff --git a/media/libstagefright/SoftwareRenderer.cpp b/media/libstagefright/omx/SoftwareRenderer.cpp
similarity index 96%
rename from media/libstagefright/SoftwareRenderer.cpp
rename to media/libstagefright/omx/SoftwareRenderer.cpp
index 66b6b07..5483238 100644
--- a/media/libstagefright/SoftwareRenderer.cpp
+++ b/media/libstagefright/omx/SoftwareRenderer.cpp
@@ -61,6 +61,10 @@
 
 void SoftwareRenderer::render(
         const void *data, size_t size, void *platformPrivate) {
+    if (size != (mDecodedHeight * mDecodedWidth * 3) / 2) {
+        LOGE("size is %d, expected %d",
+                size, (mDecodedHeight * mDecodedWidth * 3) / 2);
+    }
     assert(size >= (mDecodedWidth * mDecodedHeight * 3) / 2);
 
     static const signed kClipMin = -278;
diff --git a/media/libstagefright/TIHardwareRenderer.cpp b/media/libstagefright/omx/TIHardwareRenderer.cpp
similarity index 100%
rename from media/libstagefright/TIHardwareRenderer.cpp
rename to media/libstagefright/omx/TIHardwareRenderer.cpp
diff --git a/telephony/java/com/android/internal/telephony/CommandsInterface.java b/telephony/java/com/android/internal/telephony/CommandsInterface.java
index c52fe06..6ebd8d6 100644
--- a/telephony/java/com/android/internal/telephony/CommandsInterface.java
+++ b/telephony/java/com/android/internal/telephony/CommandsInterface.java
@@ -1300,11 +1300,13 @@
      *            the username for APN, or NULL
      * @param password
      *            the password for APN, or NULL
+     * @param authType
+     *            the PAP / CHAP auth type. Values is one of SETUP_DATA_AUTH_*
      * @param result
      *            Callback message
      */
     public void setupDataCall(String radioTechnology, String profile, String apn,
-            String user, String password, Message result);
+            String user, String password, String authType, Message result);
 
     /**
      * Deactivate packet data connection
diff --git a/telephony/java/com/android/internal/telephony/RIL.java b/telephony/java/com/android/internal/telephony/RIL.java
index 52f6526..50bf218 100644
--- a/telephony/java/com/android/internal/telephony/RIL.java
+++ b/telephony/java/com/android/internal/telephony/RIL.java
@@ -1237,10 +1237,17 @@
      */
     public void
     setupDefaultPDP(String apn, String user, String password, Message result) {
-        String radioTechnology = "1"; //0 for CDMA, 1 for GSM/UMTS
+        int radioTechnology;
+        int authType;
         String profile = ""; //profile number, NULL for GSM/UMTS
-        setupDataCall(radioTechnology, profile, apn, user,
-                password, result);
+
+        radioTechnology = RILConstants.SETUP_DATA_TECH_GSM;
+        //TODO(): Add to the APN database, AuthType is set to CHAP/PAP
+        authType = (user != null) ? RILConstants.SETUP_DATA_AUTH_PAP_CHAP
+                : RILConstants.SETUP_DATA_AUTH_NONE;
+
+        setupDataCall(Integer.toString(radioTechnology), profile, apn, user,
+                password, Integer.toString(authType), result);
 
     }
 
@@ -1259,7 +1266,7 @@
      */
     public void
     setupDataCall(String radioTechnology, String profile, String apn,
-            String user, String password, Message result) {
+            String user, String password, String authType, Message result) {
         RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_SETUP_DATA_CALL, result);
 
@@ -1270,15 +1277,12 @@
         rr.mp.writeString(apn);
         rr.mp.writeString(user);
         rr.mp.writeString(password);
-        //TODO(): Add to the APN database, AuthType is set to CHAP/PAP
-        // 0 => Neither PAP nor CHAP will be performed, 3 => PAP / CHAP will be performed.
-        if (user != null)
-            rr.mp.writeString("3");
-        else
-            rr.mp.writeString("0");
+        rr.mp.writeString(authType);
 
-        if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " "
-                + apn);
+        if (RILJ_LOGD) riljLog(rr.serialString() + "> "
+                + requestToString(rr.mRequest) + " " + radioTechnology + " "
+                + profile + " " + apn + " " + user + " "
+                + password + " " + authType);
 
         send(rr);
     }
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index 0763e63..90a82f9 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -79,6 +79,14 @@
     int CDM_TTY_HCO_MODE = 2;
     int CDM_TTY_VCO_MODE = 3;
 
+    /* Setup a packet data connection. See ril.h RIL_REQUEST_SETUP_DATA_CALL */
+    int SETUP_DATA_TECH_CDMA      = 0;
+    int SETUP_DATA_TECH_GSM       = 1;
+    int SETUP_DATA_AUTH_NONE      = 0;
+    int SETUP_DATA_AUTH_PAP       = 1;
+    int SETUP_DATA_AUTH_CHAP      = 2;
+    int SETUP_DATA_AUTH_PAP_CHAP  = 3;
+
 /*
 cat include/telephony/ril.h | \
    egrep '^#define' | \
diff --git a/telephony/java/com/android/internal/telephony/SmsMessageBase.java b/telephony/java/com/android/internal/telephony/SmsMessageBase.java
index 7a15c32..6177c8a 100644
--- a/telephony/java/com/android/internal/telephony/SmsMessageBase.java
+++ b/telephony/java/com/android/internal/telephony/SmsMessageBase.java
@@ -372,16 +372,10 @@
          * -or-
          * 2. [x@y][ ]/[body]
          */
-         String[] parts = messageBody.split("( /)|( )", 3);
-         if (parts.length < 2 || parts[0].indexOf('@') == -1) return;
+         String[] parts = messageBody.split("( /)|( )", 2);
+         if (parts.length < 1 || parts[0].indexOf('@') == -1) return;
          emailFrom = parts[0];
-         if (parts.length == 3) {
-             pseudoSubject = parts[1];
-             emailBody = parts[2];
-         } else {
-             pseudoSubject = null;
-             emailBody = parts[1];
-         }
+         emailBody = parts[1];
          isEmail = true;
     }
 
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java
index fef6d3c..4588f36 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java
@@ -143,9 +143,10 @@
         lastFailTime = -1;
         lastFailCause = FailCause.NONE;
         receivedDisconnectReq = false;
-        phone.mCM.setupDataCall(Integer.toString(RILConstants.CDMA_PHONE),
+        phone.mCM.setupDataCall(Integer.toString(RILConstants.SETUP_DATA_TECH_CDMA),
                 Integer.toString(RILConstants.DATA_PROFILE_DEFAULT), null, null,
-                null, obtainMessage(EVENT_SETUP_DATA_CONNECTION_DONE));
+                null, Integer.toString(RILConstants.SETUP_DATA_AUTH_PAP_CHAP),
+                obtainMessage(EVENT_SETUP_DATA_CONNECTION_DONE));
     }
 
     private void tearDownData(Message msg) {
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java b/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
index 3ab1f77..1f1f7c1 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
@@ -19,6 +19,7 @@
 
 import android.app.Activity;
 import android.app.PendingIntent;
+import android.app.PendingIntent.CanceledException;
 import android.content.ContentValues;
 import android.content.SharedPreferences;
 import android.database.Cursor;
@@ -31,6 +32,7 @@
 import android.preference.PreferenceManager;
 import android.util.Config;
 import android.util.Log;
+import android.telephony.SmsManager;
 
 import com.android.internal.telephony.TelephonyProperties;
 import com.android.internal.telephony.CommandsInterface;
@@ -45,6 +47,7 @@
 import java.io.ByteArrayOutputStream;
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.lang.Boolean;
 
 
 final class CdmaSMSDispatcher extends SMSDispatcher {
@@ -331,6 +334,24 @@
                 sentIntent, deliveryIntent);
     }
 
+    protected void sendRawPdu(byte[] smsc, byte[] pdu, PendingIntent sentIntent,
+            PendingIntent deliveryIntent) {
+        String inEcm = SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE);
+        if (Boolean.parseBoolean(inEcm)) {
+            if (sentIntent != null) {
+                try {
+                    sentIntent.send(SmsManager.RESULT_ERROR_NO_SERVICE);
+                } catch (CanceledException ex) {}
+            }
+            if (Config.LOGD) {
+                Log.d(TAG, "Block SMS in Emergency Callback mode");
+            }
+            return;
+        }
+
+        super.sendRawPdu(smsc, pdu, sentIntent, deliveryIntent);
+    }
+
     /** {@inheritDoc} */
     protected void sendSms(SmsTracker tracker) {
         HashMap map = tracker.mData;
diff --git a/telephony/java/com/android/internal/telephony/gsm/PdpConnection.java b/telephony/java/com/android/internal/telephony/gsm/PdpConnection.java
index 89de867..224419e 100644
--- a/telephony/java/com/android/internal/telephony/gsm/PdpConnection.java
+++ b/telephony/java/com/android/internal/telephony/gsm/PdpConnection.java
@@ -84,9 +84,13 @@
         lastFailCause = FailCause.NONE;
         receivedDisconnectReq = false;
 
-        phone.mCM.setupDataCall(Integer.toString(RILConstants.GSM_PHONE),
+        int authType = (apn.user != null) ? RILConstants.SETUP_DATA_AUTH_PAP_CHAP :
+            RILConstants.SETUP_DATA_AUTH_NONE;
+
+        phone.mCM.setupDataCall(Integer.toString(RILConstants.SETUP_DATA_TECH_GSM),
                 Integer.toString(RILConstants.DATA_PROFILE_DEFAULT), apn.apn, apn.user,
-                apn.password, obtainMessage(EVENT_SETUP_DATA_CONNECTION_DONE));
+                apn.password, Integer.toString(authType),
+                obtainMessage(EVENT_SETUP_DATA_CONNECTION_DONE));
     }
 
     private void tearDownData(Message msg) {
diff --git a/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java b/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java
index be5b842..11b3fd6 100644
--- a/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java
+++ b/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java
@@ -944,7 +944,7 @@
     }
 
     public void setupDataCall(String radioTechnology, String profile, String apn, String user,
-            String password, Message result) {
+            String password, String authType, Message result) {
         unimplemented(result);
     }