am ba8e30a3: am 223b953c: Add Dalvik heap definition for 7" xhdpi devices.

* commit 'ba8e30a31d54d11d826649bafc404e520d3c6fad':
  Add Dalvik heap definition for 7" xhdpi devices.
diff --git a/include/gui/BufferQueue.h b/include/gui/BufferQueue.h
index 6c1b691..34264bf 100644
--- a/include/gui/BufferQueue.h
+++ b/include/gui/BufferQueue.h
@@ -229,7 +229,7 @@
 
     // dump our state in a String
     virtual void dump(String8& result) const;
-    virtual void dump(String8& result, const char* prefix, char* buffer, size_t SIZE) const;
+    virtual void dump(String8& result, const char* prefix) const;
 
     // public facing structure for BufferSlot
     struct BufferItem {
diff --git a/include/gui/ConsumerBase.h b/include/gui/ConsumerBase.h
index 8a7545d..6250d8f 100644
--- a/include/gui/ConsumerBase.h
+++ b/include/gui/ConsumerBase.h
@@ -73,7 +73,7 @@
     // their state to the dump by overriding the dumpLocked method, which is
     // called by these methods after locking the mutex.
     void dump(String8& result) const;
-    void dump(String8& result, const char* prefix, char* buffer, size_t SIZE) const;
+    void dump(String8& result, const char* prefix) const;
 
     // setFrameAvailableListener sets the listener object that will be notified
     // when a new frame becomes available.
@@ -143,8 +143,7 @@
     // should call ConsumerBase::dumpLocked.
     //
     // This method must be called with mMutex locked.
-    virtual void dumpLocked(String8& result, const char* prefix, char* buffer,
-            size_t size) const;
+    virtual void dumpLocked(String8& result, const char* prefix) const;
 
     // acquireBufferLocked fetches the next buffer from the BufferQueue and
     // updates the buffer slot for the buffer returned.
diff --git a/include/gui/GLConsumer.h b/include/gui/GLConsumer.h
index f0a75dc..1e88927 100644
--- a/include/gui/GLConsumer.h
+++ b/include/gui/GLConsumer.h
@@ -233,8 +233,7 @@
 
     // dumpLocked overrides the ConsumerBase method to dump GLConsumer-
     // specific info in addition to the ConsumerBase behavior.
-    virtual void dumpLocked(String8& result, const char* prefix, char* buffer,
-           size_t size) const;
+    virtual void dumpLocked(String8& result, const char* prefix) const;
 
     // acquireBufferLocked overrides the ConsumerBase method to update the
     // mEglSlots array in addition to the ConsumerBase behavior.
diff --git a/include/media/openmax/OMX_IVCommon.h b/include/media/openmax/OMX_IVCommon.h
index 85bf00d..96a4396 100644
--- a/include/media/openmax/OMX_IVCommon.h
+++ b/include/media/openmax/OMX_IVCommon.h
@@ -161,6 +161,7 @@
     OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00,
     OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka = 0x7FA30C03,
     OMX_SEC_COLOR_FormatNV12Tiled = 0x7FC00002,
+    OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar32m = 0x7FA30C04,
     OMX_COLOR_FormatMax = 0x7FFFFFFF
 } OMX_COLOR_FORMATTYPE;
 
diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp
index b4c7231..942151f 100644
--- a/libs/gui/BufferQueue.cpp
+++ b/libs/gui/BufferQueue.cpp
@@ -707,36 +707,29 @@
     return err;
 }
 
-void BufferQueue::dump(String8& result) const
-{
-    char buffer[1024];
-    BufferQueue::dump(result, "", buffer, 1024);
+void BufferQueue::dump(String8& result) const {
+    BufferQueue::dump(result, "");
 }
 
-void BufferQueue::dump(String8& result, const char* prefix,
-        char* buffer, size_t SIZE) const
-{
+void BufferQueue::dump(String8& result, const char* prefix) const {
     Mutex::Autolock _l(mMutex);
 
     String8 fifo;
     int fifoSize = 0;
     Fifo::const_iterator i(mQueue.begin());
     while (i != mQueue.end()) {
-       snprintf(buffer, SIZE, "%02d ", *i++);
-       fifoSize++;
-       fifo.append(buffer);
+        fifo.appendFormat("%02d ", *i++);
+        fifoSize++;
     }
 
     int maxBufferCount = getMaxBufferCountLocked();
 
-    snprintf(buffer, SIZE,
+    result.appendFormat(
             "%s-BufferQueue maxBufferCount=%d, mSynchronousMode=%d, default-size=[%dx%d], "
             "default-format=%d, transform-hint=%02x, FIFO(%d)={%s}\n",
             prefix, maxBufferCount, mSynchronousMode, mDefaultWidth,
             mDefaultHeight, mDefaultBufferFormat, mTransformHint,
             fifoSize, fifo.string());
-    result.append(buffer);
-
 
     struct {
         const char * operator()(int state) const {
@@ -752,7 +745,7 @@
 
     for (int i=0 ; i<maxBufferCount ; i++) {
         const BufferSlot& slot(mSlots[i]);
-        snprintf(buffer, SIZE,
+        result.appendFormat(
                 "%s%s[%02d] "
                 "state=%-8s, crop=[%d,%d,%d,%d], "
                 "xform=0x%02x, time=%#llx, scale=%s",
@@ -762,15 +755,13 @@
                 slot.mCrop.bottom, slot.mTransform, slot.mTimestamp,
                 scalingModeName(slot.mScalingMode)
         );
-        result.append(buffer);
 
         const sp<GraphicBuffer>& buf(slot.mGraphicBuffer);
         if (buf != NULL) {
-            snprintf(buffer, SIZE,
+            result.appendFormat(
                     ", %p [%4ux%4u:%4u,%3X]",
                     buf->handle, buf->width, buf->height, buf->stride,
                     buf->format);
-            result.append(buffer);
         }
         result.append("\n");
     }
diff --git a/libs/gui/ConsumerBase.cpp b/libs/gui/ConsumerBase.cpp
index 4937b17..8d911c9 100644
--- a/libs/gui/ConsumerBase.cpp
+++ b/libs/gui/ConsumerBase.cpp
@@ -165,23 +165,19 @@
 }
 
 void ConsumerBase::dump(String8& result) const {
-    char buffer[1024];
-    dump(result, "", buffer, 1024);
+    dump(result, "");
 }
 
-void ConsumerBase::dump(String8& result, const char* prefix,
-        char* buffer, size_t size) const {
+void ConsumerBase::dump(String8& result, const char* prefix) const {
     Mutex::Autolock _l(mMutex);
-    dumpLocked(result, prefix, buffer, size);
+    dumpLocked(result, prefix);
 }
 
-void ConsumerBase::dumpLocked(String8& result, const char* prefix,
-        char* buffer, size_t SIZE) const {
-    snprintf(buffer, SIZE, "%smAbandoned=%d\n", prefix, int(mAbandoned));
-    result.append(buffer);
+void ConsumerBase::dumpLocked(String8& result, const char* prefix) const {
+    result.appendFormat("%smAbandoned=%d\n", prefix, int(mAbandoned));
 
     if (!mAbandoned) {
-        mBufferQueue->dump(result, prefix, buffer, SIZE);
+        mBufferQueue->dump(result, prefix);
     }
 }
 
diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp
index 637a403..7487612 100644
--- a/libs/gui/GLConsumer.cpp
+++ b/libs/gui/GLConsumer.cpp
@@ -887,18 +887,16 @@
     return mBufferQueue->setSynchronousMode(enabled);
 }
 
-void GLConsumer::dumpLocked(String8& result, const char* prefix,
-        char* buffer, size_t size) const
+void GLConsumer::dumpLocked(String8& result, const char* prefix) const
 {
-    snprintf(buffer, size,
+    result.appendFormat(
        "%smTexName=%d mCurrentTexture=%d\n"
        "%smCurrentCrop=[%d,%d,%d,%d] mCurrentTransform=%#x\n",
        prefix, mTexName, mCurrentTexture, prefix, mCurrentCrop.left,
        mCurrentCrop.top, mCurrentCrop.right, mCurrentCrop.bottom,
        mCurrentTransform);
-    result.append(buffer);
 
-    ConsumerBase::dumpLocked(result, prefix, buffer, size);
+    ConsumerBase::dumpLocked(result, prefix);
 }
 
 static void mtxMul(float out[16], const float a[16], const float b[16]) {
diff --git a/libs/utils/Android.mk b/libs/utils/Android.mk
index cbfe7bd..ce25605 100644
--- a/libs/utils/Android.mk
+++ b/libs/utils/Android.mk
@@ -98,7 +98,7 @@
 include $(BUILD_HOST_STATIC_LIBRARY)
 
 
-# For the device
+# For the device, static
 # =====================================================
 include $(CLEAR_VARS)
 
@@ -123,14 +123,29 @@
 
 LOCAL_LDLIBS += -lpthread
 
-LOCAL_SHARED_LIBRARIES := \
-	liblog \
+LOCAL_STATIC_LIBRARIES := \
 	libcutils \
-	libdl \
-	libcorkscrew \
 	libz
 
+LOCAL_SHARED_LIBRARIES := \
+        libcorkscrew \
+        liblog \
+        libdl
+
 LOCAL_MODULE:= libutils
+include $(BUILD_STATIC_LIBRARY)
+
+# For the device, shared
+# =====================================================
+include $(CLEAR_VARS)
+LOCAL_MODULE:= libutils
+LOCAL_WHOLE_STATIC_LIBRARIES := libutils
+LOCAL_SHARED_LIBRARIES := \
+        liblog \
+        libcutils \
+        libdl \
+        libcorkscrew \
+        libz
 include $(BUILD_SHARED_LIBRARY)
 
 # Include subdirectory makefiles
diff --git a/libs/utils/Threads.cpp b/libs/utils/Threads.cpp
index 7b877e0..e0f12dc 100644
--- a/libs/utils/Threads.cpp
+++ b/libs/utils/Threads.cpp
@@ -68,20 +68,6 @@
 
 typedef void* (*android_pthread_entry)(void*);
 
-static pthread_once_t gDoSchedulingGroupOnce = PTHREAD_ONCE_INIT;
-static bool gDoSchedulingGroup = true;
-
-static void checkDoSchedulingGroup(void) {
-    char buf[PROPERTY_VALUE_MAX];
-    int len = property_get("debug.sys.noschedgroups", buf, "");
-    if (len > 0) {
-        int temp;
-        if (sscanf(buf, "%d", &temp) == 1) {
-            gDoSchedulingGroup = temp == 0;
-        }
-    }
-}
-
 struct thread_data_t {
     thread_func_t   entryFunction;
     void*           userData;
@@ -97,15 +83,10 @@
         char * name = t->threadName;
         delete t;
         setpriority(PRIO_PROCESS, 0, prio);
-        pthread_once(&gDoSchedulingGroupOnce, checkDoSchedulingGroup);
-        if (gDoSchedulingGroup) {
-            if (prio >= ANDROID_PRIORITY_BACKGROUND) {
-                set_sched_policy(androidGetTid(), SP_BACKGROUND);
-            } else if (prio > ANDROID_PRIORITY_AUDIO) {
-                set_sched_policy(androidGetTid(), SP_FOREGROUND);
-            } else {
-                // defaults to that of parent, or as set by requestPriority()
-            }
+        if (prio >= ANDROID_PRIORITY_BACKGROUND) {
+            set_sched_policy(0, SP_BACKGROUND);
+        } else {
+            set_sched_policy(0, SP_FOREGROUND);
         }
         
         if (name) {
@@ -337,20 +318,10 @@
 #if defined(HAVE_PTHREADS)
     int lasterr = 0;
 
-    pthread_once(&gDoSchedulingGroupOnce, checkDoSchedulingGroup);
-    if (gDoSchedulingGroup) {
-        // set_sched_policy does not support tid == 0
-        int policy_tid;
-        if (tid == 0) {
-            policy_tid = androidGetTid();
-        } else {
-            policy_tid = tid;
-        }
-        if (pri >= ANDROID_PRIORITY_BACKGROUND) {
-            rc = set_sched_policy(policy_tid, SP_BACKGROUND);
-        } else if (getpriority(PRIO_PROCESS, tid) >= ANDROID_PRIORITY_BACKGROUND) {
-            rc = set_sched_policy(policy_tid, SP_FOREGROUND);
-        }
+    if (pri >= ANDROID_PRIORITY_BACKGROUND) {
+        rc = set_sched_policy(tid, SP_BACKGROUND);
+    } else if (getpriority(PRIO_PROCESS, tid) >= ANDROID_PRIORITY_BACKGROUND) {
+        rc = set_sched_policy(tid, SP_FOREGROUND);
     }
 
     if (rc) {
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index 00bfa5a..c02a85f 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -21,6 +21,7 @@
 #include <errno.h>
 #include <dlfcn.h>
 #include <limits.h>
+#include <dirent.h>
 
 #include <cutils/log.h>
 #include <cutils/properties.h>
@@ -38,9 +39,25 @@
 
 
 /*
- * EGL drivers are called
+ * EGL userspace drivers must be provided either:
+ * - as a single library:
+ *      /vendor/lib/egl/libGLES.so
+ *
+ * - as separate libraries:
+ *      /vendor/lib/egl/libEGL.so
+ *      /vendor/lib/egl/libGLESv1_CM.so
+ *      /vendor/lib/egl/libGLESv2.so
+ *
+ * The software renderer for the emulator must be provided as a single
+ * library at:
+ *
+ *      /system/lib/egl/libGLES_android.so
+ *
+ *
+ * For backward compatibility and to facilitate the transition to
+ * this new naming scheme, the loader will additionally look for:
  * 
- * /system/lib/egl/lib{[EGL|GLESv1_CM|GLESv2] | GLES}_$TAG.so 
+ *      /{vendor|system}/lib/egl/lib{GLES | [EGL|GLESv1_CM|GLESv2]}_*.so
  * 
  */
 
@@ -137,41 +154,10 @@
 // ----------------------------------------------------------------------------
 
 Loader::Loader()
-{
-    char line[256];
-    char tag[256];
-
-    /* Special case for GLES emulation */
-    if (checkGlesEmulationStatus() == 0) {
-        ALOGD("Emulator without GPU support detected. "
-              "Fallback to software renderer.");
-        mDriverTag.setTo("android");
-        return;
-    }
-
-    /* Otherwise, use egl.cfg */
-    FILE* cfg = fopen("/system/lib/egl/egl.cfg", "r");
-    if (cfg == NULL) {
-        // default config
-        ALOGD("egl.cfg not found, using default config");
-        mDriverTag.setTo("android");
-    } else {
-        while (fgets(line, 256, cfg)) {
-            int dpy, impl;
-            if (sscanf(line, "%u %u %s", &dpy, &impl, tag) == 3) {
-                //ALOGD(">>> %u %u %s", dpy, impl, tag);
-                // We only load the h/w accelerated implementation
-                if (tag != String8("android")) {
-                    mDriverTag = tag;
-                }
-            }
-        }
-        fclose(cfg);
-    }
+    : getProcAddress(NULL) {
 }
 
-Loader::~Loader()
-{
+Loader::~Loader() {
     GLTrace_stop();
 }
 
@@ -180,26 +166,20 @@
     void* dso;
     driver_t* hnd = 0;
     
-    char const* tag = mDriverTag.string();
-    if (tag) {
-        dso = load_driver("GLES", tag, cnx, EGL | GLESv1_CM | GLESv2);
+    dso = load_driver("GLES", cnx, EGL | GLESv1_CM | GLESv2);
+    if (dso) {
+        hnd = new driver_t(dso);
+    } else {
+        // Always load EGL first
+        dso = load_driver("EGL", cnx, EGL);
         if (dso) {
             hnd = new driver_t(dso);
-        } else {
-            // Always load EGL first
-            dso = load_driver("EGL", tag, cnx, EGL);
-            if (dso) {
-                hnd = new driver_t(dso);
-                // TODO: make this more automated
-                hnd->set( load_driver("GLESv1_CM", tag, cnx, GLESv1_CM), GLESv1_CM );
-                hnd->set( load_driver("GLESv2",    tag, cnx, GLESv2),    GLESv2 );
-            }
+            hnd->set( load_driver("GLESv1_CM", cnx, GLESv1_CM), GLESv1_CM );
+            hnd->set( load_driver("GLESv2",    cnx, GLESv2),    GLESv2 );
         }
     }
 
-    LOG_FATAL_IF(!index && !hnd,
-            "couldn't find the default OpenGL ES implementation "
-            "for default display");
+    LOG_ALWAYS_FATAL_IF(!hnd, "couldn't find an OpenGL ES implementation");
     
     return (void*)hnd;
 }
@@ -267,21 +247,106 @@
     }
 }
 
-void *Loader::load_driver(const char* kind, const char *tag,
+void *Loader::load_driver(const char* kind,
         egl_connection_t* cnx, uint32_t mask)
 {
-    char driver_absolute_path[PATH_MAX];
-    const char* const search1 = "/vendor/lib/egl/lib%s_%s.so";
-    const char* const search2 = "/system/lib/egl/lib%s_%s.so";
+    class MatchFile {
+    public:
+        static String8 find(const char* kind) {
+            String8 result;
+            String8 pattern;
+            pattern.appendFormat("lib%s", kind);
+            const char* const searchPaths[] = {
+                    "/vendor/lib/egl",
+                    "/system/lib/egl"
+            };
 
-    snprintf(driver_absolute_path, PATH_MAX, search1, kind, tag);
-    if (access(driver_absolute_path, R_OK)) {
-        snprintf(driver_absolute_path, PATH_MAX, search2, kind, tag);
-        if (access(driver_absolute_path, R_OK)) {
-            // this happens often, we don't want to log an error
-            return 0;
+            // first, we search for the exact name of the GLES userspace
+            // driver in both locations.
+            // i.e.:
+            //      libGLES.so, or:
+            //      libEGL.so, libGLESv1_CM.so, libGLESv2.so
+
+            for (size_t i=0 ; i<NELEM(searchPaths) ; i++) {
+                if (find(result, pattern, searchPaths[i], true)) {
+                    return result;
+                }
+            }
+
+            // for compatibility with the old "egl.cfg" naming convention
+            // we look for files that match:
+            //      libGLES_*.so, or:
+            //      libEGL_*.so, libGLESv1_CM_*.so, libGLESv2_*.so
+
+            pattern.append("_");
+            for (size_t i=0 ; i<NELEM(searchPaths) ; i++) {
+                if (find(result, pattern, searchPaths[i], false)) {
+                    return result;
+                }
+            }
+
+            // we didn't find the driver. gah.
+            result.clear();
+            return result;
         }
+
+    private:
+        static bool find(String8& result,
+                const String8& pattern, const char* const search, bool exact) {
+
+            // in the emulator case, we just return the hardcoded name
+            // of the software renderer.
+            if (checkGlesEmulationStatus() == 0) {
+                ALOGD("Emulator without GPU support detected. "
+                      "Fallback to software renderer.");
+                result.setTo("/system/lib/egl/libGLES_android.so");
+                return true;
+            }
+
+            if (exact) {
+                String8 absolutePath;
+                absolutePath.appendFormat("%s/%s.so", search, pattern.string());
+                if (!access(absolutePath.string(), R_OK)) {
+                    result = absolutePath;
+                    return true;
+                }
+                return false;
+            }
+
+            DIR* d = opendir(search);
+            if (d != NULL) {
+                struct dirent cur;
+                struct dirent* e;
+                while (readdir_r(d, &cur, &e) == 0 && e) {
+                    if (e->d_type == DT_DIR) {
+                        continue;
+                    }
+                    if (!strcmp(e->d_name, "libGLES_android.so")) {
+                        // always skip the software renderer
+                        continue;
+                    }
+                    if (strstr(e->d_name, pattern.string()) == e->d_name) {
+                        if (!strcmp(e->d_name + strlen(e->d_name) - 3, ".so")) {
+                            result.clear();
+                            result.appendFormat("%s/%s", search, e->d_name);
+                            closedir(d);
+                            return true;
+                        }
+                    }
+                }
+                closedir(d);
+            }
+            return false;
+        }
+    };
+
+
+    String8 absolutePath = MatchFile::find(kind);
+    if (absolutePath.isEmpty()) {
+        // this happens often, we don't want to log an error
+        return 0;
     }
+    const char* const driver_absolute_path = absolutePath.string();
 
     void* dso = dlopen(driver_absolute_path, RTLD_NOW | RTLD_LOCAL);
     if (dso == 0) {
diff --git a/opengl/libs/EGL/Loader.h b/opengl/libs/EGL/Loader.h
index 30773cb..8cefe32 100644
--- a/opengl/libs/EGL/Loader.h
+++ b/opengl/libs/EGL/Loader.h
@@ -52,7 +52,6 @@
         void* dso[3];
     };
     
-    String8 mDriverTag;
     getProcAddressType getProcAddress;
     
 public:
@@ -63,7 +62,7 @@
     
 private:
     Loader();
-    void *load_driver(const char* kind, const char *tag, egl_connection_t* cnx, uint32_t mask);
+    void *load_driver(const char* kind, egl_connection_t* cnx, uint32_t mask);
 
     static __attribute__((noinline))
     void init_api(void* dso, 
diff --git a/opengl/tools/glgen/stubs/gles11/common.cpp b/opengl/tools/glgen/stubs/gles11/common.cpp
index 579d573..75b75cb 100644
--- a/opengl/tools/glgen/stubs/gles11/common.cpp
+++ b/opengl/tools/glgen/stubs/gles11/common.cpp
@@ -272,6 +272,7 @@
     int _needed = 0;
 
     params = (CTYPE *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    _remaining /= sizeof(CTYPE);    // convert from bytes to item count
     _needed = getNeededCount(pname);
     // if we didn't find this pname, we just assume the user passed
     // an array of the right size -- this might happen with extensions
diff --git a/services/surfaceflinger/Colorizer.h b/services/surfaceflinger/Colorizer.h
new file mode 100644
index 0000000..6524481
--- /dev/null
+++ b/services/surfaceflinger/Colorizer.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SURFACE_FLINGER_COLORIZER_H
+#define ANDROID_SURFACE_FLINGER_COLORIZER_H
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+class Colorizer {
+    bool mEnabled;
+public:
+    enum color {
+        RED     = 31,
+        GREEN   = 32,
+        YELLOW  = 33,
+        BLUE    = 34,
+        MAGENTA = 35,
+        CYAN    = 36,
+        WHITE   = 37
+    };
+
+    Colorizer(bool enabled)
+        : mEnabled(enabled) {
+    }
+
+    void colorize(String8& out, color c) {
+        if (mEnabled) {
+            out.appendFormat("\e[%dm", c);
+        }
+    }
+
+    void bold(String8& out) {
+        if (mEnabled) {
+            out.append("\e[1m");
+        }
+    }
+
+    void reset(String8& out) {
+        if (mEnabled) {
+            out.append("\e[0m");
+        }
+    }
+};
+
+// ---------------------------------------------------------------------------
+
+}; // namespace android
+
+
+#endif /* ANDROID_SURFACE_FLINGER_COLORIZER_H */
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 68b0b7f..42b30cc 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -424,9 +424,9 @@
     mFrame = frame;
 }
 
-void DisplayDevice::dump(String8& result, char* buffer, size_t SIZE) const {
+void DisplayDevice::dump(String8& result) const {
     const Transform& tr(mGlobalTransform);
-    snprintf(buffer, SIZE,
+    result.appendFormat(
         "+ DisplayDevice: %s\n"
         "   type=%x, hwcId=%d, layerStack=%u, (%4dx%4d), ANativeWindow=%p, orient=%2d (type=%08x), "
         "flips=%u, isSecure=%d, secureVis=%d, acquired=%d, numLayers=%u\n"
@@ -443,8 +443,6 @@
         tr[0][1], tr[1][1], tr[2][1],
         tr[0][2], tr[1][2], tr[2][2]);
 
-    result.append(buffer);
-
     String8 surfaceDump;
     mDisplaySurface->dump(surfaceDump);
     result.append(surfaceDump);
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 377d924..047eecd 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -153,7 +153,7 @@
      * Debugging
      */
     uint32_t getPageFlipCount() const;
-    void dump(String8& result, char* buffer, size_t SIZE) const;
+    void dump(String8& result) const;
 
 private:
     /*
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index 54a3ce8..8b454ce 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -175,11 +175,10 @@
     ConsumerBase::dump(result);
 }
 
-void FramebufferSurface::dumpLocked(String8& result, const char* prefix,
-            char* buffer, size_t SIZE) const
+void FramebufferSurface::dumpLocked(String8& result, const char* prefix) const
 {
     mHwc.fbDump(result);
-    ConsumerBase::dumpLocked(result, prefix, buffer, SIZE);
+    ConsumerBase::dumpLocked(result, prefix);
 }
 
 // ----------------------------------------------------------------------------
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
index 2fde789..c86e9ae 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
@@ -55,8 +55,7 @@
     virtual void onFrameAvailable();
     virtual void freeBufferLocked(int slotIndex);
 
-    virtual void dumpLocked(String8& result, const char* prefix,
-            char* buffer, size_t SIZE) const;
+    virtual void dumpLocked(String8& result, const char* prefix) const;
 
     // nextBuffer waits for and then latches the next buffer from the
     // BufferQueue and releases the previously latched buffer to the
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 3f00f07..6bdccb9 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -546,9 +546,6 @@
         // triggers a Surface::queueBuffer()  on some
         // devices (!?) -- log and ignore.
         ALOGE("HWComposer: framebufferTarget is null");
-//        CallStack stack;
-//        stack.update();
-//        stack.dump("");
         return NO_ERROR;
     }
 
@@ -958,7 +955,7 @@
     return getLayerIterator(id, numLayers);
 }
 
-void HWComposer::dump(String8& result, char* buffer, size_t SIZE) const {
+void HWComposer::dump(String8& result) const {
     if (mHwc) {
         result.appendFormat("Hardware Composer state (version %8x):\n", hwcApiVersion(mHwc));
         result.appendFormat("  mDebugForceFakeVSync=%d\n", mDebugForceFakeVSync);
@@ -1026,6 +1023,8 @@
     }
 
     if (mHwc && mHwc->dump) {
+        const size_t SIZE = 4096;
+        char buffer[SIZE];
         mHwc->dump(mHwc, buffer, SIZE);
         result.append(buffer);
     }
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 604de38..a20da08 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -275,7 +275,7 @@
     friend class VSyncThread;
 
     // for debugging ----------------------------------------------------------
-    void dump(String8& out, char* scratch, size_t SIZE) const;
+    void dump(String8& out) const;
 
 private:
     void loadHwcModule();
diff --git a/services/surfaceflinger/EventThread.cpp b/services/surfaceflinger/EventThread.cpp
index 4d0fc79..4126c8a 100644
--- a/services/surfaceflinger/EventThread.cpp
+++ b/services/surfaceflinger/EventThread.cpp
@@ -320,7 +320,7 @@
     mDebugVsyncEnabled = false;
 }
 
-void EventThread::dump(String8& result, char* buffer, size_t SIZE) const {
+void EventThread::dump(String8& result) const {
     Mutex::Autolock _l(mLock);
     result.appendFormat("VSYNC state: %s\n",
             mDebugVsyncEnabled?"enabled":"disabled");
diff --git a/services/surfaceflinger/EventThread.h b/services/surfaceflinger/EventThread.h
index 1934f98..f6bd676 100644
--- a/services/surfaceflinger/EventThread.h
+++ b/services/surfaceflinger/EventThread.h
@@ -84,7 +84,7 @@
     Vector< sp<EventThread::Connection> > waitForEvent(
             DisplayEventReceiver::Event* event);
 
-    void dump(String8& result, char* buffer, size_t SIZE) const;
+    void dump(String8& result) const;
 
 private:
     virtual bool        threadLoop();
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 4779804..9896581 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -36,6 +36,7 @@
 #include <gui/Surface.h>
 
 #include "clz.h"
+#include "Colorizer.h"
 #include "DisplayDevice.h"
 #include "GLExtensions.h"
 #include "Layer.h"
@@ -1178,21 +1179,21 @@
 // debugging
 // ----------------------------------------------------------------------------
 
-void Layer::dump(String8& result, char* buffer, size_t SIZE) const
+void Layer::dump(String8& result, Colorizer& colorizer) const
 {
     const Layer::State& s(drawingState());
 
-    snprintf(buffer, SIZE,
+    colorizer.colorize(result, Colorizer::GREEN);
+    result.appendFormat(
             "+ %s %p (%s)\n",
             getTypeId(), this, getName().string());
-    result.append(buffer);
+    colorizer.reset(result);
 
     s.activeTransparentRegion.dump(result, "transparentRegion");
     visibleRegion.dump(result, "visibleRegion");
     sp<Client> client(mClientRef.promote());
 
-    snprintf(buffer, SIZE,
-            "      "
+    result.appendFormat(            "      "
             "layerStack=%4d, z=%9d, pos=(%g,%g), size=(%4d,%4d), crop=(%4d,%4d,%4d,%4d), "
             "isOpaque=%1d, invalidate=%1d, "
             "alpha=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n"
@@ -1205,7 +1206,6 @@
             s.transform[0][0], s.transform[0][1],
             s.transform[1][0], s.transform[1][1],
             client.get());
-    result.append(buffer);
 
     sp<const GraphicBuffer> buf0(mActiveBuffer);
     uint32_t w0=0, h0=0, s0=0, f0=0;
@@ -1215,26 +1215,19 @@
         s0 = buf0->getStride();
         f0 = buf0->format;
     }
-    snprintf(buffer, SIZE,
+    result.appendFormat(
             "      "
             "format=%2d, activeBuffer=[%4ux%4u:%4u,%3X],"
             " queued-frames=%d, mRefreshPending=%d\n",
             mFormat, w0, h0, s0,f0,
             mQueuedFrames, mRefreshPending);
 
-    result.append(buffer);
-
     if (mSurfaceFlingerConsumer != 0) {
-        mSurfaceFlingerConsumer->dump(result, "            ", buffer, SIZE);
+        mSurfaceFlingerConsumer->dump(result, "            ");
     }
 }
 
-
-void Layer::shortDump(String8& result, char* scratch, size_t size) const {
-    Layer::dump(result, scratch, size);
-}
-
-void Layer::dumpStats(String8& result, char* buffer, size_t SIZE) const {
+void Layer::dumpStats(String8& result) const {
     mFrameTracker.dump(result);
 }
 
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 2765db1..11fdbb5 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -51,6 +51,7 @@
 // ---------------------------------------------------------------------------
 
 class Client;
+class Colorizer;
 class DisplayDevice;
 class GraphicBuffer;
 class SurfaceFlinger;
@@ -304,9 +305,8 @@
 
 
     /* always call base class first */
-    virtual void dump(String8& result, char* scratch, size_t size) const;
-    virtual void shortDump(String8& result, char* scratch, size_t size) const;
-    virtual void dumpStats(String8& result, char* buffer, size_t SIZE) const;
+    virtual void dump(String8& result, Colorizer& colorizer) const;
+    virtual void dumpStats(String8& result) const;
     virtual void clearStats();
 
 protected:
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index e647275..735c822 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -55,10 +55,11 @@
 #include <private/android_filesystem_config.h>
 #include <private/gui/SyncFeatures.h>
 
+#include "Client.h"
 #include "clz.h"
+#include "Colorizer.h"
 #include "DdmConnection.h"
 #include "DisplayDevice.h"
-#include "Client.h"
 #include "EventThread.h"
 #include "GLExtensions.h"
 #include "Layer.h"
@@ -2141,19 +2142,15 @@
 
 status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args)
 {
-    const size_t SIZE = 4096;
-    char buffer[SIZE];
     String8 result;
 
-
     IPCThreadState* ipc = IPCThreadState::self();
     const int pid = ipc->getCallingPid();
     const int uid = ipc->getCallingUid();
     if ((uid != AID_SHELL) &&
             !PermissionCache::checkPermission(sDump, pid, uid)) {
-        snprintf(buffer, SIZE, "Permission Denial: "
+        result.appendFormat("Permission Denial: "
                 "can't dump SurfaceFlinger from pid=%d, uid=%d\n", pid, uid);
-        result.append(buffer);
     } else {
         // Try to get the main lock, but don't insist if we can't
         // (this would indicate SF is stuck, but we want to be able to
@@ -2164,10 +2161,9 @@
         }
         const bool locked(retry >= 0);
         if (!locked) {
-            snprintf(buffer, SIZE,
+            result.append(
                     "SurfaceFlinger appears to be unresponsive, "
                     "dumping anyways (no locks held)\n");
-            result.append(buffer);
         }
 
         bool dumpAll = true;
@@ -2177,27 +2173,27 @@
             if ((index < numArgs) &&
                     (args[index] == String16("--list"))) {
                 index++;
-                listLayersLocked(args, index, result, buffer, SIZE);
+                listLayersLocked(args, index, result);
                 dumpAll = false;
             }
 
             if ((index < numArgs) &&
                     (args[index] == String16("--latency"))) {
                 index++;
-                dumpStatsLocked(args, index, result, buffer, SIZE);
+                dumpStatsLocked(args, index, result);
                 dumpAll = false;
             }
 
             if ((index < numArgs) &&
                     (args[index] == String16("--latency-clear"))) {
                 index++;
-                clearStatsLocked(args, index, result, buffer, SIZE);
+                clearStatsLocked(args, index, result);
                 dumpAll = false;
             }
         }
 
         if (dumpAll) {
-            dumpAllLocked(result, buffer, SIZE);
+            dumpAllLocked(args, index, result);
         }
 
         if (locked) {
@@ -2209,19 +2205,18 @@
 }
 
 void SurfaceFlinger::listLayersLocked(const Vector<String16>& args, size_t& index,
-        String8& result, char* buffer, size_t SIZE) const
+        String8& result) const
 {
     const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
     const size_t count = currentLayers.size();
     for (size_t i=0 ; i<count ; i++) {
         const sp<Layer>& layer(currentLayers[i]);
-        snprintf(buffer, SIZE, "%s\n", layer->getName().string());
-        result.append(buffer);
+        result.appendFormat("%s\n", layer->getName().string());
     }
 }
 
 void SurfaceFlinger::dumpStatsLocked(const Vector<String16>& args, size_t& index,
-        String8& result, char* buffer, size_t SIZE) const
+        String8& result) const
 {
     String8 name;
     if (index < args.size()) {
@@ -2241,14 +2236,14 @@
         for (size_t i=0 ; i<count ; i++) {
             const sp<Layer>& layer(currentLayers[i]);
             if (name == layer->getName()) {
-                layer->dumpStats(result, buffer, SIZE);
+                layer->dumpStats(result);
             }
         }
     }
 }
 
 void SurfaceFlinger::clearStatsLocked(const Vector<String16>& args, size_t& index,
-        String8& result, char* buffer, size_t SIZE)
+        String8& result)
 {
     String8 name;
     if (index < args.size()) {
@@ -2288,9 +2283,18 @@
     result.append(config);
 }
 
-void SurfaceFlinger::dumpAllLocked(
-        String8& result, char* buffer, size_t SIZE) const
+void SurfaceFlinger::dumpAllLocked(const Vector<String16>& args, size_t& index,
+        String8& result) const
 {
+    bool colorize = false;
+    if (index < args.size()
+            && (args[index] == String16("--color"))) {
+        colorize = true;
+        index++;
+    }
+
+    Colorizer colorizer(colorize);
+
     // figure out if we're stuck somewhere
     const nsecs_t now = systemTime();
     const nsecs_t inSwapBuffers(mDebugInSwapBuffers);
@@ -2301,13 +2305,18 @@
     /*
      * Dump library configuration.
      */
+
+    colorizer.bold(result);
     result.append("Build configuration:");
+    colorizer.reset(result);
     appendSfConfigString(result);
     appendUiConfigString(result);
     appendGuiConfigString(result);
     result.append("\n");
 
+    colorizer.bold(result);
     result.append("Sync configuration: ");
+    colorizer.reset(result);
     result.append(SyncFeatures::getInstance().toString());
     result.append("\n");
 
@@ -2316,56 +2325,57 @@
      */
     const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
     const size_t count = currentLayers.size();
-    snprintf(buffer, SIZE, "Visible layers (count = %d)\n", count);
-    result.append(buffer);
+    colorizer.bold(result);
+    result.appendFormat("Visible layers (count = %d)\n", count);
+    colorizer.reset(result);
     for (size_t i=0 ; i<count ; i++) {
         const sp<Layer>& layer(currentLayers[i]);
-        layer->dump(result, buffer, SIZE);
+        layer->dump(result, colorizer);
     }
 
     /*
      * Dump Display state
      */
 
-    snprintf(buffer, SIZE, "Displays (%d entries)\n", mDisplays.size());
-    result.append(buffer);
+    colorizer.bold(result);
+    result.appendFormat("Displays (%d entries)\n", mDisplays.size());
+    colorizer.reset(result);
     for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
         const sp<const DisplayDevice>& hw(mDisplays[dpy]);
-        hw->dump(result, buffer, SIZE);
+        hw->dump(result);
     }
 
     /*
      * Dump SurfaceFlinger global state
      */
 
-    snprintf(buffer, SIZE, "SurfaceFlinger global state:\n");
-    result.append(buffer);
+    colorizer.bold(result);
+    result.append("SurfaceFlinger global state:\n");
+    colorizer.reset(result);
 
     HWComposer& hwc(getHwComposer());
     sp<const DisplayDevice> hw(getDefaultDisplayDevice());
     const GLExtensions& extensions(GLExtensions::getInstance());
 
-    snprintf(buffer, SIZE, "EGL implementation : %s\n",
+    colorizer.bold(result);
+    result.appendFormat("EGL implementation : %s\n",
             eglQueryStringImplementationANDROID(mEGLDisplay, EGL_VERSION));
-    result.append(buffer);
-    snprintf(buffer, SIZE, "%s\n",
+    colorizer.reset(result);
+    result.appendFormat("%s\n",
             eglQueryStringImplementationANDROID(mEGLDisplay, EGL_EXTENSIONS));
-    result.append(buffer);
 
-    snprintf(buffer, SIZE, "GLES: %s, %s, %s\n",
+    colorizer.bold(result);
+    result.appendFormat("GLES: %s, %s, %s\n",
             extensions.getVendor(),
             extensions.getRenderer(),
             extensions.getVersion());
-    result.append(buffer);
-    snprintf(buffer, SIZE, "%s\n", extensions.getExtension());
-    result.append(buffer);
+    colorizer.reset(result);
+    result.appendFormat("%s\n", extensions.getExtension());
 
     hw->undefinedRegion.dump(result, "undefinedRegion");
-    snprintf(buffer, SIZE,
-            "  orientation=%d, canDraw=%d\n",
+    result.appendFormat("  orientation=%d, canDraw=%d\n",
             hw->getOrientation(), hw->canDraw());
-    result.append(buffer);
-    snprintf(buffer, SIZE,
+    result.appendFormat(
             "  last eglSwapBuffers() time: %f us\n"
             "  last transaction time     : %f us\n"
             "  transaction-flags         : %08x\n"
@@ -2383,31 +2393,28 @@
             hwc.getDpiY(HWC_DISPLAY_PRIMARY),
             mEGLNativeVisualId,
             !mGpuToCpuSupported);
-    result.append(buffer);
 
-    snprintf(buffer, SIZE, "  eglSwapBuffers time: %f us\n",
+    result.appendFormat("  eglSwapBuffers time: %f us\n",
             inSwapBuffersDuration/1000.0);
-    result.append(buffer);
 
-    snprintf(buffer, SIZE, "  transaction time: %f us\n",
+    result.appendFormat("  transaction time: %f us\n",
             inTransactionDuration/1000.0);
-    result.append(buffer);
 
     /*
      * VSYNC state
      */
-    mEventThread->dump(result, buffer, SIZE);
+    mEventThread->dump(result);
 
     /*
      * Dump HWComposer state
      */
-    snprintf(buffer, SIZE, "h/w composer state:\n");
-    result.append(buffer);
-    snprintf(buffer, SIZE, "  h/w composer %s and %s\n",
+    colorizer.bold(result);
+    result.append("h/w composer state:\n");
+    colorizer.reset(result);
+    result.appendFormat("  h/w composer %s and %s\n",
             hwc.initCheck()==NO_ERROR ? "present" : "not present",
                     (mDebugDisableHWC || mDebugRegion) ? "disabled" : "enabled");
-    result.append(buffer);
-    hwc.dump(result, buffer, SIZE);
+    hwc.dump(result);
 
     /*
      * Dump gralloc state
@@ -2606,33 +2613,11 @@
         virtual bool handler() {
             Mutex::Autolock _l(flinger->mStateLock);
             sp<const DisplayDevice> hw(flinger->getDisplayDevice(display));
+            bool useReadPixels = isCpuConsumer && !flinger->mGpuToCpuSupported;
+            result = flinger->captureScreenImplLocked(hw,
+                    producer, reqWidth, reqHeight, minLayerZ, maxLayerZ,
+                    useReadPixels);
 
-            bool useReadPixels = false;
-            if (isCpuConsumer) {
-                bool formatSupportedBytBitmap =
-                        (flinger->mEGLNativeVisualId == HAL_PIXEL_FORMAT_RGBA_8888) ||
-                        (flinger->mEGLNativeVisualId == HAL_PIXEL_FORMAT_RGBX_8888);
-                if (formatSupportedBytBitmap == false) {
-                    // the pixel format we have is not compatible with
-                    // Bitmap.java, which is the likely client of this API,
-                    // so we just revert to glReadPixels() in that case.
-                    useReadPixels = true;
-                }
-                if (flinger->mGpuToCpuSupported == false) {
-                    // When we know the GL->CPU path works, we can call
-                    // captureScreenImplLocked() directly, instead of using the
-                    // glReadPixels() workaround.
-                    useReadPixels = true;
-                }
-            }
-
-            if (!useReadPixels) {
-                result = flinger->captureScreenImplLocked(hw,
-                        producer, reqWidth, reqHeight, minLayerZ, maxLayerZ);
-            } else {
-                result = flinger->captureScreenImplCpuConsumerLocked(hw,
-                        producer, reqWidth, reqHeight, minLayerZ, maxLayerZ);
-            }
             return true;
         }
     };
@@ -2713,73 +2698,8 @@
         const sp<const DisplayDevice>& hw,
         const sp<IGraphicBufferProducer>& producer,
         uint32_t reqWidth, uint32_t reqHeight,
-        uint32_t minLayerZ, uint32_t maxLayerZ)
-{
-    ATRACE_CALL();
-
-    // get screen geometry
-    const uint32_t hw_w = hw->getWidth();
-    const uint32_t hw_h = hw->getHeight();
-
-    // if we have secure windows on this display, never allow the screen capture
-    if (hw->getSecureLayerVisible()) {
-        ALOGW("FB is protected: PERMISSION_DENIED");
-        return PERMISSION_DENIED;
-    }
-
-    if ((reqWidth > hw_w) || (reqHeight > hw_h)) {
-        ALOGE("size mismatch (%d, %d) > (%d, %d)",
-                reqWidth, reqHeight, hw_w, hw_h);
-        return BAD_VALUE;
-    }
-
-    reqWidth = (!reqWidth) ? hw_w : reqWidth;
-    reqHeight = (!reqHeight) ? hw_h : reqHeight;
-
-    // Create a surface to render into
-    sp<Surface> surface = new Surface(producer);
-    ANativeWindow* const window = surface.get();
-
-    // set the buffer size to what the user requested
-    native_window_set_buffers_user_dimensions(window, reqWidth, reqHeight);
-
-    // and create the corresponding EGLSurface
-    EGLSurface eglSurface = eglCreateWindowSurface(
-            mEGLDisplay, mEGLConfig, window, NULL);
-    if (eglSurface == EGL_NO_SURFACE) {
-        ALOGE("captureScreenImplLocked: eglCreateWindowSurface() failed 0x%4x",
-                eglGetError());
-        return BAD_VALUE;
-    }
-
-    if (!eglMakeCurrent(mEGLDisplay, eglSurface, eglSurface, mEGLContext)) {
-        ALOGE("captureScreenImplLocked: eglMakeCurrent() failed 0x%4x",
-                eglGetError());
-        eglDestroySurface(mEGLDisplay, eglSurface);
-        return BAD_VALUE;
-    }
-
-    renderScreenImplLocked(hw, reqWidth, reqHeight, minLayerZ, maxLayerZ, false);
-
-    // and finishing things up...
-    if (eglSwapBuffers(mEGLDisplay, eglSurface) != EGL_TRUE) {
-        ALOGE("captureScreenImplLocked: eglSwapBuffers() failed 0x%4x",
-                eglGetError());
-        eglDestroySurface(mEGLDisplay, eglSurface);
-        return BAD_VALUE;
-    }
-
-    eglDestroySurface(mEGLDisplay, eglSurface);
-
-    return NO_ERROR;
-}
-
-
-status_t SurfaceFlinger::captureScreenImplCpuConsumerLocked(
-        const sp<const DisplayDevice>& hw,
-        const sp<IGraphicBufferProducer>& producer,
-        uint32_t reqWidth, uint32_t reqHeight,
-        uint32_t minLayerZ, uint32_t maxLayerZ)
+        uint32_t minLayerZ, uint32_t maxLayerZ,
+        bool useReadPixels)
 {
     ATRACE_CALL();
 
@@ -2806,66 +2726,102 @@
     reqWidth  = (!reqWidth)  ? hw_w : reqWidth;
     reqHeight = (!reqHeight) ? hw_h : reqHeight;
 
-    GLuint tname;
-    glGenRenderbuffersOES(1, &tname);
-    glBindRenderbufferOES(GL_RENDERBUFFER_OES, tname);
-    glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_RGBA8_OES, reqWidth, reqHeight);
-
-    // create a FBO
-    GLuint name;
-    glGenFramebuffersOES(1, &name);
-    glBindFramebufferOES(GL_FRAMEBUFFER_OES, name);
-    glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES,
-            GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, tname);
-
-    GLenum status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES);
+    // create a surface (because we're a producer, and we need to
+    // dequeue/queue a buffer)
+    sp<Surface> sur = new Surface(producer);
+    ANativeWindow* window = sur.get();
 
     status_t result = NO_ERROR;
-    if (status == GL_FRAMEBUFFER_COMPLETE_OES) {
-
-        renderScreenImplLocked(hw, reqWidth, reqHeight, minLayerZ, maxLayerZ, true);
-
-        // Below we render the screenshot into the
-        // CpuConsumer using glReadPixels from our FBO.
-        // Some older drivers don't support the GL->CPU path so we
-        // have to wrap it with a CPU->CPU path, which is what
-        // glReadPixels essentially is.
-
-        sp<Surface> sur = new Surface(producer);
-        ANativeWindow* window = sur.get();
-
-        if (native_window_api_connect(window, NATIVE_WINDOW_API_CPU) == NO_ERROR) {
-            int err = 0;
-            err = native_window_set_buffers_dimensions(window, reqWidth, reqHeight);
-            err |= native_window_set_buffers_format(window, HAL_PIXEL_FORMAT_RGBA_8888);
-            err |= native_window_set_usage(window,
-                    GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
-
-            if (err == NO_ERROR) {
-                ANativeWindowBuffer* buffer;
-                if (native_window_dequeue_buffer_and_wait(window,  &buffer) == NO_ERROR) {
-                    sp<GraphicBuffer> buf = static_cast<GraphicBuffer*>(buffer);
-                    void* vaddr;
-                    if (buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, &vaddr) == NO_ERROR) {
-                        glReadPixels(0, 0, buffer->stride, reqHeight,
-                                GL_RGBA, GL_UNSIGNED_BYTE, vaddr);
-                        buf->unlock();
-                    }
-                    window->queueBuffer(window, buffer, -1);
-                }
-            }
-            native_window_api_disconnect(window, NATIVE_WINDOW_API_CPU);
+    if (native_window_api_connect(window, NATIVE_WINDOW_API_EGL) == NO_ERROR) {
+        uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN;
+        if (!useReadPixels) {
+            usage = GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE;
         }
 
-    } else {
-        ALOGE("got GL_FRAMEBUFFER_COMPLETE_OES while taking screenshot");
-        result = INVALID_OPERATION;
-    }
+        int err = 0;
+        err = native_window_set_buffers_dimensions(window, reqWidth, reqHeight);
+        err |= native_window_set_buffers_format(window, HAL_PIXEL_FORMAT_RGBA_8888);
+        err |= native_window_set_usage(window, usage);
 
-    // back to main framebuffer
-    glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
-    glDeleteRenderbuffersOES(1, &tname);
-    glDeleteFramebuffersOES(1, &name);
+        if (err == NO_ERROR) {
+            ANativeWindowBuffer* buffer;
+            /* TODO: Once we have the sync framework everywhere this can use
+             * server-side waits on the fence that dequeueBuffer returns.
+             */
+            result = native_window_dequeue_buffer_and_wait(window,  &buffer);
+            if (result == NO_ERROR) {
+                // create an EGLImage from the buffer so we can later
+                // turn it into a texture
+                EGLImageKHR image = eglCreateImageKHR(mEGLDisplay, EGL_NO_CONTEXT,
+                        EGL_NATIVE_BUFFER_ANDROID, buffer, NULL);
+                if (image != EGL_NO_IMAGE_KHR) {
+                    GLuint tname, name;
+                    if (!useReadPixels) {
+                        // turn our EGLImage into a texture
+                        glGenTextures(1, &tname);
+                        glBindTexture(GL_TEXTURE_2D, tname);
+                        glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)image);
+                        // create a Framebuffer Object to render into
+                        glGenFramebuffersOES(1, &name);
+                        glBindFramebufferOES(GL_FRAMEBUFFER_OES, name);
+                        glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES,
+                                GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tname, 0);
+                    } else {
+                        // since we're going to use glReadPixels() anyways,
+                        // use an intermediate renderbuffer instead
+                        glGenRenderbuffersOES(1, &tname);
+                        glBindRenderbufferOES(GL_RENDERBUFFER_OES, tname);
+                        glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_RGBA8_OES, reqWidth, reqHeight);
+                        // create a FBO to render into
+                        glGenFramebuffersOES(1, &name);
+                        glBindFramebufferOES(GL_FRAMEBUFFER_OES, name);
+                        glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES,
+                                GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, tname);
+                    }
+
+                    GLenum status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES);
+                    if (status == GL_FRAMEBUFFER_COMPLETE_OES) {
+                        // this will in fact render into our dequeued buffer
+                        // via an FBO, which means we didn't have to create
+                        // an EGLSurface and therefore we're not
+                        // dependent on the context's EGLConfig.
+                        renderScreenImplLocked(hw, reqWidth, reqHeight,
+                                minLayerZ, maxLayerZ, true);
+
+                        if (useReadPixels) {
+                            sp<GraphicBuffer> buf = static_cast<GraphicBuffer*>(buffer);
+                            void* vaddr;
+                            if (buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, &vaddr) == NO_ERROR) {
+                                glReadPixels(0, 0, buffer->stride, reqHeight,
+                                        GL_RGBA, GL_UNSIGNED_BYTE, vaddr);
+                                buf->unlock();
+                            }
+                        }
+                    } else {
+                        ALOGE("got GL_FRAMEBUFFER_COMPLETE_OES error while taking screenshot");
+                        result = INVALID_OPERATION;
+                    }
+
+                    // back to main framebuffer
+                    glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
+                    glDeleteFramebuffersOES(1, &name);
+                    if (!useReadPixels) {
+                        glDeleteTextures(1, &tname);
+                    } else {
+                        glDeleteRenderbuffersOES(1, &tname);
+                    }
+                    // destroy our image
+                    eglDestroyImageKHR(mEGLDisplay, image);
+                } else {
+                    result = BAD_VALUE;
+                }
+                window->queueBuffer(window, buffer, -1);
+            }
+        } else {
+            result = BAD_VALUE;
+        }
+        native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
+    }
 
     DisplayDevice::setViewportAndProjection(hw);
 
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 739099c..66c2d42 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -298,14 +298,8 @@
             const sp<const DisplayDevice>& hw,
             const sp<IGraphicBufferProducer>& producer,
             uint32_t reqWidth, uint32_t reqHeight,
-            uint32_t minLayerZ, uint32_t maxLayerZ);
-
-    status_t captureScreenImplCpuConsumerLocked(
-            const sp<const DisplayDevice>& hw,
-            const sp<IGraphicBufferProducer>& producer,
-            uint32_t reqWidth, uint32_t reqHeight,
-            uint32_t minLayerZ, uint32_t maxLayerZ);
-
+            uint32_t minLayerZ, uint32_t maxLayerZ,
+            bool useReadPixels);
 
     /* ------------------------------------------------------------------------
      * EGL
@@ -385,12 +379,13 @@
      * Debugging & dumpsys
      */
     void listLayersLocked(const Vector<String16>& args, size_t& index,
-        String8& result, char* buffer, size_t SIZE) const;
+        String8& result) const;
     void dumpStatsLocked(const Vector<String16>& args, size_t& index,
-        String8& result, char* buffer, size_t SIZE) const;
+        String8& result) const;
     void clearStatsLocked(const Vector<String16>& args, size_t& index,
-        String8& result, char* buffer, size_t SIZE);
-    void dumpAllLocked(String8& result, char* buffer, size_t SIZE) const;
+        String8& result);
+    void dumpAllLocked(const Vector<String16>& args, size_t& index,
+        String8& result) const;
     bool startDdmConnection();
     static void appendSfConfigString(String8& result);