Merge "add all needed GL extension wrappers"
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 9807b89..3c5f53a 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -4413,7 +4413,7 @@
         });
     }
 
-    public static final ActivityThread systemMain() {
+    public static ActivityThread systemMain() {
         HardwareRenderer.disable(true);
         ActivityThread thread = new ActivityThread();
         thread.attach(true);
@@ -4454,6 +4454,8 @@
         ActivityThread thread = new ActivityThread();
         thread.attach(false);
 
+        AsyncTask.init();
+
         if (false) {
             Looper.myLooper().setMessageLogging(new
                     LogPrinter(Log.DEBUG, "ActivityThread"));
diff --git a/core/java/android/os/AsyncTask.java b/core/java/android/os/AsyncTask.java
index 5e9abb7..fd6bed7 100644
--- a/core/java/android/os/AsyncTask.java
+++ b/core/java/android/os/AsyncTask.java
@@ -135,6 +135,8 @@
  * <p>There are a few threading rules that must be followed for this class to
  * work properly:</p>
  * <ul>
+ *     <li>The AsyncTask class must be loaded on the UI thread. This is done
+ *     automatically as of {@link android.os.Build.VERSION_CODES#JELLY_BEAN}.</li>
  *     <li>The task instance must be created on the UI thread.</li>
  *     <li>{@link #execute} must be invoked on the UI thread.</li>
  *     <li>Do not call {@link #onPreExecute()}, {@link #onPostExecute},
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index c08a4024..fa4dd25 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -189,7 +189,7 @@
     }
 
     private static native int nGetMaximumTextureWidth();
-    private static native int nGetMaximumTextureHeight();    
+    private static native int nGetMaximumTextureHeight();
 
     ///////////////////////////////////////////////////////////////////////////
     // Setup
@@ -268,6 +268,24 @@
 
     private static native void nFinish(int renderer);
 
+    /**
+     * Returns the size of the stencil buffer required by the underlying
+     * implementation.
+     * 
+     * @return The minimum number of bits the stencil buffer must. Always >= 0.
+     * 
+     * @hide
+     */
+    public static int getStencilSize() {
+        return nGetStencilSize();
+    }
+
+    private static native int nGetStencilSize();
+
+    ///////////////////////////////////////////////////////////////////////////
+    // Functor
+    ///////////////////////////////////////////////////////////////////////////
+
     @Override
     public boolean callDrawGLFunction(int drawGLFunction) {
         return nCallDrawGLFunction(mRenderer, drawGLFunction);
@@ -275,7 +293,6 @@
 
     private static native boolean nCallDrawGLFunction(int renderer, int drawGLFunction);
 
-
     ///////////////////////////////////////////////////////////////////////////
     // Memory
     ///////////////////////////////////////////////////////////////////////////
@@ -361,6 +378,12 @@
 
     private static native int nGetDisplayListSize(int displayList);
 
+    static void setDisplayListName(int displayList, String name) {
+        nSetDisplayListName(displayList, name);
+    }
+
+    private static native void nSetDisplayListName(int displayList, String name);
+
     @Override
     public boolean drawDisplayList(DisplayList displayList, int width, int height, Rect dirty) {
         return nDrawDisplayList(mRenderer,
diff --git a/core/java/android/view/GLES20DisplayList.java b/core/java/android/view/GLES20DisplayList.java
index 0cb9449..969c9ab 100644
--- a/core/java/android/view/GLES20DisplayList.java
+++ b/core/java/android/view/GLES20DisplayList.java
@@ -31,10 +31,17 @@
     private GLES20RecordingCanvas mCanvas;
     private boolean mValid;
 
+    // Used for debugging
+    private final String mName;
+
     // The native display list will be destroyed when this object dies.
     // DO NOT overwrite this reference once it is set.
     private DisplayListFinalizer mFinalizer;
 
+    GLES20DisplayList(String name) {
+        mName = name;
+    }
+
     int getNativeDisplayList() {
         if (!mValid || mFinalizer == null) {
             throw new IllegalStateException("The display list is not valid.");
@@ -75,6 +82,7 @@
                 mCanvas.end(mFinalizer.mNativeDisplayList);
             } else {
                 mFinalizer = new DisplayListFinalizer(mCanvas.end(0));
+                GLES20Canvas.setDisplayListName(mFinalizer.mNativeDisplayList, mName);
             }
             mCanvas.recycle();
             mCanvas = null;
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index 1c9cbbf..9e8a228 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -283,9 +283,12 @@
      * Creates a new display list that can be used to record batches of
      * drawing operations.
      * 
+     * @param name The name of the display list, used for debugging purpose.
+     *             May be null
+     * 
      * @return A new display list.
      */
-    public abstract DisplayList createDisplayList();
+    public abstract DisplayList createDisplayList(String name);
 
     /**
      * Creates a new hardware layer. A hardware layer built by calling this
@@ -1047,7 +1050,7 @@
                     EGL_BLUE_SIZE, 8,
                     EGL_ALPHA_SIZE, 8,
                     EGL_DEPTH_SIZE, 0,
-                    EGL_STENCIL_SIZE, 0,
+                    EGL_STENCIL_SIZE, GLES20Canvas.getStencilSize(),
                     EGL_SURFACE_TYPE, EGL_WINDOW_BIT |
                             (dirtyRegions ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0),
                     EGL_NONE
@@ -1094,8 +1097,8 @@
         }
 
         @Override
-        public DisplayList createDisplayList() {
-            return new GLES20DisplayList();
+        public DisplayList createDisplayList(String name) {
+            return new GLES20DisplayList(name);
         }
 
         @Override
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 39f603d..8597017 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -3770,6 +3770,14 @@
         }
 
         if ((mPrivateFlags & FOCUSED) != 0) {
+            // If this is the first focusable do not clear focus since the we
+            // try to give it focus every time a view clears its focus. Hence,
+            // the view that would gain focus already has it.
+            View firstFocusable = getFirstFocusable();
+            if (firstFocusable == this) {
+                return;
+            }
+
             mPrivateFlags &= ~FOCUSED;
 
             if (mParent != null) {
@@ -3778,9 +3786,24 @@
 
             onFocusChanged(false, 0, null);
             refreshDrawableState();
+
+            // The view cleared focus and invoked the callbacks, so  now is the
+            // time to give focus to the the first focusable to ensure that the
+            // gain focus is announced after clear focus.
+            if (firstFocusable != null) {
+                firstFocusable.requestFocus(FOCUS_FORWARD);
+            }
         }
     }
 
+    private View getFirstFocusable() {
+        ViewRootImpl viewRoot = getViewRootImpl();
+        if (viewRoot != null) {
+            return viewRoot.focusSearch(null, FOCUS_FORWARD);
+        }
+        return null;
+    }
+
     /**
      * Called to clear the focus of a view that is about to be removed.
      * Doesn't call clearChildFocus, which prevents this view from taking
@@ -10374,7 +10397,8 @@
             // we copy in child display lists into ours in drawChild()
             mRecreateDisplayList = true;
             if (mDisplayList == null) {
-                mDisplayList = mAttachInfo.mHardwareRenderer.createDisplayList();
+                final String name = getClass().getSimpleName();
+                mDisplayList = mAttachInfo.mHardwareRenderer.createDisplayList(name);
                 // If we're creating a new display list, make sure our parent gets invalidated
                 // since they will need to recreate their display list to account for this
                 // new child display list.
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index d906a16..7559862 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -675,11 +675,14 @@
      */
     @Override
     public void clearFocus() {
-        super.clearFocus();
-
-        // clear any child focus if it exists
-        if (mFocused != null) {
+        if (DBG) {
+            System.out.println(this + " clearFocus()");
+        }
+        if (mFocused == null) {
+            super.clearFocus();
+        } else {
             mFocused.clearFocus();
+            mFocused = null;
         }
     }
 
@@ -691,12 +694,12 @@
         if (DBG) {
             System.out.println(this + " unFocus()");
         }
-
-        super.unFocus();
-        if (mFocused != null) {
+        if (mFocused == null) {
+            super.unFocus();
+        } else {
             mFocused.unFocus();
+            mFocused = null;
         }
-        mFocused = null;
     }
 
     /**
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 1a4bdf4..2ef843b 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -168,6 +168,7 @@
     View mView;
     View mFocusedView;
     View mRealFocusedView;  // this is not set to null in touch mode
+    View mOldFocusedView;
     int mViewVisibility;
     boolean mAppVisible = true;
     int mOrigWindowType = -1;
@@ -2226,32 +2227,33 @@
 
     public void requestChildFocus(View child, View focused) {
         checkThread();
-        if (mFocusedView != focused) {
-            mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(mFocusedView, focused);
-            scheduleTraversals();
+
+        if (DEBUG_INPUT_RESIZE) {
+            Log.v(TAG, "Request child focus: focus now " + focused);
         }
+
+        mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(mOldFocusedView, focused);
+        scheduleTraversals();
+
         mFocusedView = mRealFocusedView = focused;
-        if (DEBUG_INPUT_RESIZE) Log.v(TAG, "Request child focus: focus now "
-                + mFocusedView);
     }
 
     public void clearChildFocus(View child) {
         checkThread();
 
-        View oldFocus = mFocusedView;
-
-        if (DEBUG_INPUT_RESIZE) Log.v(TAG, "Clearing child focus");
-        mFocusedView = mRealFocusedView = null;
-        if (mView != null && !mView.hasFocus()) {
-            // If a view gets the focus, the listener will be invoked from requestChildFocus()
-            if (!mView.requestFocus(View.FOCUS_FORWARD)) {
-                mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
-            }
-        } else if (oldFocus != null) {
-            mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
+        if (DEBUG_INPUT_RESIZE) {
+            Log.v(TAG, "Clearing child focus");
         }
-    }
 
+        mOldFocusedView = mFocusedView;
+
+        // Invoke the listener only if there is no view to take focus
+        if (focusSearch(null, View.FOCUS_FORWARD) == null) {
+            mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(mOldFocusedView, null);
+        }
+
+        mFocusedView = mRealFocusedView = null;
+    }
 
     public void focusableViewAvailable(View v) {
         checkThread();
@@ -2724,6 +2726,7 @@
                         mView.unFocus();
                         mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(focused, null);
                         mFocusedView = null;
+                        mOldFocusedView = null;
                         return true;
                     }
                 }
diff --git a/core/java/android/webkit/Network.java b/core/java/android/webkit/Network.java
index 30bbb04..ee9b949 100644
--- a/core/java/android/webkit/Network.java
+++ b/core/java/android/webkit/Network.java
@@ -169,7 +169,9 @@
             if (!ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction()))
                 return;
 
-            NetworkInfo info = (NetworkInfo)intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
+            final ConnectivityManager connManager = (ConnectivityManager) context
+                    .getSystemService(Context.CONNECTIVITY_SERVICE);
+            final NetworkInfo info = connManager.getActiveNetworkInfo();
             if (info != null)
                 mRoaming = info.isRoaming();
         };
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 40d8a77..164bc64 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -256,10 +256,7 @@
 
     private float mShadowRadius, mShadowDx, mShadowDy;
 
-    private static final int PREDRAW_NOT_REGISTERED = 0;
-    private static final int PREDRAW_PENDING = 1;
-    private static final int PREDRAW_DONE = 2;
-    private int mPreDrawState = PREDRAW_NOT_REGISTERED;
+    private boolean mPreDrawRegistered;
 
     private TextUtils.TruncateAt mEllipsize = null;
 
@@ -365,8 +362,6 @@
 
     private SpellChecker mSpellChecker;
 
-    private boolean mSoftInputShownOnFocus = true;
-
     // The alignment to pass to Layout, or null if not resolved.
     private Layout.Alignment mLayoutAlignment;
 
@@ -2384,29 +2379,6 @@
     }
 
     /**
-     * Sets whether the soft input method will be made visible when this
-     * TextView gets focused. The default is true.
-     *
-     * @attr ref android.R.styleable#TextView_softInputShownOnFocus
-     * @hide
-     */
-    @android.view.RemotableViewMethod
-    public final void setSoftInputShownOnFocus(boolean show) {
-        mSoftInputShownOnFocus = show;
-    }
-
-    /**
-     * Returns whether the soft input method will be made visible when this
-     * TextView gets focused. The default is true.
-     *
-     * @attr ref android.R.styleable#TextView_softInputShownOnFocus
-     * @hide
-     */
-    public final boolean getSoftInputShownOnFocus() {
-        return mSoftInputShownOnFocus;
-    }
-
-    /**
      * Returns the list of URLSpans attached to the text
      * (by {@link Linkify} or otherwise) if any.  You can call
      * {@link URLSpan#getURL} on them to find where they link to
@@ -4387,26 +4359,16 @@
     }
 
     private void registerForPreDraw() {
-        final ViewTreeObserver observer = getViewTreeObserver();
-
-        if (mPreDrawState == PREDRAW_NOT_REGISTERED) {
-            observer.addOnPreDrawListener(this);
-            mPreDrawState = PREDRAW_PENDING;
-        } else if (mPreDrawState == PREDRAW_DONE) {
-            mPreDrawState = PREDRAW_PENDING;
+        if (!mPreDrawRegistered) {
+            getViewTreeObserver().addOnPreDrawListener(this);
+            mPreDrawRegistered = true;
         }
-
-        // else state is PREDRAW_PENDING, so keep waiting.
     }
 
     /**
      * {@inheritDoc}
      */
     public boolean onPreDraw() {
-        if (mPreDrawState != PREDRAW_PENDING) {
-            return true;
-        }
-
         if (mLayout == null) {
             assumeLayout();
         }
@@ -4457,7 +4419,9 @@
             startSelectionActionMode();
         }
 
-        mPreDrawState = PREDRAW_DONE;
+        getViewTreeObserver().removeOnPreDrawListener(this);
+        mPreDrawRegistered = false;
+
         return !changed;
     }
 
@@ -4492,10 +4456,9 @@
     protected void onDetachedFromWindow() {
         super.onDetachedFromWindow();
 
-        final ViewTreeObserver observer = getViewTreeObserver();
-        if (mPreDrawState != PREDRAW_NOT_REGISTERED) {
-            observer.removeOnPreDrawListener(this);
-            mPreDrawState = PREDRAW_NOT_REGISTERED;
+        if (mPreDrawRegistered) {
+            getViewTreeObserver().removeOnPreDrawListener(this);
+            mPreDrawRegistered = false;
         }
 
         if (mError != null) {
@@ -4768,12 +4731,6 @@
 
     @Override
     protected void onDraw(Canvas canvas) {
-        if (mPreDrawState == PREDRAW_DONE) {
-            final ViewTreeObserver observer = getViewTreeObserver();
-            observer.removeOnPreDrawListener(this);
-            mPreDrawState = PREDRAW_NOT_REGISTERED;
-        }
-
         if (mCurrentAlpha <= ViewConfiguration.ALPHA_THRESHOLD_INT) return;
 
         restartMarqueeIfNeeded();
@@ -5040,7 +4997,7 @@
             if (mTextDisplayList == null || !mTextDisplayList.isValid() ||
                     !mTextDisplayListIsValid) {
                 if (mTextDisplayList == null) {
-                    mTextDisplayList = getHardwareRenderer().createDisplayList();
+                    mTextDisplayList = getHardwareRenderer().createDisplayList("Text");
                 }
 
                 final HardwareCanvas hardwareCanvas = mTextDisplayList.start();
@@ -5539,7 +5496,7 @@
                                 && mLayout != null && onCheckIsTextEditor()) {
                             InputMethodManager imm = InputMethodManager.peekInstance();
                             viewClicked(imm);
-                            if (imm != null && mSoftInputShownOnFocus) {
+                            if (imm != null) {
                                 imm.showSoftInput(this, 0);
                             }
                         }
@@ -8395,7 +8352,7 @@
                 // Show the IME, except when selecting in read-only text.
                 final InputMethodManager imm = InputMethodManager.peekInstance();
                 viewClicked(imm);
-                if (!mTextIsSelectable && mSoftInputShownOnFocus) {
+                if (!mTextIsSelectable) {
                     handled |= imm != null && imm.showSoftInput(this, 0);
                 }
 
@@ -10190,7 +10147,7 @@
         }
 
         final boolean selectionStarted = mSelectionActionMode != null || willExtract;
-        if (selectionStarted && !mTextIsSelectable && mSoftInputShownOnFocus) {
+        if (selectionStarted && !mTextIsSelectable) {
             // Show the IME to be able to replace text, except when selecting non editable text.
             final InputMethodManager imm = InputMethodManager.peekInstance();
             if (imm != null) {
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index 6a533c0..e19bb38 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -188,6 +188,14 @@
     renderer->finish();
 }
 
+static jint android_view_GLES20Canvas_getStencilSize(JNIEnv* env, jobject clazz) {
+    return OpenGLRenderer::getStencilSize();
+}
+
+// ----------------------------------------------------------------------------
+// Functor
+// ----------------------------------------------------------------------------
+
 static bool android_view_GLES20Canvas_callDrawGLFunction(JNIEnv* env, jobject clazz,
         OpenGLRenderer* renderer, Functor *functor) {
     android::uirenderer::Rect dirty;
@@ -618,6 +626,15 @@
     return displayList->getSize();
 }
 
+static void android_view_GLES20Canvas_setDisplayListName(JNIEnv* env,
+        jobject clazz, DisplayList* displayList, jstring name) {
+    if (name != NULL) {
+        const char* textArray = env->GetStringUTFChars(name, NULL);
+        displayList->setName(textArray);
+        env->ReleaseStringUTFChars(name, textArray);
+    }
+}
+
 static OpenGLRenderer* android_view_GLES20Canvas_createDisplayListRenderer(JNIEnv* env,
         jobject clazz) {
     return new DisplayListRenderer;
@@ -808,6 +825,8 @@
     { "nPrepareDirty",      "(IIIIIZ)V",       (void*) android_view_GLES20Canvas_prepareDirty },
     { "nFinish",            "(I)V",            (void*) android_view_GLES20Canvas_finish },
 
+    { "nGetStencilSize",    "()I",             (void*) android_view_GLES20Canvas_getStencilSize },
+
     { "nCallDrawGLFunction", "(II)Z",
             (void*) android_view_GLES20Canvas_callDrawGLFunction },
 
@@ -880,10 +899,14 @@
     { "nGetDisplayList",         "(II)I",      (void*) android_view_GLES20Canvas_getDisplayList },
     { "nDestroyDisplayList",     "(I)V",       (void*) android_view_GLES20Canvas_destroyDisplayList },
     { "nGetDisplayListSize",     "(I)I",       (void*) android_view_GLES20Canvas_getDisplayListSize },
-    { "nCreateDisplayListRenderer", "()I",     (void*) android_view_GLES20Canvas_createDisplayListRenderer },
-    { "nResetDisplayListRenderer", "(I)V",     (void*) android_view_GLES20Canvas_resetDisplayListRenderer },
+    { "nSetDisplayListName",     "(ILjava/lang/String;)V",
+                                               (void*) android_view_GLES20Canvas_setDisplayListName },
     { "nDrawDisplayList",        "(IIIILandroid/graphics/Rect;)Z",
                                                (void*) android_view_GLES20Canvas_drawDisplayList },
+
+    { "nCreateDisplayListRenderer", "()I",     (void*) android_view_GLES20Canvas_createDisplayListRenderer },
+    { "nResetDisplayListRenderer",  "(I)V",    (void*) android_view_GLES20Canvas_resetDisplayListRenderer },
+
     { "nOutputDisplayList",      "(II)V",      (void*) android_view_GLES20Canvas_outputDisplayList },
     { "nInterrupt",              "(I)V",       (void*) android_view_GLES20Canvas_interrupt },
     { "nResume",                 "(I)V",       (void*) android_view_GLES20Canvas_resume },
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 030a6b3..1175cbb 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -881,7 +881,7 @@
     <string name="replace" msgid="5781686059063148930">"Erstat..."</string>
     <string name="delete" msgid="6098684844021697789">"Slet"</string>
     <string name="copyUrl" msgid="2538211579596067402">"Kopier webadresse"</string>
-    <string name="selectTextMode" msgid="1018691815143165326">"Marker tekst"</string>
+    <string name="selectTextMode" msgid="1018691815143165326">"Markér tekst"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"Tekstmarkering"</string>
     <string name="addToDictionary" msgid="9090375111134433012">"føj til ordbog"</string>
     <string name="deleteText" msgid="7070985395199629156">"slet"</string>
diff --git a/core/tests/bandwidthtests/src/com/android/bandwidthtest/util/ConnectionUtil.java b/core/tests/bandwidthtests/src/com/android/bandwidthtest/util/ConnectionUtil.java
index a5e5ab0e..dfcbba9 100644
--- a/core/tests/bandwidthtests/src/com/android/bandwidthtest/util/ConnectionUtil.java
+++ b/core/tests/bandwidthtests/src/com/android/bandwidthtest/util/ConnectionUtil.java
@@ -146,10 +146,10 @@
                 Log.v("ConnectivityReceiver", "onReceive() called with " + intent);
                 return;
             }
-            if (intent.hasExtra(ConnectivityManager.EXTRA_NETWORK_INFO)) {
-                mNetworkInfo = (NetworkInfo)
-                        intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
-            }
+
+            final ConnectivityManager connManager = (ConnectivityManager) context
+                    .getSystemService(Context.CONNECTIVITY_SERVICE);
+            mNetworkInfo = connManager.getActiveNetworkInfo();
 
             if (intent.hasExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO)) {
                 mOtherNetworkInfo = (NetworkInfo)
diff --git a/core/tests/coretests/src/android/widget/focus/RequestFocus.java b/core/tests/coretests/src/android/widget/focus/RequestFocus.java
index af9ee17..21d762a 100644
--- a/core/tests/coretests/src/android/widget/focus/RequestFocus.java
+++ b/core/tests/coretests/src/android/widget/focus/RequestFocus.java
@@ -21,9 +21,7 @@
 import android.app.Activity;
 import android.os.Bundle;
 import android.os.Handler;
-import android.widget.LinearLayout;
 import android.widget.Button;
-import android.view.View;
 
 /**
  * Exercises cases where elements of the UI are requestFocus()ed.
diff --git a/core/tests/coretests/src/android/widget/focus/RequestFocusTest.java b/core/tests/coretests/src/android/widget/focus/RequestFocusTest.java
index a78b0c9..baf587e 100644
--- a/core/tests/coretests/src/android/widget/focus/RequestFocusTest.java
+++ b/core/tests/coretests/src/android/widget/focus/RequestFocusTest.java
@@ -16,21 +16,27 @@
 
 package android.widget.focus;
 
-import android.widget.focus.RequestFocus;
-import com.android.frameworks.coretests.R;
-
 import android.os.Handler;
-import android.test.ActivityInstrumentationTestCase;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.UiThreadTest;
 import android.test.suitebuilder.annotation.LargeTest;
 import android.test.suitebuilder.annotation.MediumTest;
-import android.widget.Button;
 import android.util.AndroidRuntimeException;
+import android.view.View;
+import android.view.View.OnFocusChangeListener;
+import android.view.ViewTreeObserver.OnGlobalFocusChangeListener;
+import android.widget.Button;
+
+import com.android.frameworks.coretests.R;
+
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * {@link RequestFocusTest} is set up to exercise cases where the views that
  * have focus become invisible or GONE.
  */
-public class RequestFocusTest extends ActivityInstrumentationTestCase<RequestFocus> {
+public class RequestFocusTest extends ActivityInstrumentationTestCase2<RequestFocus> {
 
     private Button mTopLeftButton;
     private Button mBottomLeftButton;
@@ -39,7 +45,7 @@
     private Handler mHandler;
 
     public RequestFocusTest() {
-        super("com.android.frameworks.coretests", RequestFocus.class);
+        super(RequestFocus.class);
     }
 
     @Override
@@ -94,4 +100,145 @@
                          e.getClass().getName());
         }
     }
+
+    /**
+     * This tests checks the case in which the first focusable View clears focus.
+     * In such a case the framework tries to give the focus to another View starting
+     * from the top. Hence, the framework will try to give focus to the view that
+     * wants to clear its focus. From a client perspective, the view does not loose
+     * focus after the call, therefore no callback for focus change should be invoked.
+     *
+     * @throws Exception If an error occurs.
+     */
+    @UiThreadTest
+    public void testOnFocusChangeNotCalledIfFocusDoesNotMove() throws Exception {
+        // Get the first focusable.
+        Button button = mTopLeftButton;
+
+        // Make sure that the button is the first focusable and focus it.
+        button.getRootView().requestFocus(View.FOCUS_DOWN);
+        assertTrue(button.hasFocus());
+
+        // Attach on focus change listener that should not be called.
+        button.setOnFocusChangeListener(new OnFocusChangeListener() {
+            @Override
+            public void onFocusChange(View v, boolean hasFocus) {
+                throw new IllegalStateException("Unexpeced call to"
+                        + "OnFocusChangeListener#onFocusChange");
+            }
+        });
+
+        // Attach on global focus change listener that should not be called.
+        button.getViewTreeObserver().addOnGlobalFocusChangeListener(
+                new OnGlobalFocusChangeListener() {
+            @Override
+            public void onGlobalFocusChanged(View oldFocus, View newFocus) {
+                throw new IllegalStateException("Unexpeced call to"
+                        + "OnFocusChangeListener#onFocusChange");
+            }
+        });
+
+        // Try to clear focus.
+        button.clearFocus();
+    }
+
+    /**
+     * This tests check whether the on focus change callbacks are invoked in
+     * the proper order when a View loses focus and the framework gives it to
+     * the fist focusable one.
+     *
+     * @throws Exception
+     */
+    @UiThreadTest
+    public void testOnFocusChangeCallbackOrder() throws Exception {
+        // Get the first focusable.
+        Button clearingFocusButton = mTopRightButton;
+        Button gainingFocusButton = mTopLeftButton;
+
+        // Make sure that the clearing focus is not the first focusable.
+        View focusCandidate = clearingFocusButton.getRootView().getParent().focusSearch(null,
+                View.FOCUS_FORWARD);
+        assertNotSame("The clearing focus button is not the first focusable.",
+                clearingFocusButton, focusCandidate);
+        assertSame("The gaining focus button is the first focusable.",
+                gainingFocusButton, focusCandidate);
+
+        // Focus the clearing focus button.
+        clearingFocusButton.requestFocus();
+        assertTrue(clearingFocusButton.hasFocus());
+
+        // Register the invocation order checker.
+        CallbackOrderChecker checker = new CallbackOrderChecker(clearingFocusButton,
+                gainingFocusButton);
+        clearingFocusButton.setOnFocusChangeListener(checker);
+        gainingFocusButton.setOnFocusChangeListener(checker);
+        clearingFocusButton.getViewTreeObserver().addOnGlobalFocusChangeListener(checker);
+
+        // Try to clear focus.
+        clearingFocusButton.clearFocus();
+
+        // Check that no callback was invoked since focus did not move.
+        checker.verify();
+    }
+
+    /**
+     * This class check whether the focus change callback are invoked in order.
+     */
+    private class CallbackOrderChecker implements OnFocusChangeListener,
+            OnGlobalFocusChangeListener {
+
+        private class CallbackInvocation {
+            final String mMethodName;
+            final Object[] mArguments;
+
+            CallbackInvocation(String methodName, Object[] arguments) {
+                mMethodName = methodName;
+                mArguments = arguments;
+            }
+        }
+
+        private final View mClearingFocusView;
+        private final View mGainingFocusView;
+
+        private final List<CallbackInvocation> mInvocations = new ArrayList<CallbackInvocation>();
+
+        public CallbackOrderChecker(View clearingFocusView, View gainingFocusView) {
+            mClearingFocusView = clearingFocusView;
+            mGainingFocusView = gainingFocusView;
+        }
+
+        @Override
+        public void onFocusChange(View view, boolean hasFocus) {
+            CallbackInvocation invocation = new CallbackInvocation(
+                    "OnFocusChangeListener#onFocusChange", new Object[] {view, hasFocus});
+            mInvocations.add(invocation);
+        }
+
+        @Override
+        public void onGlobalFocusChanged(View oldFocus, View newFocus) {
+            CallbackInvocation invocation = new CallbackInvocation(
+                    "OnFocusChangeListener#onFocusChange", new Object[] {oldFocus, newFocus});
+            mInvocations.add(invocation);
+        }
+
+        public void verify() {
+            assertSame("All focus change callback should be invoked.", 3, mInvocations.size());
+            assertInvioked("Callback for View clearing focus explected.", 0,
+                    "OnFocusChangeListener#onFocusChange",
+                    new Object[] {mClearingFocusView, false});
+            assertInvioked("Callback for View global focus change explected.", 1,
+                    "OnFocusChangeListener#onFocusChange", new Object[] {mClearingFocusView,
+                    mGainingFocusView});
+            assertInvioked("Callback for View gaining focus explected.", 2,
+                    "OnFocusChangeListener#onFocusChange", new Object[] {mGainingFocusView, true});
+        }
+
+        private void assertInvioked(String message, int order, String methodName,
+                Object[] arguments) {
+            CallbackInvocation invocation = mInvocations.get(order);
+            assertEquals(message, methodName, invocation.mMethodName);
+            assertEquals(message, arguments[0], invocation.mArguments[0]);
+            assertEquals(message, arguments[1], invocation.mArguments[1]);
+        }
+    }
 }
diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs
index 4e5badd..6c01d44 100644
--- a/docs/html/guide/guide_toc.cs
+++ b/docs/html/guide/guide_toc.cs
@@ -8,15 +8,16 @@
 <ul>
 
   <li>
-    <h2><span class="en">Android Basics</span>
-        <span class="de" style="display:none">Einführung in Android</span>
-        <span class="es" style="display:none">Información básica sobre Android</span>
-        <span class="fr" style="display:none">Présentation d'Android</span>
-        <span class="it" style="display:none">Nozioni di base su Android</span>
-        <span class="ja" style="display:none">Android の基本</span>
-        <span class="zh-CN" style="display:none">Android 基础知识</span>
-        <span class="zh-TW" style="display:none">Android 簡介</span>
-    </h2>
+    <span class="heading">
+      <span class="en">Android Basics</span>
+      <span class="de" style="display:none">Einführung in Android</span>
+      <span class="es" style="display:none">Información básica sobre Android</span>
+      <span class="fr" style="display:none">Présentation d'Android</span>
+      <span class="it" style="display:none">Nozioni di base su Android</span>
+      <span class="ja" style="display:none">Android の基本</span>
+      <span class="zh-CN" style="display:none">Android 基础知识</span>
+      <span class="zh-TW" style="display:none">Android 簡介</span>
+    </span>
     <ul>
       <li><a href="<?cs var:toroot ?>guide/basics/what-is-android.html">
         <span class="en">What Is Android?</span>
@@ -46,7 +47,7 @@
   </li>
 
   <li>
-    <h2>
+    <span class="heading">
       <span class="en">Framework Topics</span>
       <span class="de" style="display:none">Framework-Themen</span>
       <span class="es" style="display:none">Temas sobre el framework</span>
@@ -55,7 +56,7 @@
       <span class="ja" style="display:none">フレームワーク トピック</span>
       <span class="zh-CN" style="display:none">框架主题</span>
       <span class="zh-TW" style="display:none">架構主題</span>
-    </h2>
+    </span>
     <ul>
       <li class="toggle-list">
         <div><a href="<?cs var:toroot ?>guide/topics/fundamentals/activities.html">
@@ -443,9 +444,9 @@
   </li>
 
   <li>
-    <h2>
+    <span class="heading">
       <span class="en">Android Market Topics</span>
-    </h2>
+    </span>
     <ul>
       <li><a href="<?cs var:toroot ?>guide/publishing/publishing.html">
           <span class="en">Publishing on Android Market</span>
@@ -489,15 +490,16 @@
 
 
   <li>
-    <h2><span class="en">Developing</span>
-               <span class="de" style="display:none">Entwicklung</span>
-               <span class="es" style="display:none">Desarrollo</span>
-               <span class="fr" style="display:none">Développement</span>
-               <span class="it" style="display:none">Sviluppo</span>
-               <span class="ja" style="display:none">開発</span>
-               <span class="zh-CN" style="display:none">开发</span>
-               <span class="zh-TW" style="display:none">開發</span>
-    </h2>
+    <span class="heading">
+      <span class="en">Developing</span>
+      <span class="de" style="display:none">Entwicklung</span>
+      <span class="es" style="display:none">Desarrollo</span>
+      <span class="fr" style="display:none">Développement</span>
+      <span class="it" style="display:none">Sviluppo</span>
+      <span class="ja" style="display:none">開発</span>
+      <span class="zh-CN" style="display:none">开发</span>
+      <span class="zh-TW" style="display:none">開發</span>
+    </span>
     <ul>
   <!--<li><a href="">Developing for Android</a></li>
       signing, upgrading, selecting a package name, select device profile, touch, trackball, dpad available, etc. -->
@@ -683,15 +685,16 @@
   </li>
 
   <li>
-    <h2><span class="en">Publishing</span>
-        <span class="de" style="display:none">Veröffentlichung</span>
-        <span class="es" style="display:none">Publicación</span>
-        <span class="fr" style="display:none">Publication</span>
-        <span class="it" style="display:none">Pubblicazione</span>
-        <span class="ja" style="display:none">公開</span>
-        <span class="zh-CN" style="display:none">发布</span>
-        <span class="zh-TW" style="display:none">發佈</span>
-    </h2>
+    <span class="heading">
+      <span class="en">Publishing</span>
+      <span class="de" style="display:none">Veröffentlichung</span>
+      <span class="es" style="display:none">Publicación</span>
+      <span class="fr" style="display:none">Publication</span>
+      <span class="it" style="display:none">Pubblicazione</span>
+      <span class="ja" style="display:none">公開</span>
+      <span class="zh-CN" style="display:none">发布</span>
+      <span class="zh-TW" style="display:none">發佈</span>
+    </span>
     <ul>
       <li><a href="<?cs var:toroot ?>guide/publishing/publishing_overview.html">
             <span class="en">Publishing Overview</span>
@@ -733,15 +736,16 @@
   </li>
 
   <li>
-    <h2><span class="en">Best Practices</span>
-               <span class="de" style="display:none">Bewährte Verfahren</span>
-               <span class="es" style="display:none">Prácticas recomendadas</span>
-               <span class="fr" style="display:none">Meilleures pratiques</span>
-               <span class="it" style="display:none">Best practice</span>
-               <span class="ja" style="display:none">ベスト プラクティス</span>
-               <span class="zh-CN" style="display:none">最佳实践</span>
-               <span class="zh-TW" style="display:none">最佳實務</span>
-    </h2>
+    <span class="heading">
+      <span class="en">Best Practices</span>
+      <span class="de" style="display:none">Bewährte Verfahren</span>
+      <span class="es" style="display:none">Prácticas recomendadas</span>
+      <span class="fr" style="display:none">Meilleures pratiques</span>
+      <span class="it" style="display:none">Best practice</span>
+      <span class="ja" style="display:none">ベスト プラクティス</span>
+      <span class="zh-CN" style="display:none">最佳实践</span>
+      <span class="zh-TW" style="display:none">最佳實務</span>
+    </span>
     <ul>
       <li><a href="<?cs var:toroot ?>guide/practices/compatibility.html">
             <span class="en">Compatibility</span>
@@ -837,8 +841,9 @@
   </li>
 
   <li>
-    <h2><span class="en">Web Applications</span>
-    </h2>
+    <span class="heading">
+      <span class="en">Web Applications</span>
+    </span>
     <ul>
       <li><a href="<?cs var:toroot ?>guide/webapps/index.html">
             <span class="en">Web Apps Overview</span>
@@ -859,15 +864,16 @@
   </li>
 
   <li>
-    <h2><span class="en">Appendix</span>
-               <span class="de" style="display:none">Anhang</span>
-               <span class="es" style="display:none">Apéndice</span>
-               <span class="fr" style="display:none">Annexes</span>
-               <span class="it" style="display:none">Appendice</span>
-               <span class="ja" style="display:none">付録</span>
-               <span class="zh-CN" style="display:none">附录</span>
-               <span class="zh-TW" style="display:none">附錄</span>
-    </h2>
+    <span class="heading">
+      <span class="en">Appendix</span>
+      <span class="de" style="display:none">Anhang</span>
+      <span class="es" style="display:none">Apéndice</span>
+      <span class="fr" style="display:none">Annexes</span>
+      <span class="it" style="display:none">Appendice</span>
+      <span class="ja" style="display:none">付録</span>
+      <span class="zh-CN" style="display:none">附录</span>
+      <span class="zh-TW" style="display:none">附錄</span>
+    </span>
     <ul>
       <li><a href="<?cs var:toroot ?>guide/appendix/api-levels.html">
             <span class="en">Android API Levels</span>
diff --git a/docs/html/guide/topics/ui/how-android-draws.jd b/docs/html/guide/topics/ui/how-android-draws.jd
index 3a57afa..6a8cd86 100644
--- a/docs/html/guide/topics/ui/how-android-draws.jd
+++ b/docs/html/guide/topics/ui/how-android-draws.jd
@@ -62,7 +62,7 @@
 
    <p>
    The measure pass uses two classes to communicate dimensions. The
-   {@link android.view.View.MeasureSpec} class is used by Views to tell their parents how they
+   {@link android.view.ViewGroup.LayoutParams} class is used by Views to tell their parents how they
    want to be measured and positioned. The base LayoutParams class just
    describes how big the View wants to be for both width and height. For each
    dimension, it can specify one of:</p>
diff --git a/docs/html/guide/topics/ui/notifiers/notifications.jd b/docs/html/guide/topics/ui/notifiers/notifications.jd
index 33b0fec..bef9671 100644
--- a/docs/html/guide/topics/ui/notifiers/notifications.jd
+++ b/docs/html/guide/topics/ui/notifiers/notifications.jd
@@ -245,31 +245,27 @@
 activity like this can cause it to be mixed with your normal application back stack
 in undesired ways.  To make it behave correctly, in the manifest declaration
 for the activity the attributes 
-<code>android:launchMode="singleInstance"</code> and
+<code>android:launchMode="singleTask"</code>,
+<code>android:taskAffinity=""</code> and
 <code>android:excludeFromRecents="true"</code>
 must be set.  The full activity declaration for this sample is:</p>
 
 {@sample development/samples/ApiDemos/AndroidManifest.xml interstitial_affinity}
 
-<p>Because of the use of <code>singleInstance</code>, you must be careful about launching
-any other activities from this one.  These activities will be launched
-in their own task, and care must be taken to make sure this interacts
-well with the current state of your application's task.  This is essentially
+<p>You must be careful when launching other activities from this initial activity,
+because this is not a top-level part of the application, does not appear in
+recents, and needs to be relaunched at any point from the notification with new data
+to show.  This best approach is to make sure any activity launched from it is
+launched in its own task.  When doing this care must be taken to make sure this
+new task interacts well with the current state of your exiting application's
+task.  This is essentially
 the same as switching to the main application as described for the Email style
 notification shown before.  Given the <code>makeMessageIntentStack()</code>
-method previously shown, handling a click here would look something like this:</p>
+method previously shown, handling a click then would look something like this:</p>
 
 {@sample development/samples/ApiDemos/src/com/example/android/apis/app/IncomingMessageInterstitial.java
   app_launch}
 
-<p>If you don't want to use the <code>singleInstance</code> launch mode for
-this activity, an alternative approach is to use <code>android:taskAffinity=""</code>.
-This tells Android that the activity should not be treated as part of the
-main application flow, so it will not get mixed together with that.  All of the
-other issues discussed here do still apply, though this would allow you to start
-additional activities that are part of this notification task instead of switching
-to and replacing the main application task.</p>
-
 <h2 id="ManageYourNotifications">Managing your Notifications</h2>
 
 <p>The {@link android.app.NotificationManager} is a system service that manages all
diff --git a/docs/html/index.jd b/docs/html/index.jd
index c14c0ae..fdf860a 100644
--- a/docs/html/index.jd
+++ b/docs/html/index.jd
@@ -1,4 +1,5 @@
 home=true
+metaDescription=The official site for Android developers. Provides the Android SDK and documentation for app developers and designers.
 @jd:body
 
 
@@ -153,7 +154,7 @@
 + "href='https://plus.google.com/108967384991768947849'>+Android Developers</a>. "
 + "We'll use it to host Hangouts for developers, talk about the latest releases, "
 + "development and design tips, and much more.</p>"
-+ "<div style='margin-top:.7em'><g:plus href='https://plus.google.com/108967384991768947849' "
++ "<div style='margin:.7em 0 0 -1.2em'><g:plus href='https://plus.google.com/108967384991768947849' "
 + "size=\"smallbadge\" width=\"275\"></g:plus></div>"
     },
 
@@ -213,6 +214,3 @@
 var s = document.getElementsByTagName("script")[0];
 s.parentNode.insertBefore(po, s);
 })();</script>
-<style type="text/css">
-  #___plus_0, #___plus_0 iframe, #___plus_0 { width: 275px !important; }
-</style>
diff --git a/docs/html/resources/resources_toc.cs b/docs/html/resources/resources_toc.cs
index 628df9e..8483037 100644
--- a/docs/html/resources/resources_toc.cs
+++ b/docs/html/resources/resources_toc.cs
@@ -1,7 +1,8 @@
 <ul>
   <li>
-    <h2><span class="en">Android Training</span>
-    </h2>
+    <span class="heading">
+      <span class="en">Android Training</span>
+    </span>
     <ul>
       
       <li><a href="<?cs var:toroot ?>training/index.html">
@@ -237,8 +238,9 @@
       
       
   <li>
-    <h2><span class="en">Technical Resources</span>
-    </h2>
+    <span class="heading">
+      <span class="en">Technical Resources</span>
+    </span>
     <ul>
       <li class="toggle-list">
         <div><a href="<?cs var:toroot ?>resources/browser.html?tag=sample">
@@ -288,15 +290,16 @@
     </ul>
   </li>
   <li>
-    <h2><span class="en">Community</span>
-               <span style="display:none" class="de"></span>
-               <span style="display:none" class="es">Comunidad</span>
-               <span style="display:none" class="fr">Communauté</span>
-               <span style="display:none" class="it"></span>
-               <span style="display:none" class="ja">コミュニティ</span>
-               <span style="display:none" class="zh-CN">社区</span>
-               <span style="display:none" class="zh-TW">社群</span>
-    </h2>
+    <span class="heading">
+      <span class="en">Community</span>
+      <span style="display:none" class="de"></span>
+      <span style="display:none" class="es">Comunidad</span>
+      <span style="display:none" class="fr">Communauté</span>
+      <span style="display:none" class="it"></span>
+      <span style="display:none" class="ja">コミュニティ</span>
+      <span style="display:none" class="zh-CN">社区</span>
+      <span style="display:none" class="zh-TW">社群</span>
+    </span>
     <ul>
       <li><a href="<?cs var:toroot ?>resources/community-groups.html">
             <span class="en">Developer Forums</span>
@@ -309,8 +312,9 @@
 <?cs
   if:android.whichdoc == "online" ?>
   <li>
-    <h2><span class="en">Device Dashboard</span>
-    </h2>
+    <span class="heading">
+      <span class="en">Device Dashboard</span>
+    </span>
     <ul>
       <li><a href="<?cs var:toroot ?>resources/dashboard/platform-versions.html">
             <span class="en">Platform Versions</span>
@@ -327,7 +331,9 @@
 ?>
 
   <li>
-   <h2><span class="en">More</span></h2>
+    <span class="heading">
+      <span class="en">More</span>
+    </span>
     <ul>
       <li><a href="<?cs var:toroot ?>resources/faq/commontasks.html">
             <span class="en">Common Tasks </span>
diff --git a/docs/html/sdk/index.jd b/docs/html/sdk/index.jd
index 65a1f46..5cf05e0 100644
--- a/docs/html/sdk/index.jd
+++ b/docs/html/sdk/index.jd
@@ -1,4 +1,5 @@
 page.title=Android SDK
+page.metaDescription=Download the official Android SDK to develop apps for Android-powered devices.
 sdk.redirect=0
 
 sdk.win_installer=installer_r16-windows.exe
diff --git a/docs/html/sdk/sdk_toc.cs b/docs/html/sdk/sdk_toc.cs
index 5f6a57f..0de477a 100644
--- a/docs/html/sdk/sdk_toc.cs
+++ b/docs/html/sdk/sdk_toc.cs
@@ -1,7 +1,7 @@
 <?cs if:!sdk.redirect ?>
 <ul>
   <li>
-    <h2>
+    <span class="heading">
       <span class="en">Android SDK Starter Package</span>
       <span style="display:none" class="de">Aktuelle SDK-Version</span>
       <span style="display:none" class="es">Versión actual del SDK</span>
@@ -10,7 +10,7 @@
       <span style="display:none" class="ja">現在リリースされている SDK</span>
       <span style="display:none" class="zh-CN">当前的 SDK 版本</span>
       <span style="display:none" class="zh-TW">目前 SDK 發行版本</span>
-    </h2>
+    </span>
     <ul><?cs
   if:android.whichdoc == "online" ?>
       <li><a href="<?cs var:toroot ?>sdk/index.html">
@@ -37,7 +37,8 @@
     </ul>
   </li><?cs
   if:sdk.preview ?>
-  <li><h2>Android 3.0 Preview SDK</h2>
+  <li>
+    <span class="heading">Android 3.0 Preview SDK</span>
     <ul>
       <li><a href="<?cs var:toroot ?>sdk/preview/start.html">Getting Started</a> <span
 class="new">new!</span></li>
@@ -46,13 +47,14 @@
   /if ?>
   <?cs
   if:sdk.preview ?>
-  <li><h2>Android x.x Preview</h2>
+  <li>
+    <span class="heading">Android x.x Preview</span>
     <ul>
     </ul>
   </li><?cs
   /if ?>
   <li>
-    <h2>
+    <span class="heading">
       <span class="en">Downloadable SDK Components</span>
       <span style="display:none" class="de"></span>
       <span style="display:none" class="es"></span>
@@ -61,7 +63,7 @@
       <span style="display:none" class="ja"></span>
       <span style="display:none" class="zh-CN"></span>
       <span style="display:none" class="zh-TW"></span>
-    </h2>
+    </span>
     <ul>
       <li><a href="<?cs var:toroot ?>sdk/adding-components.html">
       <span class="en">Adding SDK Components</span>
@@ -158,7 +160,7 @@
     </ul>
   </li>
   <li>
-      <h2>
+    <span class="heading">
       <span class="en">ADT Plugin for Eclipse</span>
       <span style="display:none" class="de"></span>
       <span style="display:none" class="es"></span>
@@ -167,7 +169,7 @@
       <span style="display:none" class="ja"></span>
       <span style="display:none" class="zh-CN"></span>
       <span style="display:none" class="zh-TW"></span>
-      </h2>
+    </span>
     <ul>
       <li><a href="<?cs var:toroot ?>sdk/eclipse-adt.html">ADT 16.0.1
       <span style="display:none" class="de"></span>
@@ -182,7 +184,8 @@
     </ul>
   </li>
   <li>
-    <h2><span class="en">Native Development Tools</span>
+    <span class="heading">
+      <span class="en">Native Development Tools</span>
       <span style="display:none" class="de"></span>
       <span style="display:none" class="es"></span>
       <span style="display:none" class="fr"></span>
@@ -190,7 +193,7 @@
       <span style="display:none" class="ja"></span>
       <span style="display:none" class="zh-CN"></span>
       <span style="display:none" class="zh-TW"></span>
-    </h2>
+    </span>
     <ul>
       <li><a href="<?cs var:toroot ?>sdk/ndk/index.html">Android NDK, r7</a>
         <span class="new">new!</span>
@@ -200,7 +203,7 @@
   </li>
 
   <li>
-    <h2>
+    <span class="heading">
       <span class="en">More Information</span>
       <span style="display:none" class="de"></span>
       <span style="display:none" class="es"></span>
@@ -209,7 +212,7 @@
       <span style="display:none" class="ja"></span>
       <span style="display:none" class="zh-CN"></span>
       <span style="display:none" class="zh-TW"></span>
-    </h2>
+    </span>
     <ul>
       <li><a href="<?cs var:toroot ?>sdk/oem-usb.html">
         <span class="en">OEM USB Drivers</span>
diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp
index bc1db4d..07bf7bf 100644
--- a/graphics/jni/android_renderscript_RenderScript.cpp
+++ b/graphics/jni/android_renderscript_RenderScript.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 The Android Open Source Project
+ * Copyright (C) 2011-2012 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.
@@ -567,7 +567,7 @@
     jint len = _env->GetArrayLength(data);
     LOG_API("nAllocationElementData1D, con(%p), alloc(%p), offset(%i), comp(%i), len(%i), sizeBytes(%i)", con, (RsAllocation)alloc, offset, compIdx, len, sizeBytes);
     jbyte *ptr = _env->GetByteArrayElements(data, NULL);
-    rsAllocation1DElementData(con, (RsAllocation)alloc, offset, lod, ptr, compIdx, sizeBytes);
+    rsAllocation1DElementData(con, (RsAllocation)alloc, offset, lod, ptr, sizeBytes, compIdx);
     _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
 }
 
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index d1af1a3..0ef8469 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -55,6 +55,16 @@
 
     glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
 
+    if (extensions.hasDebugMarker()) {
+        eventMark = glInsertEventMarkerEXT;
+        startMark = glPushGroupMarkerEXT;
+        endMark = glPopGroupMarkerEXT;
+    } else {
+        eventMark = eventMarkNull;
+        startMark = startMarkNull;
+        endMark = endMarkNull;
+    }
+
     init();
 
     mDebugLevel = readDebugLevel();
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index 409584f..f8c7bcc 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -240,7 +240,15 @@
     GammaFontRenderer fontRenderer;
     ResourceCache resourceCache;
 
+    PFNGLINSERTEVENTMARKEREXTPROC eventMark;
+    PFNGLPUSHGROUPMARKEREXTPROC startMark;
+    PFNGLPOPGROUPMARKEREXTPROC endMark;
+
 private:
+    static void eventMarkNull(GLsizei length, const GLchar *marker) { }
+    static void startMarkNull(GLsizei length, const GLchar *marker) { }
+    static void endMarkNull() { }
+
     GLuint mCurrentBuffer;
     GLuint mCurrentIndicesBuffer;
     void* mCurrentPositionPointer;
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index ee935e4..1a11fbc 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -19,9 +19,10 @@
 
 #include "DisplayListLogBuffer.h"
 #include "DisplayListRenderer.h"
-#include <utils/String8.h>
 #include "Caches.h"
 
+#include <utils/String8.h>
+
 namespace android {
 namespace uirenderer {
 
@@ -217,7 +218,7 @@
         indent[i] = ' ';
     }
     indent[count] = '\0';
-    ALOGD("%sStart display list (%p)", (char*) indent + 2, this);
+    ALOGD("%sStart display list (%p, %s)", (char*) indent + 2, this, mName.string());
 
     int saveCount = renderer.getSaveCount() - 1;
 
@@ -562,9 +563,11 @@
         indent[i] = ' ';
     }
     indent[count] = '\0';
-    DISPLAY_LIST_LOGD("%sStart display list (%p)", (char*) indent + 2, this);
+    DISPLAY_LIST_LOGD("%sStart display list (%p, %s)", (char*) indent + 2, this, mName.string());
 #endif
 
+    renderer.startMark(mName.string());
+
     DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance();
     int saveCount = renderer.getSaveCount() - 1;
     while (!mReader.eof()) {
@@ -575,7 +578,9 @@
             case DrawGLFunction: {
                 Functor *functor = (Functor *) getInt();
                 DISPLAY_LIST_LOGD("%s%s %p", (char*) indent, OP_NAMES[op], functor);
+                renderer.startMark("GL functor");
                 needsInvalidate |= renderer.callDrawGLFunction(functor, dirty);
+                renderer.endMark();
             }
             break;
             case Save: {
@@ -934,6 +939,8 @@
         }
     }
 
+    renderer.endMark();
+
     DISPLAY_LIST_LOGD("%sDone, returning %d", (char*) indent + 2, needsInvalidate);
     return needsInvalidate;
 }
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 6fe4205..46506e4 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -28,6 +28,8 @@
 
 #include <cutils/compiler.h>
 
+#include <utils/String8.h>
+
 #include "DisplayListLogBuffer.h"
 #include "OpenGLRenderer.h"
 #include "utils/Functor.h"
@@ -128,6 +130,12 @@
         return mIsRenderable;
     }
 
+    void setName(const char* name) {
+        if (name) {
+            mName.setTo(name);
+        }
+    }
+
 private:
     void init();
 
@@ -224,6 +232,8 @@
     size_t mSize;
 
     bool mIsRenderable;
+
+    String8 mName;
 };
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/Extensions.h b/libs/hwui/Extensions.h
index 1069e3f..f11fecc 100644
--- a/libs/hwui/Extensions.h
+++ b/libs/hwui/Extensions.h
@@ -67,6 +67,7 @@
         mHasNPot = hasExtension("GL_OES_texture_npot");
         mHasFramebufferFetch = hasExtension("GL_NV_shader_framebuffer_fetch");
         mHasDiscardFramebuffer = hasExtension("GL_EXT_discard_framebuffer");
+        mHasDebugMarker = hasExtension("GL_EXT_debug_marker");
 
         const char* vendor = (const char*) glGetString(GL_VENDOR);
         EXT_LOGD("Vendor: %s", vendor);
@@ -82,6 +83,7 @@
     inline bool hasFramebufferFetch() const { return mHasFramebufferFetch; }
     inline bool needsHighpTexCoords() const { return mNeedsHighpTexCoords; }
     inline bool hasDiscardFramebuffer() const { return mHasDiscardFramebuffer; }
+    inline bool hasDebugMarker() const { return mHasDebugMarker; }
 
     bool hasExtension(const char* extension) const {
         const String8 s(extension);
@@ -101,6 +103,7 @@
     bool mNeedsHighpTexCoords;
     bool mHasFramebufferFetch;
     bool mHasDiscardFramebuffer;
+    bool mHasDebugMarker;
 }; // class Extensions
 
 }; // namespace uirenderer
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index cc0e05e..bd213d5 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -124,9 +124,25 @@
 }
 
 ///////////////////////////////////////////////////////////////////////////////
+// Debug
+///////////////////////////////////////////////////////////////////////////////
+
+void OpenGLRenderer::startMark(const char* name) const {
+    mCaches.startMark(0, name);
+}
+
+void OpenGLRenderer::endMark() const {
+    mCaches.endMark();
+}
+
+///////////////////////////////////////////////////////////////////////////////
 // Setup
 ///////////////////////////////////////////////////////////////////////////////
 
+uint32_t OpenGLRenderer::getStencilSize() {
+    return STENCIL_BUFFER_SIZE;
+}
+
 void OpenGLRenderer::setViewport(int width, int height) {
     mOrthoMatrix.loadOrtho(0, width, height, 0, -1, 1);
 
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index ae355bb..3c2d09e 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -141,6 +141,11 @@
 
     SkPaint* filterPaint(SkPaint* paint);
 
+    ANDROID_API static uint32_t getStencilSize();
+
+    void startMark(const char* name) const;
+    void endMark() const;
+
 protected:
     /**
      * Compose the layer defined in the current snapshot with the layer
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index 2eae0f1..71fb8da 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -37,6 +37,11 @@
 // Textures used by layers must have dimensions multiples of this number
 #define LAYER_SIZE 64
 
+// Defines the size in bits of the stencil buffer
+// Note: We only want 1 bit, but in practice we'll get 8 bits on all GPUs
+//       for the foreseeable future
+#define STENCIL_BUFFER_SIZE 0
+
 /**
  * Debug level for app developers.
  */
diff --git a/libs/rs/rs.spec b/libs/rs/rs.spec
index 20b1f52..6887b22 100644
--- a/libs/rs/rs.spec
+++ b/libs/rs/rs.spec
@@ -162,7 +162,7 @@
 	param uint32_t x
 	param uint32_t lod
 	param const void *data
-	param uint32_t comp_offset
+	param size_t comp_offset
 	}
 
 Allocation2DData {
@@ -183,7 +183,7 @@
 	param uint32_t lod
 	param RsAllocationCubemapFace face
 	param const void *data
-	param uint32_t element_offset
+	param size_t element_offset
 	}
 
 AllocationGenerateMipmaps {
diff --git a/libs/rs/rsAllocation.cpp b/libs/rs/rsAllocation.cpp
index 2773d5c..972e3d6 100644
--- a/libs/rs/rsAllocation.cpp
+++ b/libs/rs/rsAllocation.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 The Android Open Source Project
+ * Copyright (C) 2009-2012 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.
@@ -71,11 +71,11 @@
 }
 
 void Allocation::data(Context *rsc, uint32_t xoff, uint32_t lod,
-                         uint32_t count, const void *data, uint32_t sizeBytes) {
-    const uint32_t eSize = mHal.state.type->getElementSizeBytes();
+                         uint32_t count, const void *data, size_t sizeBytes) {
+    const size_t eSize = mHal.state.type->getElementSizeBytes();
 
     if ((count * eSize) != sizeBytes) {
-        ALOGE("Allocation::subData called with mismatched size expected %i, got %i",
+        ALOGE("Allocation::subData called with mismatched size expected %zu, got %zu",
              (count * eSize), sizeBytes);
         mHal.state.type->dumpLOGV("type info");
         return;
@@ -86,14 +86,14 @@
 }
 
 void Allocation::data(Context *rsc, uint32_t xoff, uint32_t yoff, uint32_t lod, RsAllocationCubemapFace face,
-             uint32_t w, uint32_t h, const void *data, uint32_t sizeBytes) {
-    const uint32_t eSize = mHal.state.elementSizeBytes;
-    const uint32_t lineSize = eSize * w;
+             uint32_t w, uint32_t h, const void *data, size_t sizeBytes) {
+    const size_t eSize = mHal.state.elementSizeBytes;
+    const size_t lineSize = eSize * w;
 
     //ALOGE("data2d %p,  %i %i %i %i %i %i %p %i", this, xoff, yoff, lod, face, w, h, data, sizeBytes);
 
     if ((lineSize * h) != sizeBytes) {
-        ALOGE("Allocation size mismatch, expected %i, got %i", (lineSize * h), sizeBytes);
+        ALOGE("Allocation size mismatch, expected %zu, got %zu", (lineSize * h), sizeBytes);
         rsAssert(!"Allocation::subData called with mismatched size");
         return;
     }
@@ -104,12 +104,12 @@
 
 void Allocation::data(Context *rsc, uint32_t xoff, uint32_t yoff, uint32_t zoff,
                       uint32_t lod, RsAllocationCubemapFace face,
-                      uint32_t w, uint32_t h, uint32_t d, const void *data, uint32_t sizeBytes) {
+                      uint32_t w, uint32_t h, uint32_t d, const void *data, size_t sizeBytes) {
 }
 
 void Allocation::elementData(Context *rsc, uint32_t x, const void *data,
-                                uint32_t cIdx, uint32_t sizeBytes) {
-    uint32_t eSize = mHal.state.elementSizeBytes;
+                                uint32_t cIdx, size_t sizeBytes) {
+    size_t eSize = mHal.state.elementSizeBytes;
 
     if (cIdx >= mHal.state.type->getElement()->getFieldCount()) {
         ALOGE("Error Allocation::subElementData component %i out of range.", cIdx);
@@ -125,7 +125,7 @@
 
     const Element * e = mHal.state.type->getElement()->getField(cIdx);
     if (sizeBytes != e->getSizeBytes()) {
-        ALOGE("Error Allocation::subElementData data size %i does not match field size %zu.", sizeBytes, e->getSizeBytes());
+        ALOGE("Error Allocation::subElementData data size %zu does not match field size %zu.", sizeBytes, e->getSizeBytes());
         rsc->setError(RS_ERROR_BAD_VALUE, "subElementData bad size.");
         return;
     }
@@ -135,8 +135,8 @@
 }
 
 void Allocation::elementData(Context *rsc, uint32_t x, uint32_t y,
-                                const void *data, uint32_t cIdx, uint32_t sizeBytes) {
-    uint32_t eSize = mHal.state.elementSizeBytes;
+                                const void *data, uint32_t cIdx, size_t sizeBytes) {
+    size_t eSize = mHal.state.elementSizeBytes;
 
     if (x >= mHal.state.dimensionX) {
         ALOGE("Error Allocation::subElementData X offset %i out of range.", x);
@@ -159,7 +159,7 @@
     const Element * e = mHal.state.type->getElement()->getField(cIdx);
 
     if (sizeBytes != e->getSizeBytes()) {
-        ALOGE("Error Allocation::subElementData data size %i does not match field size %zu.", sizeBytes, e->getSizeBytes());
+        ALOGE("Error Allocation::subElementData data size %zu does not match field size %zu.", sizeBytes, e->getSizeBytes());
         rsc->setError(RS_ERROR_BAD_VALUE, "subElementData bad size.");
         return;
     }
@@ -249,7 +249,7 @@
     delete[] sizeUnpadded;
 }
 
-void Allocation::unpackVec3Allocation(const void *data, uint32_t dataSize) {
+void Allocation::unpackVec3Allocation(const void *data, size_t dataSize) {
     const uint8_t *src = (const uint8_t*)data;
     uint8_t *dst = (uint8_t*)getPtr();
 
@@ -519,13 +519,13 @@
 }
 
 void rsi_Allocation2DElementData(Context *rsc, RsAllocation va, uint32_t x, uint32_t y, uint32_t lod, RsAllocationCubemapFace face,
-                                 const void *data, size_t eoff, uint32_t sizeBytes) { // TODO: this seems wrong, eoff and sizeBytes may be swapped
+                                 const void *data, size_t sizeBytes, size_t eoff) {
     Allocation *a = static_cast<Allocation *>(va);
     a->elementData(rsc, x, y, data, eoff, sizeBytes);
 }
 
 void rsi_Allocation1DElementData(Context *rsc, RsAllocation va, uint32_t x, uint32_t lod,
-                                 const void *data, size_t eoff, uint32_t sizeBytes) { // TODO: this seems wrong, eoff and sizeBytes may be swapped
+                                 const void *data, size_t sizeBytes, size_t eoff) {
     Allocation *a = static_cast<Allocation *>(va);
     a->elementData(rsc, x, data, eoff, sizeBytes);
 }
diff --git a/libs/rs/rsAllocation.h b/libs/rs/rsAllocation.h
index 4ce863a..20201ca 100644
--- a/libs/rs/rsAllocation.h
+++ b/libs/rs/rsAllocation.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 The Android Open Source Project
+ * Copyright (C) 2009-2012 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.
@@ -80,16 +80,16 @@
     void resize1D(Context *rsc, uint32_t dimX);
     void resize2D(Context *rsc, uint32_t dimX, uint32_t dimY);
 
-    void data(Context *rsc, uint32_t xoff, uint32_t lod, uint32_t count, const void *data, uint32_t sizeBytes);
+    void data(Context *rsc, uint32_t xoff, uint32_t lod, uint32_t count, const void *data, size_t sizeBytes);
     void data(Context *rsc, uint32_t xoff, uint32_t yoff, uint32_t lod, RsAllocationCubemapFace face,
-                 uint32_t w, uint32_t h, const void *data, uint32_t sizeBytes);
+                 uint32_t w, uint32_t h, const void *data, size_t sizeBytes);
     void data(Context *rsc, uint32_t xoff, uint32_t yoff, uint32_t zoff, uint32_t lod, RsAllocationCubemapFace face,
-                 uint32_t w, uint32_t h, uint32_t d, const void *data, uint32_t sizeBytes);
+                 uint32_t w, uint32_t h, uint32_t d, const void *data, size_t sizeBytes);
 
     void elementData(Context *rsc, uint32_t x,
-                        const void *data, uint32_t elementOff, uint32_t sizeBytes);
+                     const void *data, uint32_t elementOff, size_t sizeBytes);
     void elementData(Context *rsc, uint32_t x, uint32_t y,
-                        const void *data, uint32_t elementOff, uint32_t sizeBytes);
+                     const void *data, uint32_t elementOff, size_t sizeBytes);
 
     void read(void *data);
 
@@ -138,7 +138,7 @@
 
     uint32_t getPackedSize() const;
     static void writePackedData(const Type *type, uint8_t *dst, const uint8_t *src, bool dstPadded);
-    void unpackVec3Allocation(const void *data, uint32_t dataSize);
+    void unpackVec3Allocation(const void *data, size_t dataSize);
     void packVec3Allocation(OStream *stream) const;
 };
 
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 4d61067..a452ad5 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -74,6 +74,7 @@
         libcrypto        \
         libssl           \
         libgui           \
+        libstagefright_omx \
 
 LOCAL_STATIC_LIBRARIES := \
         libstagefright_color_conversion \
diff --git a/media/libstagefright/OMXClient.cpp b/media/libstagefright/OMXClient.cpp
index 9de873e..391add5 100644
--- a/media/libstagefright/OMXClient.cpp
+++ b/media/libstagefright/OMXClient.cpp
@@ -20,11 +20,299 @@
 
 #include <binder/IServiceManager.h>
 #include <media/IMediaPlayerService.h>
-#include <media/stagefright/MediaDebug.h>
+#include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/OMXClient.h>
+#include <utils/KeyedVector.h>
+
+#include "include/OMX.h"
 
 namespace android {
 
+struct MuxOMX : public IOMX {
+    MuxOMX(const sp<IOMX> &remoteOMX);
+    virtual ~MuxOMX();
+
+    virtual IBinder *onAsBinder() { return NULL; }
+
+    virtual bool livesLocally(pid_t pid);
+
+    virtual status_t listNodes(List<ComponentInfo> *list);
+
+    virtual status_t allocateNode(
+            const char *name, const sp<IOMXObserver> &observer,
+            node_id *node);
+
+    virtual status_t freeNode(node_id node);
+
+    virtual status_t sendCommand(
+            node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param);
+
+    virtual status_t getParameter(
+            node_id node, OMX_INDEXTYPE index,
+            void *params, size_t size);
+
+    virtual status_t setParameter(
+            node_id node, OMX_INDEXTYPE index,
+            const void *params, size_t size);
+
+    virtual status_t getConfig(
+            node_id node, OMX_INDEXTYPE index,
+            void *params, size_t size);
+
+    virtual status_t setConfig(
+            node_id node, OMX_INDEXTYPE index,
+            const void *params, size_t size);
+
+    virtual status_t getState(
+            node_id node, OMX_STATETYPE* state);
+
+    virtual status_t storeMetaDataInBuffers(
+            node_id node, OMX_U32 port_index, OMX_BOOL enable);
+
+    virtual status_t enableGraphicBuffers(
+            node_id node, OMX_U32 port_index, OMX_BOOL enable);
+
+    virtual status_t getGraphicBufferUsage(
+            node_id node, OMX_U32 port_index, OMX_U32* usage);
+
+    virtual status_t useBuffer(
+            node_id node, OMX_U32 port_index, const sp<IMemory> &params,
+            buffer_id *buffer);
+
+    virtual status_t useGraphicBuffer(
+            node_id node, OMX_U32 port_index,
+            const sp<GraphicBuffer> &graphicBuffer, buffer_id *buffer);
+
+    virtual status_t allocateBuffer(
+            node_id node, OMX_U32 port_index, size_t size,
+            buffer_id *buffer, void **buffer_data);
+
+    virtual status_t allocateBufferWithBackup(
+            node_id node, OMX_U32 port_index, const sp<IMemory> &params,
+            buffer_id *buffer);
+
+    virtual status_t freeBuffer(
+            node_id node, OMX_U32 port_index, buffer_id buffer);
+
+    virtual status_t fillBuffer(node_id node, buffer_id buffer);
+
+    virtual status_t emptyBuffer(
+            node_id node,
+            buffer_id buffer,
+            OMX_U32 range_offset, OMX_U32 range_length,
+            OMX_U32 flags, OMX_TICKS timestamp);
+
+    virtual status_t getExtensionIndex(
+            node_id node,
+            const char *parameter_name,
+            OMX_INDEXTYPE *index);
+
+private:
+    mutable Mutex mLock;
+
+    sp<IOMX> mRemoteOMX;
+    sp<IOMX> mLocalOMX;
+
+    KeyedVector<node_id, bool> mIsLocalNode;
+
+    bool isLocalNode(node_id node) const;
+    bool isLocalNode_l(node_id node) const;
+    const sp<IOMX> &getOMX(node_id node) const;
+    const sp<IOMX> &getOMX_l(node_id node) const;
+
+    static bool IsSoftwareComponent(const char *name);
+
+    DISALLOW_EVIL_CONSTRUCTORS(MuxOMX);
+};
+
+MuxOMX::MuxOMX(const sp<IOMX> &remoteOMX)
+    : mRemoteOMX(remoteOMX) {
+}
+
+MuxOMX::~MuxOMX() {
+}
+
+bool MuxOMX::isLocalNode(node_id node) const {
+    Mutex::Autolock autoLock(mLock);
+
+    return isLocalNode_l(node);
+}
+
+bool MuxOMX::isLocalNode_l(node_id node) const {
+    return mIsLocalNode.indexOfKey(node) >= 0;
+}
+
+// static
+bool MuxOMX::IsSoftwareComponent(const char *name) {
+    return !strncasecmp(name, "OMX.google.", 11);
+}
+
+const sp<IOMX> &MuxOMX::getOMX(node_id node) const {
+    return isLocalNode(node) ? mLocalOMX : mRemoteOMX;
+}
+
+const sp<IOMX> &MuxOMX::getOMX_l(node_id node) const {
+    return isLocalNode_l(node) ? mLocalOMX : mRemoteOMX;
+}
+
+bool MuxOMX::livesLocally(pid_t pid) {
+    return true;
+}
+
+status_t MuxOMX::listNodes(List<ComponentInfo> *list) {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mLocalOMX == NULL) {
+        mLocalOMX = new OMX;
+    }
+
+    return mLocalOMX->listNodes(list);
+}
+
+status_t MuxOMX::allocateNode(
+        const char *name, const sp<IOMXObserver> &observer,
+        node_id *node) {
+    Mutex::Autolock autoLock(mLock);
+
+    sp<IOMX> omx;
+
+    if (IsSoftwareComponent(name)) {
+        if (mLocalOMX == NULL) {
+            mLocalOMX = new OMX;
+        }
+        omx = mLocalOMX;
+    } else {
+        omx = mRemoteOMX;
+    }
+
+    status_t err = omx->allocateNode(name, observer, node);
+
+    if (err != OK) {
+        return err;
+    }
+
+    if (omx == mLocalOMX) {
+        mIsLocalNode.add(*node, true);
+    }
+
+    return OK;
+}
+
+status_t MuxOMX::freeNode(node_id node) {
+    Mutex::Autolock autoLock(mLock);
+
+    status_t err = getOMX_l(node)->freeNode(node);
+
+    if (err != OK) {
+        return err;
+    }
+
+    mIsLocalNode.removeItem(node);
+
+    return OK;
+}
+
+status_t MuxOMX::sendCommand(
+        node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) {
+    return getOMX(node)->sendCommand(node, cmd, param);
+}
+
+status_t MuxOMX::getParameter(
+        node_id node, OMX_INDEXTYPE index,
+        void *params, size_t size) {
+    return getOMX(node)->getParameter(node, index, params, size);
+}
+
+status_t MuxOMX::setParameter(
+        node_id node, OMX_INDEXTYPE index,
+        const void *params, size_t size) {
+    return getOMX(node)->setParameter(node, index, params, size);
+}
+
+status_t MuxOMX::getConfig(
+        node_id node, OMX_INDEXTYPE index,
+        void *params, size_t size) {
+    return getOMX(node)->getConfig(node, index, params, size);
+}
+
+status_t MuxOMX::setConfig(
+        node_id node, OMX_INDEXTYPE index,
+        const void *params, size_t size) {
+    return getOMX(node)->setConfig(node, index, params, size);
+}
+
+status_t MuxOMX::getState(
+        node_id node, OMX_STATETYPE* state) {
+    return getOMX(node)->getState(node, state);
+}
+
+status_t MuxOMX::storeMetaDataInBuffers(
+        node_id node, OMX_U32 port_index, OMX_BOOL enable) {
+    return getOMX(node)->storeMetaDataInBuffers(node, port_index, enable);
+}
+
+status_t MuxOMX::enableGraphicBuffers(
+        node_id node, OMX_U32 port_index, OMX_BOOL enable) {
+    return getOMX(node)->enableGraphicBuffers(node, port_index, enable);
+}
+
+status_t MuxOMX::getGraphicBufferUsage(
+        node_id node, OMX_U32 port_index, OMX_U32* usage) {
+    return getOMX(node)->getGraphicBufferUsage(node, port_index, usage);
+}
+
+status_t MuxOMX::useBuffer(
+        node_id node, OMX_U32 port_index, const sp<IMemory> &params,
+        buffer_id *buffer) {
+    return getOMX(node)->useBuffer(node, port_index, params, buffer);
+}
+
+status_t MuxOMX::useGraphicBuffer(
+        node_id node, OMX_U32 port_index,
+        const sp<GraphicBuffer> &graphicBuffer, buffer_id *buffer) {
+    return getOMX(node)->useGraphicBuffer(
+            node, port_index, graphicBuffer, buffer);
+}
+
+status_t MuxOMX::allocateBuffer(
+        node_id node, OMX_U32 port_index, size_t size,
+        buffer_id *buffer, void **buffer_data) {
+    return getOMX(node)->allocateBuffer(
+            node, port_index, size, buffer, buffer_data);
+}
+
+status_t MuxOMX::allocateBufferWithBackup(
+        node_id node, OMX_U32 port_index, const sp<IMemory> &params,
+        buffer_id *buffer) {
+    return getOMX(node)->allocateBufferWithBackup(
+            node, port_index, params, buffer);
+}
+
+status_t MuxOMX::freeBuffer(
+        node_id node, OMX_U32 port_index, buffer_id buffer) {
+    return getOMX(node)->freeBuffer(node, port_index, buffer);
+}
+
+status_t MuxOMX::fillBuffer(node_id node, buffer_id buffer) {
+    return getOMX(node)->fillBuffer(node, buffer);
+}
+
+status_t MuxOMX::emptyBuffer(
+        node_id node,
+        buffer_id buffer,
+        OMX_U32 range_offset, OMX_U32 range_length,
+        OMX_U32 flags, OMX_TICKS timestamp) {
+    return getOMX(node)->emptyBuffer(
+            node, buffer, range_offset, range_length, flags, timestamp);
+}
+
+status_t MuxOMX::getExtensionIndex(
+        node_id node,
+        const char *parameter_name,
+        OMX_INDEXTYPE *index) {
+    return getOMX(node)->getExtensionIndex(node, parameter_name, index);
+}
+
 OMXClient::OMXClient() {
 }
 
@@ -38,6 +326,11 @@
     mOMX = service->getOMX();
     CHECK(mOMX.get() != NULL);
 
+    if (!mOMX->livesLocally(getpid())) {
+        ALOGI("Using client-side OMX mux.");
+        mOMX = new MuxOMX(mOMX);
+    }
+
     return OK;
 }
 
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index 2fc6125..06be2ef 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -253,6 +253,19 @@
         if (f == NULL) {
             //ALOGD("%s", name);
             f = (__eglMustCastToProperFunctionPointerType)gl_unimplemented;
+
+            /*
+             * GL_EXT_debug_label is special, we always report it as
+             * supported, it's handled by GLES_trace. If GLES_trace is not
+             * enabled, then these are no-ops.
+             */
+            if (!strcmp(name, "glInsertEventMarkerEXT")) {
+                f = (__eglMustCastToProperFunctionPointerType)gl_noop;
+            } else if (!strcmp(name, "glPushGroupMarkerEXT")) {
+                f = (__eglMustCastToProperFunctionPointerType)gl_noop;
+            } else if (!strcmp(name, "glPopGroupMarkerEXT")) {
+                f = (__eglMustCastToProperFunctionPointerType)gl_noop;
+            }
         }
         *curr++ = f;
         api++;
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index e053589..83933e5 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -233,6 +233,26 @@
 
 // ----------------------------------------------------------------------------
 
+const GLubyte * egl_get_string_for_current_context(GLenum name) {
+    // NOTE: returning NULL here will fall-back to the default
+    // implementation.
+
+    EGLContext context = egl_tls_t::getContext();
+    if (context == EGL_NO_CONTEXT)
+        return NULL;
+
+    egl_context_t const * const c = get_context(context);
+    if (c == NULL) // this should never happen, by construction
+        return NULL;
+
+    if (name != GL_EXTENSIONS)
+        return NULL;
+
+    return (const GLubyte *)c->gl_extensions.string();
+}
+
+// ----------------------------------------------------------------------------
+
 // this mutex protects:
 //    d->disp[]
 //    egl_init_drivers_locked()
@@ -290,6 +310,9 @@
     ALOGE("called unimplemented OpenGL ES API");
 }
 
+void gl_noop() {
+}
+
 // ----------------------------------------------------------------------------
 
 #if USE_FAST_TLS_KEY
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 8b37da5..9379c53 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -578,8 +578,7 @@
         SurfaceRef _cur_r(cur_r);
         SurfaceRef _cur_d(cur_d);
 
-        cur_c->read = NULL;
-        cur_c->draw = NULL;
+        cur_c->onLooseCurrent();
 
         _cur_c.release();
         _cur_r.release();
@@ -687,8 +686,7 @@
             _c.acquire();
             _r.acquire();
             _d.acquire();
-            c->read = read;
-            c->draw = draw;
+            c->onMakeCurrent(draw, read);
         } else {
             setGLHooksThreadSpecific(&gHooksNoContext);
             egl_tls_t::setContext(EGL_NO_CONTEXT);
@@ -924,7 +922,8 @@
                     cnx->hooks[GLESv1_INDEX]->ext.extensions[slot] =
                     cnx->hooks[GLESv2_INDEX]->ext.extensions[slot] =
 #if EGL_TRACE
-                    debugHooks->ext.extensions[slot] = gHooksTrace.ext.extensions[slot] =
+                    debugHooks->ext.extensions[slot] =
+                    gHooksTrace.ext.extensions[slot] =
 #endif
                             cnx->egl.eglGetProcAddress(procname);
                 }
diff --git a/opengl/libs/EGL/egl_object.cpp b/opengl/libs/EGL/egl_object.cpp
index 26e8c3e..b660c53 100644
--- a/opengl/libs/EGL/egl_object.cpp
+++ b/opengl/libs/EGL/egl_object.cpp
@@ -62,5 +62,41 @@
 }
 
 // ----------------------------------------------------------------------------
+
+egl_context_t::egl_context_t(EGLDisplay dpy, EGLContext context, EGLConfig config,
+        int impl, egl_connection_t const* cnx, int version) :
+    egl_object_t(get_display(dpy)), dpy(dpy), context(context),
+            config(config), read(0), draw(0), impl(impl), cnx(cnx),
+            version(version)
+{
+}
+
+void egl_context_t::onLooseCurrent() {
+    read = NULL;
+    draw = NULL;
+}
+
+void egl_context_t::onMakeCurrent(EGLSurface draw, EGLSurface read) {
+    this->read = read;
+    this->draw = draw;
+
+    /*
+     * Here we cache the GL_EXTENSIONS string for this context and we
+     * add the extensions always handled by the wrapper
+     */
+
+    if (gl_extensions.isEmpty()) {
+        // call the implementation's glGetString(GL_EXTENSIONS)
+        const char* exts = (const char *)gEGLImpl[impl].hooks[version]->gl.glGetString(GL_EXTENSIONS);
+        gl_extensions.setTo(exts);
+        if (gl_extensions.find("GL_EXT_debug_marker") < 0) {
+            String8 temp("GL_EXT_debug_marker ");
+            temp.append(gl_extensions);
+            gl_extensions.setTo(temp);
+        }
+    }
+}
+
+// ----------------------------------------------------------------------------
 }; // namespace android
 // ----------------------------------------------------------------------------
diff --git a/opengl/libs/EGL/egl_object.h b/opengl/libs/EGL/egl_object.h
index 7106fa5..abd4cbb 100644
--- a/opengl/libs/EGL/egl_object.h
+++ b/opengl/libs/EGL/egl_object.h
@@ -28,6 +28,7 @@
 #include <GLES/glext.h>
 
 #include <utils/threads.h>
+#include <utils/String8.h>
 
 #include <system/window.h>
 
@@ -158,11 +159,11 @@
     typedef egl_object_t::LocalRef<egl_context_t, EGLContext> Ref;
 
     egl_context_t(EGLDisplay dpy, EGLContext context, EGLConfig config,
-            int impl, egl_connection_t const* cnx, int version) :
-        egl_object_t(get_display(dpy)), dpy(dpy), context(context),
-                config(config), read(0), draw(0), impl(impl), cnx(cnx),
-                version(version) {
-    }
+            int impl, egl_connection_t const* cnx, int version);
+
+    void onLooseCurrent();
+    void onMakeCurrent(EGLSurface draw, EGLSurface read);
+
     EGLDisplay dpy;
     EGLContext context;
     EGLConfig config;
@@ -171,6 +172,7 @@
     int impl;
     egl_connection_t const* cnx;
     int version;
+    String8 gl_extensions;
 };
 
 class egl_image_t: public egl_object_t {
diff --git a/opengl/libs/EGL/egldefs.h b/opengl/libs/EGL/egldefs.h
index 107acd9..ff20957 100644
--- a/opengl/libs/EGL/egldefs.h
+++ b/opengl/libs/EGL/egldefs.h
@@ -58,6 +58,7 @@
 extern gl_hooks_t gHooksNoContext;
 extern pthread_key_t gGLWrapperKey;
 extern "C" void gl_unimplemented();
+extern "C" void gl_noop();
 
 extern char const * const gl_names[];
 extern char const * const egl_names[];
diff --git a/opengl/libs/GLES2/gl2.cpp b/opengl/libs/GLES2/gl2.cpp
index df22b96..79aa3cd 100644
--- a/opengl/libs/GLES2/gl2.cpp
+++ b/opengl/libs/GLES2/gl2.cpp
@@ -110,6 +110,20 @@
 #undef CALL_GL_API
 #undef CALL_GL_API_RETURN
 
+/*
+ * glGetString() is special because we expose some extensions in the wrapper
+ */
+
+extern "C" const GLubyte * __glGetString(GLenum name);
+
+const GLubyte * glGetString(GLenum name)
+{
+    const GLubyte * ret = egl_get_string_for_current_context(name);
+    if (ret == NULL) {
+        ret = __glGetString(name);
+    }
+    return ret;
+}
 
 /*
  * These GL calls are special because they need to EGL to retrieve some
diff --git a/opengl/libs/GLES2/gl2_api.in b/opengl/libs/GLES2/gl2_api.in
index 5164450..9a89a52 100644
--- a/opengl/libs/GLES2/gl2_api.in
+++ b/opengl/libs/GLES2/gl2_api.in
@@ -211,7 +211,7 @@
 void API_ENTRY(glGetShaderSource)(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source) {
     CALL_GL_API(glGetShaderSource, shader, bufsize, length, source);
 }
-const GLubyte* API_ENTRY(glGetString)(GLenum name) {
+const GLubyte* API_ENTRY(__glGetString)(GLenum name) {
     CALL_GL_API_RETURN(glGetString, name);
 }
 void API_ENTRY(glGetTexParameterfv)(GLenum target, GLenum pname, GLfloat* params) {
diff --git a/opengl/libs/GLES_CM/gl.cpp b/opengl/libs/GLES_CM/gl.cpp
index 2d31a35..adeaa5b 100644
--- a/opengl/libs/GLES_CM/gl.cpp
+++ b/opengl/libs/GLES_CM/gl.cpp
@@ -165,6 +165,20 @@
 #undef CALL_GL_API
 #undef CALL_GL_API_RETURN
 
+/*
+ * glGetString() is special because we expose some extensions in the wrapper
+ */
+
+extern "C" const GLubyte * __glGetString(GLenum name);
+
+const GLubyte * glGetString(GLenum name)
+{
+    const GLubyte * ret = egl_get_string_for_current_context(name);
+    if (ret == NULL) {
+        ret = __glGetString(name);
+    }
+    return ret;
+}
 
 /*
  * These GL calls are special because they need to EGL to retrieve some
diff --git a/opengl/libs/GLES_CM/gl_api.in b/opengl/libs/GLES_CM/gl_api.in
index 7f20c4f..c8f6b0c 100644
--- a/opengl/libs/GLES_CM/gl_api.in
+++ b/opengl/libs/GLES_CM/gl_api.in
@@ -262,7 +262,7 @@
 void API_ENTRY(glGetPointerv)(GLenum pname, GLvoid **params) {
     CALL_GL_API(glGetPointerv, pname, params);
 }
-const GLubyte * API_ENTRY(glGetString)(GLenum name) {
+const GLubyte * API_ENTRY(__glGetString)(GLenum name) {
     CALL_GL_API_RETURN(glGetString, name);
 }
 void API_ENTRY(glGetTexEnviv)(GLenum env, GLenum pname, GLint *params) {
diff --git a/opengl/libs/egl_impl.h b/opengl/libs/egl_impl.h
index a809316..8ff51ec 100644
--- a/opengl/libs/egl_impl.h
+++ b/opengl/libs/egl_impl.h
@@ -29,6 +29,7 @@
 namespace android {
 // ----------------------------------------------------------------------------
 
+EGLAPI const GLubyte * egl_get_string_for_current_context(GLenum name);
 EGLAPI EGLImageKHR egl_get_image_for_current_context(EGLImageKHR image);
 
 // ----------------------------------------------------------------------------
diff --git a/opengl/libs/tools/glapigen b/opengl/libs/tools/glapigen
index bd8dda3..9be40cf 100755
--- a/opengl/libs/tools/glapigen
+++ b/opengl/libs/tools/glapigen
@@ -43,6 +43,9 @@
   if ($name eq "glEGLImageTargetRenderbufferStorageOES") {
     $prefix = "__";
   }
+  if ($name eq "glGetString") {
+    $prefix = "__";
+  }
   
   printf("%s API_ENTRY(%s%s)(%s)", $type, $prefix, $name, $args);
   
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index d46ab6c..d0f72a4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -850,8 +850,10 @@
             Slog.d(TAG, "updateConnectivity: intent=" + intent);
         }
 
-        NetworkInfo info = (NetworkInfo)(intent.getParcelableExtra(
-                ConnectivityManager.EXTRA_NETWORK_INFO));
+        final ConnectivityManager connManager = (ConnectivityManager) mContext
+                .getSystemService(Context.CONNECTIVITY_SERVICE);
+        final NetworkInfo info = connManager.getActiveNetworkInfo();
+
         int connectionStatus = intent.getIntExtra(ConnectivityManager.EXTRA_INET_CONDITION, 0);
 
         if (CHATTY) {
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index 56afe7f..8cb9d99b 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -1962,8 +1962,10 @@
                 } else {
                     mNetworkState = LocationProvider.TEMPORARILY_UNAVAILABLE;
                 }
-                NetworkInfo info =
-                    (NetworkInfo)intent.getExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
+
+                final ConnectivityManager connManager = (ConnectivityManager) context
+                        .getSystemService(Context.CONNECTIVITY_SERVICE);
+                final NetworkInfo info = connManager.getActiveNetworkInfo();
 
                 // Notify location providers of current network state
                 synchronized (mLock) {
diff --git a/services/java/com/android/server/NetworkTimeUpdateService.java b/services/java/com/android/server/NetworkTimeUpdateService.java
index f7fe39e..a7d1992 100644
--- a/services/java/com/android/server/NetworkTimeUpdateService.java
+++ b/services/java/com/android/server/NetworkTimeUpdateService.java
@@ -234,8 +234,9 @@
             String action = intent.getAction();
             if (ConnectivityManager.CONNECTIVITY_ACTION.equals(action)) {
                 // There is connectivity
-                NetworkInfo netInfo = (NetworkInfo)intent.getParcelableExtra(
-                        ConnectivityManager.EXTRA_NETWORK_INFO);
+                final ConnectivityManager connManager = (ConnectivityManager) context
+                        .getSystemService(Context.CONNECTIVITY_SERVICE);
+                final NetworkInfo netInfo = connManager.getActiveNetworkInfo();
                 if (netInfo != null) {
                     // Verify that it's a WIFI connection
                     if (netInfo.getState() == NetworkInfo.State.CONNECTED &&
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 95d651a..732af53 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -23,18 +23,22 @@
 LOCAL_CFLAGS:= -DLOG_TAG=\"SurfaceFlinger\"
 LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
 
+ifeq ($(TARGET_HAS_WAITFORVSYNC), true)
+	LOCAL_CFLAGS += -DHAS_WAITFORVSYNC
+endif
+
 ifeq ($(TARGET_BOARD_PLATFORM), omap3)
 	LOCAL_CFLAGS += -DNO_RGBX_8888
 endif
 ifeq ($(TARGET_BOARD_PLATFORM), omap4)
 	LOCAL_CFLAGS += -DHAS_CONTEXT_PRIORITY
+	LOCAL_CFLAGS += -DUSE_TRIPLE_BUFFERING=1
 endif
 ifeq ($(TARGET_BOARD_PLATFORM), s5pc110)
 	LOCAL_CFLAGS += -DHAS_CONTEXT_PRIORITY -DNEVER_DEFAULT_TO_ASYNC_MODE
 	LOCAL_CFLAGS += -DREFRESH_RATE=56
 endif
 
-
 LOCAL_SHARED_LIBRARIES := \
 	libcutils \
 	libhardware \
diff --git a/services/surfaceflinger/EventThread.cpp b/services/surfaceflinger/EventThread.cpp
index 6796d7d..92d4266 100644
--- a/services/surfaceflinger/EventThread.cpp
+++ b/services/surfaceflinger/EventThread.cpp
@@ -36,6 +36,7 @@
 EventThread::EventThread(const sp<SurfaceFlinger>& flinger)
     : mFlinger(flinger),
       mHw(flinger->graphicPlane(0).displayHardware()),
+      mLastVSyncTimestamp(0),
       mDeliveredEvents(0)
 {
 }
@@ -44,6 +45,20 @@
     run("EventThread", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
 }
 
+sp<DisplayEventConnection> EventThread::createEventConnection() const {
+    return new DisplayEventConnection(const_cast<EventThread*>(this));
+}
+
+nsecs_t EventThread::getLastVSyncTimestamp() const {
+    Mutex::Autolock _l(mLock);
+    return mLastVSyncTimestamp;
+}
+
+nsecs_t EventThread::getVSyncPeriod() const {
+    return mHw.getRefreshPeriod();
+
+}
+
 status_t EventThread::registerDisplayEventConnection(
         const sp<DisplayEventConnection>& connection) {
     Mutex::Autolock _l(mLock);
@@ -80,8 +95,11 @@
         Mutex::Autolock _l(mLock);
         ConnectionInfo* info = getConnectionInfoLocked(connection);
         if (info) {
-            info->count = (count == 0) ? -1 : count;
-            mCondition.signal();
+            const int32_t new_count = (count == 0) ? -1 : count;
+            if (info->count != new_count) {
+                info->count = new_count;
+                mCondition.signal();
+            }
         }
     }
 }
@@ -90,10 +108,8 @@
         const wp<DisplayEventConnection>& connection) {
     Mutex::Autolock _l(mLock);
     ConnectionInfo* info = getConnectionInfoLocked(connection);
-    if (info) {
-        if (info->count < 0) {
-            info->count = 0;
-        }
+    if (info && info->count < 0) {
+        info->count = 0;
         mCondition.signal();
     }
 }
@@ -132,6 +148,7 @@
             timestamp = mHw.waitForRefresh();
             mLock.lock();
             mDeliveredEvents++;
+            mLastVSyncTimestamp = timestamp;
 
             // now see if we still need to report this VSYNC event
             bool reportVsync = false;
diff --git a/services/surfaceflinger/EventThread.h b/services/surfaceflinger/EventThread.h
index 35bd299..3a3071e 100644
--- a/services/surfaceflinger/EventThread.h
+++ b/services/surfaceflinger/EventThread.h
@@ -36,6 +36,7 @@
 
 class SurfaceFlinger;
 class DisplayHardware;
+class DisplayEventConnection;
 
 // ---------------------------------------------------------------------------
 
@@ -45,6 +46,8 @@
 public:
     EventThread(const sp<SurfaceFlinger>& flinger);
 
+    sp<DisplayEventConnection> createEventConnection() const;
+
     status_t registerDisplayEventConnection(
             const sp<DisplayEventConnection>& connection);
 
@@ -56,6 +59,10 @@
 
     void requestNextVsync(const wp<DisplayEventConnection>& connection);
 
+    nsecs_t getLastVSyncTimestamp() const;
+
+    nsecs_t getVSyncPeriod() const;
+
     void dump(String8& result, char* buffer, size_t SIZE) const;
 
 private:
@@ -88,6 +95,7 @@
 
     // protected by mLock
     KeyedVector< wp<DisplayEventConnection>, ConnectionInfo > mDisplayEventConnections;
+    nsecs_t mLastVSyncTimestamp;
 
     // main thread only
     size_t mDeliveredEvents;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 8e87b88..9c04d59 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -97,7 +97,12 @@
     mSurfaceTexture = new SurfaceTextureLayer(mTextureName, this);
     mSurfaceTexture->setFrameAvailableListener(new FrameQueuedListener(this));
     mSurfaceTexture->setSynchronousMode(true);
+#ifdef USE_TRIPLE_BUFFERING
+#warning "using triple buffering"
+    mSurfaceTexture->setBufferCountServer(3);
+#else
     mSurfaceTexture->setBufferCountServer(2);
+#endif
 }
 
 Layer::~Layer()
diff --git a/services/surfaceflinger/MessageQueue.cpp b/services/surfaceflinger/MessageQueue.cpp
index cbd530c..70711e7 100644
--- a/services/surfaceflinger/MessageQueue.cpp
+++ b/services/surfaceflinger/MessageQueue.cpp
@@ -18,12 +18,17 @@
 #include <errno.h>
 #include <sys/types.h>
 
+#include <binder/IPCThreadState.h>
+
 #include <utils/threads.h>
 #include <utils/Timers.h>
 #include <utils/Log.h>
-#include <binder/IPCThreadState.h>
+
+#include <gui/IDisplayEventConnection.h>
+#include <gui/BitTube.h>
 
 #include "MessageQueue.h"
+#include "EventThread.h"
 
 namespace android {
 
@@ -51,6 +56,15 @@
 MessageQueue::~MessageQueue() {
 }
 
+void MessageQueue::setEventThread(const sp<EventThread>& eventThread)
+{
+    mEventThread = eventThread;
+    mEvents = eventThread->createEventConnection();
+    mEventTube = mEvents->getDataChannel();
+    mLooper->addFd(mEventTube->getFd(), 0, ALOOPER_EVENT_INPUT,
+            MessageQueue::cb_eventReceiver, this);
+}
+
 void MessageQueue::waitMessage() {
     do {
         IPCThreadState::self()->flushCommands();
@@ -93,13 +107,54 @@
     return NO_ERROR;
 }
 
-status_t MessageQueue::invalidate() {
+void MessageQueue::scheduleWorkASAP() {
     if (android_atomic_or(1, &mWorkPending) == 0) {
         mLooper->wake();
-    }
+   }
+}
+
+status_t MessageQueue::invalidate() {
+    mEvents->requestNextVsync();
     return NO_ERROR;
 }
 
+int MessageQueue::cb_eventReceiver(int fd, int events, void* data) {
+    MessageQueue* queue = reinterpret_cast<MessageQueue *>(data);
+    return queue->eventReceiver(fd, events);
+}
+
+int MessageQueue::eventReceiver(int fd, int events) {
+    ssize_t n;
+    DisplayEventReceiver::Event buffer[8];
+    while ((n = getEvents(buffer, 8)) > 0) {
+        for (int i=0 ; i<n ; i++) {
+            if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
+                scheduleWorkASAP();
+                break;
+            }
+        }
+    }
+    return 1;
+}
+
+ssize_t MessageQueue::getEvents(
+        DisplayEventReceiver::Event* events, size_t count)
+{
+    ssize_t size = mEventTube->read(events, sizeof(events[0])*count);
+    ALOGE_IF(size<0, "MessageQueue::getEvents error (%s)", strerror(-size));
+    if (size >= 0) {
+        // Note: if (size % sizeof(events[0])) != 0, we've got a
+        // partial read. This can happen if the queue filed up (ie: if we
+        // didn't pull from it fast enough).
+        // We discard the partial event and rely on the sender to
+        // re-send the event if appropriate (some events, like VSYNC
+        // can be lost forever).
+        // returns number of events read
+        size /= sizeof(events[0]);
+    }
+    return size;
+}
+
 // ---------------------------------------------------------------------------
 
 }; // namespace android
diff --git a/services/surfaceflinger/MessageQueue.h b/services/surfaceflinger/MessageQueue.h
index 2317d81..5ea197d 100644
--- a/services/surfaceflinger/MessageQueue.h
+++ b/services/surfaceflinger/MessageQueue.h
@@ -25,10 +25,15 @@
 #include <utils/Timers.h>
 #include <utils/Looper.h>
 
+#include <gui/DisplayEventReceiver.h>
+
 #include "Barrier.h"
 
 namespace android {
 
+class IDisplayEventConnection;
+class EventThread;
+
 // ---------------------------------------------------------------------------
 
 class MessageBase : public MessageHandler
@@ -55,11 +60,20 @@
 
 class MessageQueue {
     sp<Looper> mLooper;
-    volatile int32_t mWorkPending;
+    sp<EventThread> mEventThread;
+    sp<IDisplayEventConnection> mEvents;
+    sp<BitTube> mEventTube;
+    int32_t mWorkPending;
+
+    static int cb_eventReceiver(int fd, int events, void* data);
+    int eventReceiver(int fd, int events);
+    ssize_t getEvents(DisplayEventReceiver::Event* events, size_t count);
+    void scheduleWorkASAP();
 
 public:
     MessageQueue();
     ~MessageQueue();
+    void setEventThread(const sp<EventThread>& events);
 
     void waitMessage();
     status_t postMessage(const sp<MessageBase>& message, nsecs_t reltime=0);
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 887aee7..ff70ec3 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -296,6 +296,7 @@
 
     // start the EventThread
     mEventThread = new EventThread(this);
+    mEventQueue.setEventThread(mEventThread);
 
     /*
      *  We're now ready to accept clients...
@@ -383,8 +384,7 @@
 // ----------------------------------------------------------------------------
 
 sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection() {
-    sp<DisplayEventConnection> result(new DisplayEventConnection(mEventThread));
-    return result;
+    return mEventThread->createEventConnection();
 }
 
 // ----------------------------------------------------------------------------
@@ -432,7 +432,6 @@
     } else {
         // pretend we did the post
         hw.compositionComplete();
-        hw.waitForRefresh();
     }
     return true;
 }
diff --git a/services/surfaceflinger/SurfaceTextureLayer.cpp b/services/surfaceflinger/SurfaceTextureLayer.cpp
index 259b937..49e8e63 100644
--- a/services/surfaceflinger/SurfaceTextureLayer.cpp
+++ b/services/surfaceflinger/SurfaceTextureLayer.cpp
@@ -94,6 +94,10 @@
             *outTransform = orientation;
         }
         switch(api) {
+            case NATIVE_WINDOW_API_CPU:
+                // SurfaceTextureClient supports only 2 buffers for CPU connections
+                this->setBufferCountServer(2);
+                break;
             case NATIVE_WINDOW_API_MEDIA:
             case NATIVE_WINDOW_API_CAMERA:
                 // Camera preview and videos are rate-limited on the producer