Merge "CpuConsumer: Properly track acquired buffers" into jb-mr2-dev
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index c6fda97..29838e4 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -69,43 +69,44 @@
 
 /* Tracing categories */
 static const TracingCategory k_categories[] = {
-    { "gfx",    "Graphics",         ATRACE_TAG_GRAPHICS, { } },
-    { "input",  "Input",            ATRACE_TAG_INPUT, { } },
-    { "view",   "View System",      ATRACE_TAG_VIEW, { } },
-    { "wm",     "Window Manager",   ATRACE_TAG_WINDOW_MANAGER, { } },
-    { "am",     "Activity Manager", ATRACE_TAG_ACTIVITY_MANAGER, { } },
-    { "audio",  "Audio",            ATRACE_TAG_AUDIO, { } },
-    { "video",  "Video",            ATRACE_TAG_VIDEO, { } },
-    { "camera", "Camera",           ATRACE_TAG_CAMERA, { } },
-    { "hal",    "Hardware Modules", ATRACE_TAG_HAL, { } },
-    { "sched",  "CPU Scheduling",   0, {
-        { REQ,  "/sys/kernel/debug/tracing/events/sched/sched_switch/enable" },
-        { REQ,  "/sys/kernel/debug/tracing/events/sched/sched_wakeup/enable" },
+    { "gfx",        "Graphics",         ATRACE_TAG_GRAPHICS, { } },
+    { "input",      "Input",            ATRACE_TAG_INPUT, { } },
+    { "view",       "View System",      ATRACE_TAG_VIEW, { } },
+    { "webview",    "WebView",          ATRACE_TAG_WEBVIEW, { } },
+    { "wm",         "Window Manager",   ATRACE_TAG_WINDOW_MANAGER, { } },
+    { "am",         "Activity Manager", ATRACE_TAG_ACTIVITY_MANAGER, { } },
+    { "audio",      "Audio",            ATRACE_TAG_AUDIO, { } },
+    { "video",      "Video",            ATRACE_TAG_VIDEO, { } },
+    { "camera",     "Camera",           ATRACE_TAG_CAMERA, { } },
+    { "hal",        "Hardware Modules", ATRACE_TAG_HAL, { } },
+    { "sched",      "CPU Scheduling",   0, {
+        { REQ,      "/sys/kernel/debug/tracing/events/sched/sched_switch/enable" },
+        { REQ,      "/sys/kernel/debug/tracing/events/sched/sched_wakeup/enable" },
     } },
-    { "freq",   "CPU Frequency",    0, {
-        { REQ,  "/sys/kernel/debug/tracing/events/power/cpu_frequency/enable" },
-        { OPT, "/sys/kernel/debug/tracing/events/power/clock_set_rate/enable" },
+    { "freq",       "CPU Frequency",    0, {
+        { REQ,      "/sys/kernel/debug/tracing/events/power/cpu_frequency/enable" },
+        { OPT,      "/sys/kernel/debug/tracing/events/power/clock_set_rate/enable" },
     } },
-    { "membus", "Memory Bus Utilization", 0, {
-        { REQ,  "/sys/kernel/debug/tracing/events/memory_bus/enable" },
+    { "membus",     "Memory Bus Utilization", 0, {
+        { REQ,      "/sys/kernel/debug/tracing/events/memory_bus/enable" },
     } },
-    { "idle",   "CPU Idle",         0, {
-        { REQ,  "/sys/kernel/debug/tracing/events/power/cpu_idle/enable" },
+    { "idle",       "CPU Idle",         0, {
+        { REQ,      "/sys/kernel/debug/tracing/events/power/cpu_idle/enable" },
     } },
-    { "disk",   "Disk I/O",         0, {
-        { REQ,  "/sys/kernel/debug/tracing/events/ext4/ext4_sync_file_enter/enable" },
-        { REQ,  "/sys/kernel/debug/tracing/events/ext4/ext4_sync_file_exit/enable" },
-        { REQ,  "/sys/kernel/debug/tracing/events/block/block_rq_issue/enable" },
-        { REQ,  "/sys/kernel/debug/tracing/events/block/block_rq_complete/enable" },
+    { "disk",       "Disk I/O",         0, {
+        { REQ,      "/sys/kernel/debug/tracing/events/ext4/ext4_sync_file_enter/enable" },
+        { REQ,      "/sys/kernel/debug/tracing/events/ext4/ext4_sync_file_exit/enable" },
+        { REQ,      "/sys/kernel/debug/tracing/events/block/block_rq_issue/enable" },
+        { REQ,      "/sys/kernel/debug/tracing/events/block/block_rq_complete/enable" },
     } },
-    { "load",   "CPU Load",         0, {
-        { REQ,  "/sys/kernel/debug/tracing/events/cpufreq_interactive/enable" },
+    { "load",       "CPU Load",         0, {
+        { REQ,      "/sys/kernel/debug/tracing/events/cpufreq_interactive/enable" },
     } },
-    { "sync",   "Synchronization",  0, {
-        { REQ,  "/sys/kernel/debug/tracing/events/sync/enable" },
+    { "sync",       "Synchronization",  0, {
+        { REQ,      "/sys/kernel/debug/tracing/events/sync/enable" },
     } },
-    { "workq",  "Kernel Workqueues", 0, {
-        { REQ,  "/sys/kernel/debug/tracing/events/workqueue/enable" },
+    { "workq",      "Kernel Workqueues", 0, {
+        { REQ,      "/sys/kernel/debug/tracing/events/workqueue/enable" },
     } },
 };
 
@@ -116,6 +117,7 @@
 static bool g_compress = false;
 static bool g_nohup = false;
 static int g_initialSleepSecs = 0;
+static const char* g_kernelTraceFuncs = NULL;
 
 /* Global state */
 static bool g_traceAborted = false;
@@ -131,6 +133,30 @@
 static const char* k_tracingOverwriteEnablePath =
     "/sys/kernel/debug/tracing/options/overwrite";
 
+static const char* k_currentTracerPath =
+    "/sys/kernel/debug/tracing/current_tracer";
+
+static const char* k_printTgidPath =
+    "/sys/kernel/debug/tracing/options/print-tgid";
+
+static const char* k_funcgraphAbsTimePath =
+    "/sys/kernel/debug/tracing/options/funcgraph-abstime";
+
+static const char* k_funcgraphCpuPath =
+    "/sys/kernel/debug/tracing/options/funcgraph-cpu";
+
+static const char* k_funcgraphProcPath =
+    "/sys/kernel/debug/tracing/options/funcgraph-proc";
+
+static const char* k_funcgraphFlatPath =
+    "/sys/kernel/debug/tracing/options/funcgraph-flat";
+
+static const char* k_funcgraphDurationPath =
+    "/sys/kernel/debug/tracing/options/funcgraph-duration";
+
+static const char* k_ftraceFilterPath =
+    "/sys/kernel/debug/tracing/set_ftrace_filter";
+
 static const char* k_tracingOnPath =
     "/sys/kernel/debug/tracing/tracing_on";
 
@@ -147,10 +173,22 @@
     return access(filename, W_OK) != -1;
 }
 
-// Write a string to a file, returning true if the write was successful.
-static bool writeStr(const char* filename, const char* str)
+// Truncate a file.
+static bool truncateFile(const char* path)
 {
-    int fd = open(filename, O_WRONLY);
+    int err = truncate(path, 0);
+    if (err != 0) {
+        fprintf(stderr, "error truncating %s: %s (%d)\n", path,
+                strerror(errno), errno);
+        return false;
+    }
+
+    return true;
+}
+
+static bool _writeStr(const char* filename, const char* str, int flags)
+{
+    int fd = open(filename, flags);
     if (fd == -1) {
         fprintf(stderr, "error opening %s: %s (%d)\n", filename,
                 strerror(errno), errno);
@@ -170,6 +208,18 @@
     return ok;
 }
 
+// Write a string to a file, returning true if the write was successful.
+static bool writeStr(const char* filename, const char* str)
+{
+    return _writeStr(filename, str, O_WRONLY);
+}
+
+// Append a string to a file, returning true if the write was successful.
+static bool appendStr(const char* filename, const char* str)
+{
+    return _writeStr(filename, str, O_APPEND|O_WRONLY);
+}
+
 // Enable or disable a kernel option by writing a "1" or a "0" into a /sys
 // file.
 static bool setKernelOptionEnable(const char* filename, bool enable)
@@ -243,16 +293,7 @@
 // Clear the contents of the kernel trace.
 static bool clearTrace()
 {
-    int traceFD = creat(k_tracePath, 0);
-    if (traceFD == -1) {
-        fprintf(stderr, "error truncating %s: %s (%d)\n", k_tracePath,
-                strerror(errno), errno);
-        return false;
-    }
-
-    close(traceFD);
-
-    return true;
+    return truncateFile(k_tracePath);
 }
 
 // Set the size of the kernel's trace buffer in kilobytes.
@@ -274,6 +315,14 @@
     return writeStr(k_traceClockPath, enable ? "global" : "local");
 }
 
+static bool setPrintTgidEnableIfPresent(bool enable)
+{
+    if (fileExists(k_printTgidPath)) {
+        return setKernelOptionEnable(k_printTgidPath, enable);
+    }
+    return true;
+}
+
 // Poke all the binder-enabled processes in the system to get them to re-read
 // their system properties.
 static bool pokeBinderServices()
@@ -329,8 +378,90 @@
     return ok;
 }
 
-// Enable tracing in the kernel.
-static bool startTrace()
+// Verify that the comma separated list of functions are being traced by the
+// kernel.
+static bool verifyKernelTraceFuncs(const char* funcs)
+{
+    int fd = open(k_ftraceFilterPath, O_RDONLY);
+    if (fd == -1) {
+        fprintf(stderr, "error opening %s: %s (%d)\n", k_ftraceFilterPath,
+            strerror(errno), errno);
+        return false;
+    }
+
+    char buf[4097];
+    ssize_t n = read(fd, buf, 4096);
+    close(fd);
+    if (n == -1) {
+        fprintf(stderr, "error reading %s: %s (%d)\n", k_ftraceFilterPath,
+            strerror(errno), errno);
+        return false;
+    }
+
+    buf[n] = '\0';
+    String8 funcList = String8::format("\n%s", buf);
+
+    // Make sure that every function listed in funcs is in the list we just
+    // read from the kernel.
+    bool ok = true;
+    char* myFuncs = strdup(funcs);
+    char* func = strtok(myFuncs, ",");
+    while (func) {
+        String8 fancyFunc = String8::format("\n%s\n", func);
+        bool found = funcList.find(fancyFunc.string(), 0) >= 0;
+        if (!found || func[0] == '\0') {
+            fprintf(stderr, "error: \"%s\" is not a valid kernel function "
+                "to trace.\n", func);
+            ok = false;
+        }
+        func = strtok(NULL, ",");
+    }
+    free(myFuncs);
+
+    return ok;
+}
+
+// Set the comma separated list of functions that the kernel is to trace.
+static bool setKernelTraceFuncs(const char* funcs)
+{
+    bool ok = true;
+
+    if (funcs == NULL || funcs[0] == '\0') {
+        // Disable kernel function tracing.
+        ok &= writeStr(k_currentTracerPath, "nop");
+        if (fileExists(k_ftraceFilterPath)) {
+            ok &= truncateFile(k_ftraceFilterPath);
+        }
+    } else {
+        // Enable kernel function tracing.
+        ok &= writeStr(k_currentTracerPath, "function_graph");
+        ok &= setKernelOptionEnable(k_funcgraphAbsTimePath, true);
+        ok &= setKernelOptionEnable(k_funcgraphCpuPath, true);
+        ok &= setKernelOptionEnable(k_funcgraphProcPath, true);
+        ok &= setKernelOptionEnable(k_funcgraphFlatPath, true);
+
+        // Set the requested filter functions.
+        ok &= truncateFile(k_ftraceFilterPath);
+        char* myFuncs = strdup(funcs);
+        char* func = strtok(myFuncs, ",");
+        while (func) {
+            ok &= appendStr(k_ftraceFilterPath, func);
+            func = strtok(NULL, ",");
+        }
+        free(myFuncs);
+
+        // Verify that the set functions are being traced.
+        if (ok) {
+            ok &= verifyKernelTraceFuncs(funcs);
+        }
+    }
+
+    return ok;
+}
+
+// Set all the kernel tracing settings to the desired state for this trace
+// capture.
+static bool setUpTrace()
 {
     bool ok = true;
 
@@ -338,6 +469,8 @@
     ok &= setTraceOverwriteEnable(g_traceOverwrite);
     ok &= setTraceBufferSizeKB(g_traceBufferSizeKB);
     ok &= setGlobalClockEnable(true);
+    ok &= setPrintTgidEnableIfPresent(true);
+    ok &= setKernelTraceFuncs(g_kernelTraceFuncs);
 
     // Set up the tags property.
     uint64_t tags = 0;
@@ -372,18 +505,12 @@
         }
     }
 
-    // Enable tracing.
-    ok &= setTracingEnabled(true);
-
     return ok;
 }
 
-// Disable tracing in the kernel.
-static void stopTrace()
+// Reset all the kernel tracing settings to their default state.
+static void cleanUpTrace()
 {
-    // Disable tracing.
-    setTracingEnabled(false);
-
     // Disable all tracing that we're able to.
     disableKernelTraceEvents();
 
@@ -392,10 +519,23 @@
 
     // Set the options back to their defaults.
     setTraceOverwriteEnable(true);
+    setTraceBufferSizeKB(1);
     setGlobalClockEnable(false);
+    setPrintTgidEnableIfPresent(false);
+    setKernelTraceFuncs(NULL);
+}
 
-    // Note that we can't reset the trace buffer size here because that would
-    // clear the trace before we've read it.
+
+// Enable tracing in the kernel.
+static bool startTrace()
+{
+    return setTracingEnabled(true);
+}
+
+// Disable tracing in the kernel.
+static void stopTrace()
+{
+    setTracingEnabled(false);
 }
 
 // Read the current kernel trace and write it to stdout.
@@ -555,6 +695,7 @@
     fprintf(stderr, "options include:\n"
                     "  -b N            use a trace buffer size of N KB\n"
                     "  -c              trace into a circular buffer\n"
+                    "  -k fname,...    trace the listed kernel functions\n"
                     "  -n              ignore signals\n"
                     "  -s N            sleep for N seconds before tracing [default 0]\n"
                     "  -t N            trace for N seconds [defualt 5]\n"
@@ -591,7 +732,7 @@
             {           0,                0, 0,  0 }
         };
 
-        ret = getopt_long(argc, argv, "b:cns:t:z",
+        ret = getopt_long(argc, argv, "b:ck:ns:t:z",
                           long_options, &option_index);
 
         if (ret < 0) {
@@ -613,6 +754,10 @@
                 g_traceOverwrite = true;
             break;
 
+            case 'k':
+                g_kernelTraceFuncs = optarg;
+                break;
+
             case 'n':
                 g_nohup = true;
                 break;
@@ -662,7 +807,9 @@
         sleep(g_initialSleepSecs);
     }
 
-    bool ok = startTrace();
+    bool ok = true;
+    ok &= setUpTrace();
+    ok &= startTrace();
 
     if (ok && traceStart) {
         printf("capturing trace...");
@@ -708,7 +855,7 @@
 
     // Reset the trace buffer size to 1.
     if (traceStop)
-        setTraceBufferSizeKB(1);
+        cleanUpTrace();
 
     return g_traceAborted ? 1 : 0;
 }
diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c
index 9a1839d..a18c00d 100644
--- a/cmds/dumpstate/dumpstate.c
+++ b/cmds/dumpstate/dumpstate.c
@@ -101,6 +101,12 @@
 
     run_command("LIST OF OPEN FILES", 10, SU_PATH, "root", "lsof", NULL);
 
+    if (screenshot_path[0]) {
+        ALOGI("taking screenshot\n");
+        run_command(NULL, 10, "/system/bin/screencap", "-p", screenshot_path, NULL);
+        ALOGI("wrote screenshot: %s\n", screenshot_path);
+    }
+
     for_each_pid(do_showmap, "SMAPS OF ALL PROCESSES");
     for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
 
@@ -159,12 +165,6 @@
     dump_file("LAST PANIC CONSOLE", "/data/dontpanic/apanic_console");
     dump_file("LAST PANIC THREADS", "/data/dontpanic/apanic_threads");
 
-    if (screenshot_path[0]) {
-        ALOGI("taking screenshot\n");
-        run_command(NULL, 5, SU_PATH, "root", "screenshot", screenshot_path, NULL);
-        ALOGI("wrote screenshot: %s\n", screenshot_path);
-    }
-
     run_command("SYSTEM SETTINGS", 20, SU_PATH, "root", "sqlite3",
             "/data/data/com.android.providers.settings/databases/settings.db",
             "pragma user_version; select * from system; select * from secure; select * from global;", NULL);
@@ -311,6 +311,7 @@
             "  -b: play sound file instead of vibrate, at beginning of job\n"
             "  -e: play sound file instead of vibrate, at end of job\n"
             "  -q: disable vibrate\n"
+            "  -B: send broadcast when finished (requires -o and -p)\n"
 		);
 }
 
@@ -323,6 +324,7 @@
     char* end_sound = 0;
     int use_socket = 0;
     int do_fb = 0;
+    int do_broadcast = 0;
 
     if (getuid() != 0) {
         // Old versions of the adb client would call the
@@ -348,7 +350,7 @@
     dump_traces_path = dump_traces();
 
     int c;
-    while ((c = getopt(argc, argv, "b:de:ho:svqzp")) != -1) {
+    while ((c = getopt(argc, argv, "b:de:ho:svqzpB")) != -1) {
         switch (c) {
             case 'b': begin_sound = optarg;  break;
             case 'd': do_add_date = 1;       break;
@@ -359,6 +361,7 @@
             case 'q': do_vibrate = 0;        break;
             case 'z': do_compress = 6;       break;
             case 'p': do_fb = 1;             break;
+            case 'B': do_broadcast = 1;      break;
             case '?': printf("\n");
             case 'h':
                 usage();
@@ -474,6 +477,14 @@
         fprintf(stderr, "rename(%s, %s): %s\n", tmp_path, path, strerror(errno));
     }
 
+    if (do_broadcast && use_outfile && do_fb) {
+        run_command(NULL, 5, "/system/bin/am", "broadcast",
+                "-a", "android.intent.action.BUGREPORT_FINISHED",
+                "--es", "android.intent.extra.BUGREPORT", path,
+                "--es", "android.intent.extra.SCREENSHOT", screenshot_path,
+                "--receiver-permission", "android.permission.DUMP", NULL);
+    }
+
     ALOGI("done\n");
 
     return 0;
diff --git a/cmds/dumpstate/utils.c b/cmds/dumpstate/utils.c
index fd390f5..9b0013e 100644
--- a/cmds/dumpstate/utils.c
+++ b/cmds/dumpstate/utils.c
@@ -31,6 +31,7 @@
 #include <sys/klog.h>
 #include <time.h>
 #include <unistd.h>
+#include <sys/prctl.h>
 
 #include <cutils/debugger.h>
 #include <cutils/properties.h>
@@ -264,6 +265,9 @@
         const char *args[1024] = {command};
         size_t arg;
 
+        /* make sure the child dies when dumpstate dies */
+        prctl(PR_SET_PDEATHSIG, SIGKILL);
+
         va_list ap;
         va_start(ap, command);
         if (title) printf("------ %s (%s", title, command);
@@ -375,7 +379,7 @@
         chp = strchr(chp, '/');
         if (chp) {
             *chp = 0;
-            mkdir(path, 0775);  /* drwxrwxr-x */
+            mkdir(path, 0770);  /* drwxrwx--- */
             *chp++ = '/';
         }
     }
diff --git a/cmds/surfaceflinger/main_surfaceflinger.cpp b/cmds/surfaceflinger/main_surfaceflinger.cpp
index 28e58e4..ce7fde0 100644
--- a/cmds/surfaceflinger/main_surfaceflinger.cpp
+++ b/cmds/surfaceflinger/main_surfaceflinger.cpp
@@ -20,9 +20,9 @@
 using namespace android;
 
 int main(int argc, char** argv) {
-    SurfaceFlinger::publishAndJoinThreadPool(true);
     // When SF is launched in its own process, limit the number of
     // binder threads to 4.
     ProcessState::self()->setThreadPoolMaxThreadCount(4);
+    SurfaceFlinger::publishAndJoinThreadPool(true);
     return 0;
 }
diff --git a/include/android/input.h b/include/android/input.h
index f2befa9e..c8ac938 100644
--- a/include/android/input.h
+++ b/include/android/input.h
@@ -428,6 +428,7 @@
 enum {
     AINPUT_SOURCE_CLASS_MASK = 0x000000ff,
 
+    AINPUT_SOURCE_CLASS_NONE = 0x00000000,
     AINPUT_SOURCE_CLASS_BUTTON = 0x00000001,
     AINPUT_SOURCE_CLASS_POINTER = 0x00000002,
     AINPUT_SOURCE_CLASS_NAVIGATION = 0x00000004,
@@ -446,6 +447,7 @@
     AINPUT_SOURCE_STYLUS = 0x00004000 | AINPUT_SOURCE_CLASS_POINTER,
     AINPUT_SOURCE_TRACKBALL = 0x00010000 | AINPUT_SOURCE_CLASS_NAVIGATION,
     AINPUT_SOURCE_TOUCHPAD = 0x00100000 | AINPUT_SOURCE_CLASS_POSITION,
+    AINPUT_SOURCE_TOUCH_NAVIGATION = 0x00200000 | AINPUT_SOURCE_CLASS_NONE,
     AINPUT_SOURCE_JOYSTICK = 0x01000000 | AINPUT_SOURCE_CLASS_JOYSTICK,
 
     AINPUT_SOURCE_ANY = 0xffffff00,
diff --git a/include/binder/BinderService.h b/include/binder/BinderService.h
index 6460268..5ac36d9 100644
--- a/include/binder/BinderService.h
+++ b/include/binder/BinderService.h
@@ -36,13 +36,18 @@
 public:
     static status_t publish(bool allowIsolated = false) {
         sp<IServiceManager> sm(defaultServiceManager());
-        return sm->addService(String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated);
+        return sm->addService(
+                String16(SERVICE::getServiceName()),
+                new SERVICE(), allowIsolated);
     }
 
     static void publishAndJoinThreadPool(bool allowIsolated = false) {
         sp<IServiceManager> sm(defaultServiceManager());
-        sm->addService(String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated);
+        sm->addService(
+                String16(SERVICE::getServiceName()),
+                new SERVICE(), allowIsolated);
         ProcessState::self()->startThreadPool();
+        ProcessState::self()->giveThreadPoolName();
         IPCThreadState::self()->joinThreadPool();
     }
 
diff --git a/include/binder/ProcessState.h b/include/binder/ProcessState.h
index 8caf1af..e63a0d0 100644
--- a/include/binder/ProcessState.h
+++ b/include/binder/ProcessState.h
@@ -71,6 +71,7 @@
             void                spawnPooledThread(bool isMain);
             
             status_t            setThreadPoolMaxThreadCount(size_t maxThreads);
+            void                giveThreadPoolName();
 
 private:
     friend class IPCThreadState;
@@ -80,6 +81,7 @@
 
                                 ProcessState(const ProcessState& o);
             ProcessState&       operator=(const ProcessState& o);
+            String8             makeBinderThreadName();
             
             struct handle_entry {
                 IBinder* binder;
diff --git a/include/gui/BufferQueue.h b/include/gui/BufferQueue.h
index c59e00e..6a86db6 100644
--- a/include/gui/BufferQueue.h
+++ b/include/gui/BufferQueue.h
@@ -128,7 +128,7 @@
     // GL_MAX_VIEWPORT_DIMS and GL_MAX_TEXTURE_SIZE (see: glGetIntegerv).
     // An error due to invalid dimensions might not be reported until
     // updateTexImage() is called.
-    virtual status_t dequeueBuffer(int *buf, sp<Fence>& fence,
+    virtual status_t dequeueBuffer(int *buf, sp<Fence>* fence,
             uint32_t width, uint32_t height, uint32_t format, uint32_t usage);
 
     // queueBuffer returns a filled buffer to the BufferQueue. In addition, a
@@ -139,7 +139,7 @@
     virtual status_t queueBuffer(int buf,
             const QueueBufferInput& input, QueueBufferOutput* output);
 
-    virtual void cancelBuffer(int buf, sp<Fence> fence);
+    virtual void cancelBuffer(int buf, const sp<Fence>& fence);
 
     // setSynchronousMode set whether dequeueBuffer is synchronous or
     // asynchronous. In synchronous mode, dequeueBuffer blocks until
diff --git a/include/gui/ConsumerBase.h b/include/gui/ConsumerBase.h
index 49a764f..78a3608 100644
--- a/include/gui/ConsumerBase.h
+++ b/include/gui/ConsumerBase.h
@@ -69,10 +69,9 @@
     // ConsumerBase is connected.
     sp<BufferQueue> getBufferQueue() const;
 
-    // dump writes the current state to a string.  These methods should NOT be
-    // overridden by child classes.  Instead they should override the
-    // dumpLocked method, which is called by these methods after locking the
-    // mutex.
+    // dump writes the current state to a string. Child classes should add
+    // 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;
 
diff --git a/include/gui/IGraphicBufferProducer.h b/include/gui/IGraphicBufferProducer.h
index a3e258d..29c7ff3 100644
--- a/include/gui/IGraphicBufferProducer.h
+++ b/include/gui/IGraphicBufferProducer.h
@@ -84,7 +84,7 @@
     // the buffer. The contents of the buffer must not be overwritten until the
     // fence signals. If the fence is NULL, the buffer may be written
     // immediately.
-    virtual status_t dequeueBuffer(int *slot, sp<Fence>& fence,
+    virtual status_t dequeueBuffer(int *slot, sp<Fence>* fence,
             uint32_t w, uint32_t h, uint32_t format, uint32_t usage) = 0;
 
     // queueBuffer indicates that the client has finished filling in the
@@ -165,7 +165,7 @@
     // cancelBuffer indicates that the client does not wish to fill in the
     // buffer associated with slot and transfers ownership of the slot back to
     // the server.
-    virtual void cancelBuffer(int slot, sp<Fence> fence) = 0;
+    virtual void cancelBuffer(int slot, const sp<Fence>& fence) = 0;
 
     // query retrieves some information for this surface
     // 'what' tokens allowed are that of android_natives.h
diff --git a/include/gui/ISurface.h b/include/gui/ISurface.h
deleted file mode 100644
index 5a928f2..0000000
--- a/include/gui/ISurface.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2007 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_GUI_ISURFACE_H
-#define ANDROID_GUI_ISURFACE_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <utils/Errors.h>
-#include <utils/RefBase.h>
-
-#include <binder/IInterface.h>
-
-#include <ui/PixelFormat.h>
-
-namespace android {
-
-class IGraphicBufferProducer;
-
-class ISurface : public IInterface
-{
-protected:
-    enum {
-        GET_SURFACE_TEXTURE = IBinder::FIRST_CALL_TRANSACTION,
-    };
-
-public: 
-    DECLARE_META_INTERFACE(Surface);
-
-    virtual sp<IGraphicBufferProducer> getSurfaceTexture() const = 0;
-};
-
-// ----------------------------------------------------------------------------
-
-class BnSurface : public BnInterface<ISurface>
-{
-public:
-    virtual status_t    onTransact( uint32_t code,
-                                    const Parcel& data,
-                                    Parcel* reply,
-                                    uint32_t flags = 0);
-};
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
-
-#endif // ANDROID_GUI_ISURFACE_H
diff --git a/include/gui/ISurfaceComposer.h b/include/gui/ISurfaceComposer.h
index 4862949..9018b87 100644
--- a/include/gui/ISurfaceComposer.h
+++ b/include/gui/ISurfaceComposer.h
@@ -95,24 +95,28 @@
     virtual bool authenticateSurfaceTexture(
             const sp<IGraphicBufferProducer>& surface) const = 0;
 
-    /* Capture the specified screen. requires READ_FRAME_BUFFER permission
-     * This function will fail if there is a secure window on screen.
+    /* triggers screen off and waits for it to complete
+     * requires ACCESS_SURFACE_FLINGER permission.
      */
-    virtual status_t captureScreen(const sp<IBinder>& display, sp<IMemoryHeap>* heap,
-            uint32_t* width, uint32_t* height, PixelFormat* format,
-            uint32_t reqWidth, uint32_t reqHeight,
-            uint32_t minLayerZ, uint32_t maxLayerZ) = 0;
-
-
-    /* triggers screen off and waits for it to complete */
     virtual void blank(const sp<IBinder>& display) = 0;
 
-    /* triggers screen on and waits for it to complete */
+    /* triggers screen on and waits for it to complete
+     * requires ACCESS_SURFACE_FLINGER permission.
+     */
     virtual void unblank(const sp<IBinder>& display) = 0;
 
     /* returns information about a display
      * intended to be used to get information about built-in displays */
     virtual status_t getDisplayInfo(const sp<IBinder>& display, DisplayInfo* info) = 0;
+
+    /* Capture the specified screen. requires READ_FRAME_BUFFER permission
+     * This function will fail if there is a secure window on screen.
+     */
+    virtual status_t captureScreen(const sp<IBinder>& display,
+            const sp<IGraphicBufferProducer>& producer,
+            uint32_t reqWidth, uint32_t reqHeight,
+            uint32_t minLayerZ, uint32_t maxLayerZ,
+            bool isCpuConsumer) = 0;
 };
 
 // ----------------------------------------------------------------------------
@@ -130,11 +134,11 @@
         GET_BUILT_IN_DISPLAY,
         SET_TRANSACTION_STATE,
         AUTHENTICATE_SURFACE,
-        CAPTURE_SCREEN,
         BLANK,
         UNBLANK,
         GET_DISPLAY_INFO,
         CONNECT_DISPLAY,
+        CAPTURE_SCREEN,
     };
 
     virtual status_t onTransact(uint32_t code, const Parcel& data,
diff --git a/include/gui/ISurfaceComposerClient.h b/include/gui/ISurfaceComposerClient.h
index 23d1d4c..cb9816f 100644
--- a/include/gui/ISurfaceComposerClient.h
+++ b/include/gui/ISurfaceComposerClient.h
@@ -27,11 +27,11 @@
 
 #include <ui/PixelFormat.h>
 
-#include <gui/ISurface.h>
-
 namespace android {
 // ----------------------------------------------------------------------------
 
+class IGraphicBufferProducer;
+
 class ISurfaceComposerClient : public IInterface
 {
 public:
@@ -48,18 +48,18 @@
         eProtectedByDRM     = 0x00001000,
 
         eFXSurfaceNormal    = 0x00000000,
-        eFXSurfaceBlur      = 0x00010000, // deprecated, same as Dim
         eFXSurfaceDim       = 0x00020000,
-        eFXSurfaceScreenshot= 0x00030000,
         eFXSurfaceMask      = 0x000F0000,
     };
 
     /*
      * Requires ACCESS_SURFACE_FLINGER permission
      */
-    virtual sp<ISurface> createSurface(
+    virtual status_t createSurface(
             const String8& name, uint32_t w, uint32_t h,
-            PixelFormat format, uint32_t flags) = 0;
+            PixelFormat format, uint32_t flags,
+            sp<IBinder>* handle,
+            sp<IGraphicBufferProducer>* gbp) = 0;
 
     /*
      * Requires ACCESS_SURFACE_FLINGER permission
diff --git a/include/gui/Surface.h b/include/gui/Surface.h
index 18e57ed..c25847c 100644
--- a/include/gui/Surface.h
+++ b/include/gui/Surface.h
@@ -76,24 +76,13 @@
         return surface != NULL && surface->getIGraphicBufferProducer() != NULL;
     }
 
-    /* writes the given Surface into a Parcel */
-    static status_t writeToParcel(const sp<Surface>& surface, Parcel* parcel);
-
-    /* constructs a Surface from a Parcel. see Surface::writeToParcel()
-     * and SurfaceControl::writeToParcel() */
-    static sp<Surface> readFromParcel(const Parcel& data);
-
-
 protected:
-    Surface();
     virtual ~Surface();
-    void setIGraphicBufferProducer(const sp<IGraphicBufferProducer>& bufferProducer);
 
 private:
     // can't be copied
     Surface& operator = (const Surface& rhs);
     Surface(const Surface& rhs);
-    void init();
 
     // ANativeWindow hooks
     static int hook_cancelBuffer(ANativeWindow* window,
diff --git a/include/gui/SurfaceComposerClient.h b/include/gui/SurfaceComposerClient.h
index 9e4d6fc..23655c7 100644
--- a/include/gui/SurfaceComposerClient.h
+++ b/include/gui/SurfaceComposerClient.h
@@ -30,6 +30,7 @@
 
 #include <ui/PixelFormat.h>
 
+#include <gui/CpuConsumer.h>
 #include <gui/SurfaceControl.h>
 
 namespace android {
@@ -38,7 +39,6 @@
 
 class DisplayInfo;
 class Composer;
-class IMemoryHeap;
 class ISurfaceComposerClient;
 class IGraphicBufferProducer;
 class Region;
@@ -156,10 +156,18 @@
 
 class ScreenshotClient
 {
-    sp<IMemoryHeap> mHeap;
-    uint32_t mWidth;
-    uint32_t mHeight;
-    PixelFormat mFormat;
+public:
+    static status_t capture(
+            const sp<IBinder>& display,
+            const sp<IGraphicBufferProducer>& producer,
+            uint32_t reqWidth, uint32_t reqHeight,
+            uint32_t minLayerZ, uint32_t maxLayerZ);
+
+private:
+    mutable sp<CpuConsumer> mCpuConsumer;
+    CpuConsumer::LockedBuffer mBuffer;
+    bool mHaveBuffer;
+
 public:
     ScreenshotClient();
 
@@ -171,6 +179,8 @@
             uint32_t reqWidth, uint32_t reqHeight,
             uint32_t minLayerZ, uint32_t maxLayerZ);
 
+    sp<CpuConsumer> getCpuConsumer() const;
+
     // release memory occupied by the screenshot
     void release();
 
diff --git a/include/gui/SurfaceControl.h b/include/gui/SurfaceControl.h
index f70888d..f27754c 100644
--- a/include/gui/SurfaceControl.h
+++ b/include/gui/SurfaceControl.h
@@ -27,7 +27,6 @@
 #include <ui/PixelFormat.h>
 #include <ui/Region.h>
 
-#include <gui/ISurface.h>
 #include <gui/ISurfaceComposerClient.h>
 
 namespace android {
@@ -46,9 +45,11 @@
     static bool isValid(const sp<SurfaceControl>& surface) {
         return (surface != 0) && surface->isValid();
     }
+
     bool isValid() {
-        return mSurface!=0 && mClient!=0;
+        return mHandle!=0 && mClient!=0;
     }
+
     static bool isSameSurface(
             const sp<SurfaceControl>& lhs, const sp<SurfaceControl>& rhs);
         
@@ -57,7 +58,7 @@
     
     status_t    setLayerStack(int32_t layerStack);
     status_t    setLayer(int32_t layer);
-    status_t    setPosition(int32_t x, int32_t y);
+    status_t    setPosition(float x, float y);
     status_t    setSize(uint32_t w, uint32_t h);
     status_t    hide();
     status_t    show();
@@ -82,7 +83,8 @@
 
     SurfaceControl(
             const sp<SurfaceComposerClient>& client,
-            const sp<ISurface>& surface);
+            const sp<IBinder>& handle,
+            const sp<IGraphicBufferProducer>& gbp);
 
     ~SurfaceControl();
 
@@ -90,7 +92,7 @@
     void destroy();
     
     sp<SurfaceComposerClient>   mClient;
-    sp<IBinder>                 mSurface;
+    sp<IBinder>                 mHandle;
     sp<IGraphicBufferProducer>  mGraphicBufferProducer;
     mutable Mutex               mLock;
     mutable sp<Surface>         mSurfaceData;
diff --git a/include/media/drm/DrmAPI.h b/include/media/drm/DrmAPI.h
new file mode 100644
index 0000000..77da0bf
--- /dev/null
+++ b/include/media/drm/DrmAPI.h
@@ -0,0 +1,205 @@
+ /*
+ * Copyright (C) 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 DRM_API_H_
+#define DRM_API_H_
+
+#include <utils/List.h>
+#include <utils/String8.h>
+#include <utils/Vector.h>
+#include <utils/KeyedVector.h>
+#include <utils/RefBase.h>
+#include <media/stagefright/foundation/ABase.h>
+
+//  Loadable DrmEngine shared libraries should define the entry points
+//  createDrmFactory and createCryptoFactory as shown below:
+//
+//  extern "C" {
+//      extern android::DrmFactory *createDrmFactory();
+//      extern android::CryptoFactory *createCryptoFactory();
+//  }
+
+namespace android {
+
+    struct DrmPlugin;
+
+    // DRMs are implemented in DrmEngine plugins, which are dynamically
+    // loadable shared libraries that implement the entry points
+    // createDrmFactory and createCryptoFactory.  createDrmFactory
+    // constructs and returns an instance of a DrmFactory object.  Similarly,
+    // createCryptoFactory creates an instance of a CryptoFactory object.
+    // When a MediaCrypto or MediaDrm object needs to be constructed, all
+    // available DrmEngines present in the plugins directory on the device
+    // are scanned for a matching DrmEngine that can support the crypto
+    // scheme.  When a match is found, the DrmEngine's createCryptoPlugin and
+    // createDrmPlugin methods are used to create CryptoPlugin or
+    // DrmPlugin instances to support that DRM scheme.
+
+    class DrmFactory {
+    public:
+        DrmFactory() {}
+        virtual ~DrmFactory() {}
+
+        // DrmFactory::isCryptoSchemeSupported can be called to determine
+        // if the plugin factory is able to construct plugins that support a
+        // given crypto scheme, which is specified by a UUID.
+        virtual bool isCryptoSchemeSupported(const uint8_t uuid[16]) = 0;
+
+        // Construct a DrmPlugin for the crypto scheme specified by UUID.
+        virtual status_t createDrmPlugin(
+                const uint8_t uuid[16], DrmPlugin **plugin) = 0;
+
+    private:
+        DrmFactory(const DrmFactory &);
+        DrmFactory &operator=(const DrmFactory &);
+    };
+
+    class DrmPlugin {
+    public:
+        enum EventType {
+            kDrmPluginEventProvisionRequired,
+            kDrmPluginEventLicenseNeeded,
+            kDrmPluginEventLicenseExpired,
+            kDrmPluginEventVendorDefined
+        };
+
+        // A license can be for offline content or for online streaming.
+        // Offline licenses are persisted on the device and may be used when the device
+        // is disconnected from the network.
+        enum LicenseType {
+            kLicenseType_Offline,
+            kLicenseType_Streaming
+        };
+
+        DrmPlugin() {}
+        virtual ~DrmPlugin() {}
+
+        // Open a new session with the DrmPlugin object.  A session ID is returned
+        // in the sessionId parameter.
+        virtual status_t openSession(Vector<uint8_t> &sessionId) = 0;
+
+        // Close a session on the DrmPlugin object.
+        virtual status_t closeSession(Vector<uint8_t> const &sessionId) = 0;
+
+        // A license request/response exchange occurs between the app and a License
+        // Server to obtain the keys required to decrypt the content.  getLicenseRequest()
+        // is used to obtain an opaque license request blob that is delivered to the
+        // license server.
+        //
+        // The init data passed to getLicenseRequest is container-specific and its
+        // meaning is interpreted based on the mime type provided in the mimeType
+        // parameter to getLicenseRequest.  It could contain, for example, the content
+        // ID, key ID or other data obtained from the content metadata that is required
+        // in generating the license request.
+        //
+        // licenseType specifes if the license is for streaming or offline content
+        //
+        // optionalParameters are included in the license server request message to
+        // allow a client application to provide additional message parameters to the
+        // server.
+        //
+        // If successful, the opaque license request blob is returned to the caller.
+        virtual status_t
+            getLicenseRequest(Vector<uint8_t> const &sessionId,
+                              Vector<uint8_t> const &initData,
+                              String8 const &mimeType, LicenseType licenseType,
+                              KeyedVector<String8, String8> const &optionalParameters,
+                              Vector<uint8_t> &request, String8 &defaultUrl) = 0;
+
+        // After a license response is received by the app, it is provided to the
+        // Drm plugin using provideLicenseResponse.
+        virtual status_t provideLicenseResponse(Vector<uint8_t> const &sessionId,
+                                                Vector<uint8_t> const &response) = 0;
+
+        // Remove the keys associated with a license.
+        virtual status_t removeLicense(Vector<uint8_t> const &sessionId) = 0;
+
+        // Request an informative description of the license for the session.  The status
+        // is in the form of {name, value} pairs.  Since DRM license policies vary by
+        // vendor, the specific status field names are determined by each DRM vendor.
+        // Refer to your DRM provider documentation for definitions of the field names
+        // for a particular DrmEngine.
+        virtual status_t
+            queryLicenseStatus(Vector<uint8_t> const &sessionId,
+                               KeyedVector<String8, String8> &infoMap) const = 0;
+
+        // A provision request/response exchange occurs between the app and a
+        // provisioning server to retrieve a device certificate.  getProvisionRequest
+        // is used to obtain an opaque license request blob that is delivered to the
+        // provisioning server.
+        //
+        // If successful, the opaque provision request blob is returned to the caller.
+        virtual status_t getProvisionRequest(Vector<uint8_t> &request,
+                                             String8 &defaultUrl) = 0;
+
+        // After a provision response is received by the app, it is provided to the
+        // Drm plugin using provideProvisionResponse.
+        virtual status_t provideProvisionResponse(Vector<uint8_t> const &response) = 0;
+
+        // A means of enforcing the contractual requirement for a concurrent stream
+        // limit per subscriber across devices is provided via SecureStop.  SecureStop
+        // is a means of securely monitoring the lifetime of sessions. Since playback
+        // on a device can be interrupted due to reboot, power failure, etc. a means
+        // of persisting the lifetime information on the device is needed.
+        //
+        // A signed version of the sessionID is written to persistent storage on the
+        // device when each MediaCrypto object is created. The sessionID is signed by
+        // the device private key to prevent tampering.
+        //
+        // In the normal case, playback will be completed, the session destroyed and
+        // the Secure Stops will be queried. The App queries secure stops and forwards
+        // the secure stop message to the server which verifies the signature and
+        // notifies the server side database that the session destruction has been
+        // confirmed. The persisted record on the client is only removed after positive
+        // confirmation that the server received the message using releaseSecureStops().
+        virtual status_t getSecureStops(List<Vector<uint8_t> > &secureStops) = 0;
+        virtual status_t releaseSecureStops(Vector<uint8_t> const &ssRelease) = 0;
+
+        // Read a property value given the device property string.  There are a few forms
+        // of property access methods, depending on the data type returned.
+        // Since DRM plugin properties may vary, additional field names may be defined
+        // by each DRM vendor.  Refer to your DRM provider documentation for definitions
+        // of its additional field names.
+        //
+        // Standard values are:
+        //   "vendor" [string] identifies the maker of the plugin
+        //   "version" [string] identifies the version of the plugin
+        //   "description" [string] describes the plugin
+        //   'deviceUniqueId' [byte array] The device unique identifier is established
+        //   during device provisioning and provides a means of uniquely identifying
+        //   each device.
+        virtual status_t getPropertyString(String8 const &name, String8 &value ) const = 0;
+        virtual status_t getPropertyByteArray(String8 const &name,
+                                              Vector<uint8_t> &value ) const = 0;
+
+        // Write  a property value given the device property string.  There are a few forms
+        // of property setting methods, depending on the data type.
+        // Since DRM plugin properties may vary, additional field names may be defined
+        // by each DRM vendor.  Refer to your DRM provider documentation for definitions
+        // of its field names.
+        virtual status_t setPropertyString(String8 const &name,
+                                           String8 const &value ) = 0;
+        virtual status_t setPropertyByteArray(String8 const &name,
+                                              Vector<uint8_t> const &value ) = 0;
+
+        // TODO: provide way to send an event
+    private:
+        DISALLOW_EVIL_CONSTRUCTORS(DrmPlugin);
+    };
+
+}  // namespace android
+
+#endif // DRM_API_H_
diff --git a/include/media/drm/DrmClientAPI.h b/include/media/drm/DrmClientAPI.h
deleted file mode 100644
index 6a08933..0000000
--- a/include/media/drm/DrmClientAPI.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (C) 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.
- * 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 DRM_CLIENT_API_H_
-#define DRM_CLIENT_API_H_
-
-#include <utils/String8.h>
-#include <utils/Vector.h>
-#include <utils/List.h>
-#include <media/stagefright/foundation/ABase.h>
-
-namespace android {
-
-    // A DrmMessageStatus object aggregates a sessionId, which uniquely
-    // identifies a playback context with a status code and opaque message
-    // data.
-    struct DrmMessageStatus {
-        Vector<uint8_t> mSessionId;
-        status_t mStatus;
-        Vector<uint8_t> mData;
-    };
-
-    class DrmClientPlugin {
-    public:
-
-        // A license can be for downloaded, offline content or for online streaming
-        // Offline licenses are persisted on the device and may be used when the device
-        // is disconnected from the network.
-        enum LicenseType {
-            kLicenseType_Offline,
-            kLicenseType_Streaming
-        };
-
-        DrmClientPlugin() {}
-        virtual ~DrmClientPlugin() {}
-
-        // A license request/response exchange occurs between the app and a License
-        // Server to obtain the keys required to decrypt the content.  getLicenseRequest()
-        // is used to obtain an opaque license request blob that is delivered to the
-        // license server.
-        //
-        // The init data passed to getLicenseRequest is container-specific and its
-        // meaning is interpreted based on the mime type provided in the mimeType
-        // parameter to getLicenseRequest.  It could contain, for example, the content
-        // ID, key ID or other data obtained from the content metadata that is required
-        // in generating the license request.
-        //
-        // The DrmMessageStatus returned from getLicenseRequest contains a sessionId for
-        // the new session, a status code indicating whether the operation was successful
-        // and if so, the request blob is placed into the mData field.
-        virtual DrmMessageStatus getLicenseRequest(Vector<uint8_t> const &initData,
-                String8 const &mimeType, LicenseType licenseType) = 0;
-
-        // After a license response is received by the app, it is provided to the
-        // DrmClient plugin using provideLicenseResponse.  The response data is provided
-        // in the mData field of the response parameter.
-        virtual status_t provideLicenseResponse(DrmMessageStatus const &response) = 0;
-
-        // Remove the keys associated with a license and release the session
-        virtual status_t clearLicense(Vector<uint8_t> const &sessionId) = 0;
-
-        // A provision request/response exchange occurs between the app and a
-        // provisioning server to retrieve a device certificate.  getProvisionRequest
-        // is used to obtain an opaque license request blob that is delivered to the
-        // provisioning server.
-        //
-        // The DrmMessageStatus returned from getLicenseRequest contains a status code
-        // indicating whether the operation was successful and if so, the request blob
-        // is placed into the mData field.
-        virtual DrmMessageStatus getProvisionRequest() = 0;
-
-        // After a provision response is received by the app, it is provided to the
-        // DrmClient plugin using provideProvisionResponse.  The response data is
-        // provided in the mData field of the response parameter.
-        virtual status_t provideProvisionResponse(DrmMessageStatus const &response) = 0;
-
-        // A means of enforcing the contractual requirement for a concurrent stream
-        // limit per subscriber across devices is provided via SecureStop.  SecureStop
-        // is a means of securely monitoring the lifetime of sessions. Since playback
-        // on a device can be interrupted due to reboot, power failure, etc. a means
-        // of persisting the lifetime information on the device is needed.
-        //
-        // A signed version of the sessionID is written to persistent storage on the
-        // device when each MediaCrypto object is created. The sessionID is signed by
-        // the device private key to prevent tampering.
-        //
-        // In the normal case, playback will be completed, the session destroyed and
-        // the Secure Stops will be queried. The App queries secure stops and forwards
-        // the secure stop message to the server which verifies the signature and
-        // notifies the server side database that the session destruction has been
-        // confirmed. The persisted record on the client is only removed after positive
-        // confirmation that the server received the message using releaseSecureStops().
-        virtual List<DrmMessageStatus> getSecureStops() = 0;
-        virtual status_t releaseSecureStops(DrmMessageStatus const &ssRelease) = 0;
-
-        // Retrieve the device unique identifier for this device.  The device unique
-        // identifier is established during device provisioning.
-        virtual Vector<uint8_t> getDeviceUniqueId() const = 0;
-
-    private:
-        DISALLOW_EVIL_CONSTRUCTORS(DrmClientPlugin);
-    };
-
-}  // namespace android
-
-#endif // DRM_CLIENT_API_H_
diff --git a/include/media/drm/DrmEngineAPI.h b/include/media/drm/DrmEngineAPI.h
deleted file mode 100644
index 25bd34a..0000000
--- a/include/media/drm/DrmEngineAPI.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 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.
- * 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 DRM_ENGINE_API_H_
-#define DRM_ENGINE_API_H_
-
-#include <utils/Errors.h>
-#include <media/stagefright/foundation/ABase.h>
-
-
-namespace android {
-
-    class CryptoPlugin;
-    class DrmClientPlugin;
-
-     // DRMs are implemented in DrmEngine plugins, which are dynamically
-     // loadable shared libraries that implement the entry point
-     // createDrmPluginFactory.  createDrmPluginFactory constructs and returns
-     // an instance of a DrmPluginFactory object.  When a MediaCrypto or
-     // DrmClient object needs to be constructed, all available
-     // DrmEngines present in the plugins directory on the device are scanned
-     // for a matching DrmEngine that can support the crypto scheme.  When a
-     // match is found, the DrmEngine’s createCryptoPlugin or
-     // createDrmClientPlugin methods are used to create CryptoPlugin or
-     // DrmClientPlugin instances to support that DRM scheme.
-
-    class DrmPluginFactory {
-    public:
-        DrmPluginFactory() {}
-        virtual ~DrmPluginFactory() {}
-
-         // DrmPluginFactory::isCryptoSchemeSupported can be called to determine
-         // if the plugin factory is able to construct plugins that support a
-         // given crypto scheme, which is specified by a UUID.
-        virtual bool isCryptoSchemeSupported(const uint8_t uuid[16]) const = 0;
-
-        // Construct a CryptoPlugin for the crypto scheme specified by UUID.
-        // {data, size} provide scheme-specific initialization data.
-        virtual status_t createCryptoPlugin(
-                const uint8_t uuid[16], const void *data, size_t size,
-                CryptoPlugin **plugin) = 0;
-
-        // Construct a DrmClientPlugin for the crypto scheme specified by UUID.
-        // {data, size} provide scheme-specific initialization data.
-        virtual status_t createDrmClientPlugin(
-                const uint8_t uuid[16], const void *data, size_t size,
-                DrmClientPlugin **plugin) = 0;
-
-    private:
-        DISALLOW_EVIL_CONSTRUCTORS(DrmPluginFactory);
-    };
-
-}  // namespace android
-
- //  Loadable DrmEngine shared libraries should define the entry point
- //  createDrmPluginFactory as shown below:
- //
- //  extern "C" {
- //      extern android::DrmPluginFactory *createDrmPluginFactory();
- //  }
-
-#endif // DRM_ENGINE_API_H_
diff --git a/include/private/gui/LayerState.h b/include/private/gui/LayerState.h
index 0798e17..bf4bf03 100644
--- a/include/private/gui/LayerState.h
+++ b/include/private/gui/LayerState.h
@@ -24,7 +24,6 @@
 
 #include <ui/Region.h>
 #include <ui/Rect.h>
-#include <gui/ISurface.h>
 
 namespace android {
 
diff --git a/include/ui/GraphicBuffer.h b/include/ui/GraphicBuffer.h
index 4b9b5a8..ea9368d 100644
--- a/include/ui/GraphicBuffer.h
+++ b/include/ui/GraphicBuffer.h
@@ -24,6 +24,7 @@
 #include <ui/PixelFormat.h>
 #include <ui/Rect.h>
 #include <utils/Flattenable.h>
+#include <utils/RefBase.h>
 
 
 struct ANativeWindowBuffer;
@@ -37,10 +38,8 @@
 // ===========================================================================
 
 class GraphicBuffer
-    : public ANativeObjectBase<
-        ANativeWindowBuffer,
-        GraphicBuffer, 
-        LightRefBase<GraphicBuffer> >, public Flattenable
+    : public ANativeObjectBase< ANativeWindowBuffer, GraphicBuffer, RefBase >,
+      public Flattenable
 {
 public:
 
diff --git a/include/utils/AndroidThreads.h b/include/utils/AndroidThreads.h
index f67648f..4eee14d 100644
--- a/include/utils/AndroidThreads.h
+++ b/include/utils/AndroidThreads.h
@@ -56,6 +56,9 @@
                                      size_t threadStackSize,
                                      android_thread_id_t *threadId);
 
+// set the same of the running thread
+extern void androidSetThreadName(const char* name);
+
 // Used by the Java Runtime to control how threads are created, so that
 // they can be proper and lovely Java threads.
 typedef int (*android_create_thread_fn)(android_thread_func_t entryFunction,
diff --git a/include/utils/Condition.h b/include/utils/Condition.h
index 8852d53..e63ba7e 100644
--- a/include/utils/Condition.h
+++ b/include/utils/Condition.h
@@ -48,6 +48,11 @@
         SHARED = 1
     };
 
+    enum WakeUpType {
+        WAKE_UP_ONE = 0,
+        WAKE_UP_ALL = 1
+    };
+
     Condition();
     Condition(int type);
     ~Condition();
@@ -57,6 +62,14 @@
     status_t waitRelative(Mutex& mutex, nsecs_t reltime);
     // Signal the condition variable, allowing one thread to continue.
     void signal();
+    // Signal the condition variable, allowing one or all threads to continue.
+    void signal(WakeUpType type) {
+        if (type == WAKE_UP_ONE) {
+            signal();
+        } else {
+            broadcast();
+        }
+    }
     // Signal the condition variable, allowing all threads to continue.
     void broadcast();
 
diff --git a/include/utils/RefBase.h b/include/utils/RefBase.h
index 0a8e10a..033fe67 100644
--- a/include/utils/RefBase.h
+++ b/include/utils/RefBase.h
@@ -52,12 +52,16 @@
 }
 
 // ---------------------------------------------------------------------------
-class ReferenceMover;
-class ReferenceConverterBase {
+
+class ReferenceRenamer {
+protected:
+    // destructor is purposedly not virtual so we avoid code overhead from
+    // subclasses; we have to make it protected to guarantee that it
+    // cannot be called from this base class (and to make strict compilers
+    // happy).
+    ~ReferenceRenamer() { }
 public:
-    virtual size_t getReferenceTypeSize() const = 0;
-    virtual void* getReferenceBase(void const*) const = 0;
-    inline virtual ~ReferenceConverterBase() { }
+    virtual void operator()(size_t i) const = 0;
 };
 
 // ---------------------------------------------------------------------------
@@ -144,17 +148,23 @@
     virtual void            onLastWeakRef(const void* id);
 
 private:
-    friend class ReferenceMover;
-    static void moveReferences(void* d, void const* s, size_t n,
-            const ReferenceConverterBase& caster);
-
-private:
     friend class weakref_type;
     class weakref_impl;
     
                             RefBase(const RefBase& o);
             RefBase&        operator=(const RefBase& o);
 
+private:
+    friend class ReferenceMover;
+
+    static void renameRefs(size_t n, const ReferenceRenamer& renamer);
+
+    static void renameRefId(weakref_type* ref,
+            const void* old_id, const void* new_id);
+
+    static void renameRefId(RefBase* ref,
+            const void* old_id, const void* new_id);
+
         weakref_impl* const mRefs;
 };
 
@@ -185,8 +195,9 @@
 
 private:
     friend class ReferenceMover;
-    inline static void moveReferences(void* d, void const* s, size_t n,
-            const ReferenceConverterBase& caster) { }
+    inline static void renameRefs(size_t n, const ReferenceRenamer& renamer) { }
+    inline static void renameRefId(T* ref,
+            const void* old_id, const void* new_id) { }
 
 private:
     mutable volatile int32_t mCount;
@@ -455,42 +466,48 @@
 
 // this class just serves as a namespace so TYPE::moveReferences can stay
 // private.
-
 class ReferenceMover {
-    // StrongReferenceCast and WeakReferenceCast do the impedance matching
-    // between the generic (void*) implementation in Refbase and the strongly typed
-    // template specializations below.
-
-    template <typename TYPE>
-    struct StrongReferenceCast : public ReferenceConverterBase {
-        virtual size_t getReferenceTypeSize() const { return sizeof( sp<TYPE> ); }
-        virtual void* getReferenceBase(void const* p) const {
-            sp<TYPE> const* sptr(reinterpret_cast<sp<TYPE> const*>(p));
-            return static_cast<typename TYPE::basetype *>(sptr->get());
-        }
-    };
-
-    template <typename TYPE>
-    struct WeakReferenceCast : public ReferenceConverterBase {
-        virtual size_t getReferenceTypeSize() const { return sizeof( wp<TYPE> ); }
-        virtual void* getReferenceBase(void const* p) const {
-            wp<TYPE> const* sptr(reinterpret_cast<wp<TYPE> const*>(p));
-            return static_cast<typename TYPE::basetype *>(sptr->unsafe_get());
-        }
-    };
-
 public:
+    // it would be nice if we could make sure no extra code is generated
+    // for sp<TYPE> or wp<TYPE> when TYPE is a descendant of RefBase:
+    // Using a sp<RefBase> override doesn't work; it's a bit like we wanted
+    // a template<typename TYPE inherits RefBase> template...
+
     template<typename TYPE> static inline
     void move_references(sp<TYPE>* d, sp<TYPE> const* s, size_t n) {
+
+        class Renamer : public ReferenceRenamer {
+            sp<TYPE>* d;
+            sp<TYPE> const* s;
+            virtual void operator()(size_t i) const {
+                // The id are known to be the sp<>'s this pointer
+                TYPE::renameRefId(d[i].get(), &s[i], &d[i]);
+            }
+        public:
+            Renamer(sp<TYPE>* d, sp<TYPE> const* s) : s(s), d(d) { }
+        };
+
         memmove(d, s, n*sizeof(sp<TYPE>));
-        StrongReferenceCast<TYPE> caster;
-        TYPE::moveReferences(d, s, n, caster);
+        TYPE::renameRefs(n, Renamer(d, s));
     }
+
+
     template<typename TYPE> static inline
     void move_references(wp<TYPE>* d, wp<TYPE> const* s, size_t n) {
+
+        class Renamer : public ReferenceRenamer {
+            wp<TYPE>* d;
+            wp<TYPE> const* s;
+            virtual void operator()(size_t i) const {
+                // The id are known to be the wp<>'s this pointer
+                TYPE::renameRefId(d[i].get_refs(), &s[i], &d[i]);
+            }
+        public:
+            Renamer(wp<TYPE>* d, wp<TYPE> const* s) : s(s), d(d) { }
+        };
+
         memmove(d, s, n*sizeof(wp<TYPE>));
-        WeakReferenceCast<TYPE> caster;
-        TYPE::moveReferences(d, s, n, caster);
+        TYPE::renameRefs(n, Renamer(d, s));
     }
 };
 
diff --git a/include/utils/Thread.h b/include/utils/Thread.h
index 4a34abd..df30611 100644
--- a/include/utils/Thread.h
+++ b/include/utils/Thread.h
@@ -67,6 +67,9 @@
     // Do not call from this object's thread; will return WOULD_BLOCK in that case.
             status_t    join();
 
+    // Indicates whether this thread is running or not.
+            bool        isRunning() const;
+
 #ifdef HAVE_ANDROID_OS
     // Return the thread's kernel ID, same as the thread itself calling gettid() or
     // androidGetTid(), or -1 if the thread is not running.
diff --git a/include/utils/Vector.h b/include/utils/Vector.h
index f3020d6..ed7b725 100644
--- a/include/utils/Vector.h
+++ b/include/utils/Vector.h
@@ -80,7 +80,13 @@
     //! sets the capacity. capacity can never be reduced less than size()
     inline  ssize_t         setCapacity(size_t size)    { return VectorImpl::setCapacity(size); }
 
-    /*! 
+    /*!
+     * set the size of the vector. items are appended with the default
+     * constructor, or removed from the end as needed.
+     */
+    inline  ssize_t         resize(size_t size)         { return VectorImpl::resize(size); }
+
+    /*!
      * C-style array access
      */
      
diff --git a/include/utils/VectorImpl.h b/include/utils/VectorImpl.h
index c4ec2ff..9bc50e6 100644
--- a/include/utils/VectorImpl.h
+++ b/include/utils/VectorImpl.h
@@ -64,6 +64,7 @@
     inline  bool            isEmpty() const     { return mCount == 0; }
             size_t          capacity() const;
             ssize_t         setCapacity(size_t size);
+            ssize_t         resize(size_t size);
 
             /*! append/insert another vector or array */
             ssize_t         insertVectorAt(const VectorImpl& vector, size_t index);
diff --git a/libs/binder/MemoryBase.cpp b/libs/binder/MemoryBase.cpp
index 033066b..5c82330 100644
--- a/libs/binder/MemoryBase.cpp
+++ b/libs/binder/MemoryBase.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#define LOG_TAG "MemoryBase"
 
 #include <stdlib.h>
 #include <stdint.h>
@@ -44,3 +45,11 @@
 
 // ---------------------------------------------------------------------------
 }; // namespace android
+
+// Backwards compatibility for libdatabase_sqlcipher (http://b/8253769).
+extern "C" void _ZN7android10MemoryBaseC1ERKNS_2spINS_11IMemoryHeapEEEij(void*, void*, ssize_t, size_t);
+extern "C" void _ZN7android10MemoryBaseC1ERKNS_2spINS_11IMemoryHeapEEElj(void* obj, void* h, long o, unsigned int size) {
+    _ZN7android10MemoryBaseC1ERKNS_2spINS_11IMemoryHeapEEEij(obj, h, o, size);
+    ALOGW("Using temporary compatibility workaround for usage of MemoryBase "
+          "private API. Please fix your application!");
+}
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index d95fd6f..294e1d4 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -283,15 +283,20 @@
     }
 }
 
+String8 ProcessState::makeBinderThreadName() {
+    int32_t s = android_atomic_add(1, &mThreadPoolSeq);
+    String8 name;
+    name.appendFormat("Binder_%X", s);
+    return name;
+}
+
 void ProcessState::spawnPooledThread(bool isMain)
 {
     if (mThreadPoolStarted) {
-        int32_t s = android_atomic_add(1, &mThreadPoolSeq);
-        char buf[16];
-        snprintf(buf, sizeof(buf), "Binder_%X", s);
-        ALOGV("Spawning new pooled thread, name=%s\n", buf);
+        String8 name = makeBinderThreadName();
+        ALOGV("Spawning new pooled thread, name=%s\n", name.string());
         sp<Thread> t = new PoolThread(isMain);
-        t->run(buf);
+        t->run(name.string());
     }
 }
 
@@ -304,6 +309,10 @@
     return result;
 }
 
+void ProcessState::giveThreadPoolName() {
+    androidSetThreadName( makeBinderThreadName().string() );
+}
+
 static int open_driver()
 {
     int fd = open("/dev/binder", O_RDWR);
diff --git a/libs/gui/Android.mk b/libs/gui/Android.mk
index 544b664..5c7bb4c 100644
--- a/libs/gui/Android.mk
+++ b/libs/gui/Android.mk
@@ -17,7 +17,6 @@
 	IGraphicBufferProducer.cpp \
 	ISensorEventConnection.cpp \
 	ISensorServer.cpp \
-	ISurface.cpp \
 	ISurfaceComposer.cpp \
 	ISurfaceComposerClient.cpp \
 	LayerState.cpp \
diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp
index d93c067..75a0296 100644
--- a/libs/gui/BufferQueue.cpp
+++ b/libs/gui/BufferQueue.cpp
@@ -254,7 +254,7 @@
     return NO_ERROR;
 }
 
-status_t BufferQueue::dequeueBuffer(int *outBuf, sp<Fence>& outFence,
+status_t BufferQueue::dequeueBuffer(int *outBuf, sp<Fence>* outFence,
         uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
     ATRACE_CALL();
     ST_LOGV("dequeueBuffer: w=%d h=%d fmt=%#x usage=%#x", w, h, format, usage);
@@ -393,7 +393,7 @@
 
         dpy = mSlots[buf].mEglDisplay;
         eglFence = mSlots[buf].mEglFence;
-        outFence = mSlots[buf].mFence;
+        *outFence = mSlots[buf].mFence;
         mSlots[buf].mEglFence = EGL_NO_SYNC_KHR;
         mSlots[buf].mFence = Fence::NO_FENCE;
     }  // end lock scope
@@ -590,7 +590,7 @@
     return OK;
 }
 
-void BufferQueue::cancelBuffer(int buf, sp<Fence> fence) {
+void BufferQueue::cancelBuffer(int buf, const sp<Fence>& fence) {
     ATRACE_CALL();
     ST_LOGV("cancelBuffer: slot=%d", buf);
     Mutex::Autolock lock(mMutex);
@@ -995,7 +995,7 @@
 }
 
 status_t BufferQueue::drainQueueLocked() {
-    while (mSynchronousMode && !mQueue.isEmpty()) {
+    while (mSynchronousMode && mQueue.size() > 1) {
         mDequeueCondition.wait(mMutex);
         if (mAbandoned) {
             ST_LOGE("drainQueueLocked: BufferQueue has been abandoned!");
@@ -1012,7 +1012,7 @@
 status_t BufferQueue::drainQueueAndFreeBuffersLocked() {
     status_t err = drainQueueLocked();
     if (err == NO_ERROR) {
-        if (mSynchronousMode) {
+        if (mQueue.empty()) {
             freeAllBuffersLocked();
         } else {
             freeAllBuffersExceptHeadLocked();
diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp
index 54860d7..63d7628 100644
--- a/libs/gui/IGraphicBufferProducer.cpp
+++ b/libs/gui/IGraphicBufferProducer.cpp
@@ -81,7 +81,7 @@
         return result;
     }
 
-    virtual status_t dequeueBuffer(int *buf, sp<Fence>& fence,
+    virtual status_t dequeueBuffer(int *buf, sp<Fence>* fence,
             uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
         Parcel data, reply;
         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
@@ -99,8 +99,8 @@
             // If the fence was written by the callee, then overwrite the
             // caller's fence here.  If it wasn't written then don't touch the
             // caller's fence.
-            fence = new Fence();
-            reply.read(*fence.get());
+            *fence = new Fence();
+            reply.read(*(fence->get()));
         }
         result = reply.readInt32();
         return result;
@@ -121,7 +121,7 @@
         return result;
     }
 
-    virtual void cancelBuffer(int buf, sp<Fence> fence) {
+    virtual void cancelBuffer(int buf, const sp<Fence>& fence) {
         Parcel data, reply;
         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
         data.writeInt32(buf);
@@ -215,7 +215,7 @@
             uint32_t usage  = data.readInt32();
             int buf;
             sp<Fence> fence;
-            int result = dequeueBuffer(&buf, fence, w, h, format, usage);
+            int result = dequeueBuffer(&buf, &fence, w, h, format, usage);
             reply->writeInt32(buf);
             reply->writeInt32(fence != NULL);
             if (fence != NULL) {
diff --git a/libs/gui/ISurface.cpp b/libs/gui/ISurface.cpp
deleted file mode 100644
index 8c25f45..0000000
--- a/libs/gui/ISurface.cpp
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "ISurface"
-
-#include <stdio.h>
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <binder/Parcel.h>
-
-#include <gui/ISurface.h>
-#include <gui/IGraphicBufferProducer.h>
-
-namespace android {
-
-// ----------------------------------------------------------------------
-
-class BpSurface : public BpInterface<ISurface>
-{
-public:
-    BpSurface(const sp<IBinder>& impl)
-        : BpInterface<ISurface>(impl)
-    {
-    }
-
-    virtual sp<IGraphicBufferProducer> getSurfaceTexture() const {
-        Parcel data, reply;
-        data.writeInterfaceToken(ISurface::getInterfaceDescriptor());
-        remote()->transact(GET_SURFACE_TEXTURE, data, &reply);
-        return interface_cast<IGraphicBufferProducer>(reply.readStrongBinder());
-    }
-};
-
-IMPLEMENT_META_INTERFACE(Surface, "android.ui.ISurface");
-
-// ----------------------------------------------------------------------
-
-status_t BnSurface::onTransact(
-    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
-    switch(code) {
-        case GET_SURFACE_TEXTURE: {
-            CHECK_INTERFACE(ISurface, data, reply);
-            reply->writeStrongBinder( getSurfaceTexture()->asBinder() );
-            return NO_ERROR;
-        }
-        default:
-            return BBinder::onTransact(code, data, reply, flags);
-    }
-}
-
-}; // namespace android
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 72b6277..6442a86 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -102,24 +102,22 @@
         remote()->transact(BnSurfaceComposer::BOOT_FINISHED, data, &reply);
     }
 
-    virtual status_t captureScreen(
-            const sp<IBinder>& display, sp<IMemoryHeap>* heap,
-            uint32_t* width, uint32_t* height, PixelFormat* format,
+    virtual status_t captureScreen(const sp<IBinder>& display,
+            const sp<IGraphicBufferProducer>& producer,
             uint32_t reqWidth, uint32_t reqHeight,
-            uint32_t minLayerZ, uint32_t maxLayerZ)
+            uint32_t minLayerZ, uint32_t maxLayerZ,
+            bool isCpuConsumer)
     {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
         data.writeStrongBinder(display);
+        data.writeStrongBinder(producer->asBinder());
         data.writeInt32(reqWidth);
         data.writeInt32(reqHeight);
         data.writeInt32(minLayerZ);
         data.writeInt32(maxLayerZ);
+        data.writeInt32(isCpuConsumer);
         remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN, data, &reply);
-        *heap = interface_cast<IMemoryHeap>(reply.readStrongBinder());
-        *width = reply.readInt32();
-        *height = reply.readInt32();
-        *format = reply.readInt32();
         return reply.readInt32();
     }
 
@@ -271,19 +269,16 @@
         case CAPTURE_SCREEN: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
             sp<IBinder> display = data.readStrongBinder();
+            sp<IGraphicBufferProducer> producer =
+                    interface_cast<IGraphicBufferProducer>(data.readStrongBinder());
             uint32_t reqWidth = data.readInt32();
             uint32_t reqHeight = data.readInt32();
             uint32_t minLayerZ = data.readInt32();
             uint32_t maxLayerZ = data.readInt32();
-            sp<IMemoryHeap> heap;
-            uint32_t w, h;
-            PixelFormat f;
-            status_t res = captureScreen(display, &heap, &w, &h, &f,
-                    reqWidth, reqHeight, minLayerZ, maxLayerZ);
-            reply->writeStrongBinder(heap->asBinder());
-            reply->writeInt32(w);
-            reply->writeInt32(h);
-            reply->writeInt32(f);
+            bool isCpuConsumer = data.readInt32();
+            status_t res = captureScreen(display, producer,
+                    reqWidth, reqHeight, minLayerZ, maxLayerZ,
+                    isCpuConsumer);
             reply->writeInt32(res);
         } break;
         case AUTHENTICATE_SURFACE: {
diff --git a/libs/gui/ISurfaceComposerClient.cpp b/libs/gui/ISurfaceComposerClient.cpp
index 101292d..1adc134 100644
--- a/libs/gui/ISurfaceComposerClient.cpp
+++ b/libs/gui/ISurfaceComposerClient.cpp
@@ -29,7 +29,7 @@
 #include <ui/Point.h>
 #include <ui/Rect.h>
 
-#include <gui/ISurface.h>
+#include <gui/IGraphicBufferProducer.h>
 #include <gui/ISurfaceComposerClient.h>
 #include <private/gui/LayerState.h>
 
@@ -46,16 +46,13 @@
 {
 public:
     BpSurfaceComposerClient(const sp<IBinder>& impl)
-        : BpInterface<ISurfaceComposerClient>(impl)
-    {
+        : BpInterface<ISurfaceComposerClient>(impl) {
     }
 
-    virtual sp<ISurface> createSurface( const String8& name,
-                                        uint32_t w,
-                                        uint32_t h,
-                                        PixelFormat format,
-                                        uint32_t flags)
-    {
+    virtual status_t createSurface(const String8& name, uint32_t w,
+            uint32_t h, PixelFormat format, uint32_t flags,
+            sp<IBinder>* handle,
+            sp<IGraphicBufferProducer>* gbp) {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceComposerClient::getInterfaceDescriptor());
         data.writeString8(name);
@@ -64,11 +61,12 @@
         data.writeInt32(format);
         data.writeInt32(flags);
         remote()->transact(CREATE_SURFACE, data, &reply);
-        return interface_cast<ISurface>(reply.readStrongBinder());
+        *handle = reply.readStrongBinder();
+        *gbp = interface_cast<IGraphicBufferProducer>(reply.readStrongBinder());
+        return reply.readInt32();
     }
 
-    virtual status_t destroySurface(const sp<IBinder>& handle)
-    {
+    virtual status_t destroySurface(const sp<IBinder>& handle) {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceComposerClient::getInterfaceDescriptor());
         data.writeStrongBinder(handle);
@@ -92,8 +90,13 @@
             uint32_t h = data.readInt32();
             PixelFormat format = data.readInt32();
             uint32_t flags = data.readInt32();
-            sp<ISurface> s = createSurface(name, w, h, format, flags);
-            reply->writeStrongBinder(s->asBinder());
+            sp<IBinder> handle;
+            sp<IGraphicBufferProducer> gbp;
+            status_t result = createSurface(name, w, h, format, flags,
+                    &handle, &gbp);
+            reply->writeStrongBinder(handle);
+            reply->writeStrongBinder(gbp->asBinder());
+            reply->writeInt32(result);
             return NO_ERROR;
         } break;
         case DESTROY_SURFACE: {
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 410ad5d..4a58023 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -38,22 +38,8 @@
 
 Surface::Surface(
         const sp<IGraphicBufferProducer>& bufferProducer)
+    : mGraphicBufferProducer(bufferProducer)
 {
-    Surface::init();
-    Surface::setIGraphicBufferProducer(bufferProducer);
-}
-
-Surface::Surface() {
-    Surface::init();
-}
-
-Surface::~Surface() {
-    if (mConnectedToCpu) {
-        Surface::disconnect(NATIVE_WINDOW_API_CPU);
-    }
-}
-
-void Surface::init() {
     // Initialize the ANativeWindow function pointers.
     ANativeWindow::setSwapInterval  = hook_setSwapInterval;
     ANativeWindow::dequeueBuffer    = hook_dequeueBuffer;
@@ -87,10 +73,10 @@
     mConnectedToCpu = false;
 }
 
-void Surface::setIGraphicBufferProducer(
-        const sp<IGraphicBufferProducer>& bufferProducer)
-{
-    mGraphicBufferProducer = bufferProducer;
+Surface::~Surface() {
+    if (mConnectedToCpu) {
+        Surface::disconnect(NATIVE_WINDOW_API_CPU);
+    }
 }
 
 sp<IGraphicBufferProducer> Surface::getIGraphicBufferProducer() const {
@@ -196,8 +182,8 @@
     int reqW = mReqWidth ? mReqWidth : mUserWidth;
     int reqH = mReqHeight ? mReqHeight : mUserHeight;
     sp<Fence> fence;
-    status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, fence, reqW, reqH,
-            mReqFormat, mReqUsage);
+    status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence,
+            reqW, reqH, mReqFormat, mReqUsage);
     if (result < 0) {
         ALOGV("dequeueBuffer: IGraphicBufferProducer::dequeueBuffer(%d, %d, %d, %d)"
              "failed: %d", mReqWidth, mReqHeight, mReqFormat, mReqUsage,
@@ -723,23 +709,6 @@
 
 // ----------------------------------------------------------------------------
 
-status_t Surface::writeToParcel(
-        const sp<Surface>& surface, Parcel* parcel) {
-    sp<IGraphicBufferProducer> bp;
-    if (surface != NULL) {
-        bp = surface->mGraphicBufferProducer;
-    }
-    return parcel->writeStrongBinder(bp->asBinder());
-}
-
-sp<Surface> Surface::readFromParcel(const Parcel& data) {
-    sp<IBinder> binder(data.readStrongBinder());
-    sp<IGraphicBufferProducer> bp(interface_cast<IGraphicBufferProducer>(binder));
-    return new Surface(bp);
-}
-
-// ----------------------------------------------------------------------------
-
 status_t Surface::lock(
         ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds)
 {
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index e8e208f..ec46fce 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -31,8 +31,8 @@
 
 #include <ui/DisplayInfo.h>
 
+#include <gui/CpuConsumer.h>
 #include <gui/IGraphicBufferProducer.h>
-#include <gui/ISurface.h>
 #include <gui/ISurfaceComposer.h>
 #include <gui/ISurfaceComposerClient.h>
 #include <gui/SurfaceComposerClient.h>
@@ -471,14 +471,18 @@
         PixelFormat format,
         uint32_t flags)
 {
-    sp<SurfaceControl> result;
+    sp<SurfaceControl> sur;
     if (mStatus == NO_ERROR) {
-        sp<ISurface> surface = mClient->createSurface(name, w, h, format, flags);
-        if (surface != 0) {
-            result = new SurfaceControl(this, surface);
+        sp<IBinder> handle;
+        sp<IGraphicBufferProducer> gbp;
+        status_t err = mClient->createSurface(name, w, h, format, flags,
+                &handle, &gbp);
+        ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err));
+        if (err == NO_ERROR) {
+            sur = new SurfaceControl(this, handle, gbp);
         }
     }
-    return result;
+    return sur;
 }
 
 sp<IBinder> SurfaceComposerClient::createDisplay(const String8& displayName,
@@ -606,27 +610,29 @@
 
 // ----------------------------------------------------------------------------
 
+status_t ScreenshotClient::capture(
+        const sp<IBinder>& display,
+        const sp<IGraphicBufferProducer>& producer,
+        uint32_t reqWidth, uint32_t reqHeight,
+        uint32_t minLayerZ, uint32_t maxLayerZ) {
+    sp<ISurfaceComposer> s(ComposerService::getComposerService());
+    if (s == NULL) return NO_INIT;
+    return s->captureScreen(display, producer,
+            reqWidth, reqHeight, minLayerZ, maxLayerZ,
+            false);
+}
+
 ScreenshotClient::ScreenshotClient()
-    : mWidth(0), mHeight(0), mFormat(PIXEL_FORMAT_NONE) {
+    : mHaveBuffer(false) {
+    memset(&mBuffer, 0, sizeof(mBuffer));
 }
 
-status_t ScreenshotClient::update(const sp<IBinder>& display) {
-    sp<ISurfaceComposer> s(ComposerService::getComposerService());
-    if (s == NULL) return NO_INIT;
-    mHeap = 0;
-    return s->captureScreen(display, &mHeap,
-            &mWidth, &mHeight, &mFormat, 0, 0,
-            0, -1UL);
-}
-
-status_t ScreenshotClient::update(const sp<IBinder>& display,
-        uint32_t reqWidth, uint32_t reqHeight) {
-    sp<ISurfaceComposer> s(ComposerService::getComposerService());
-    if (s == NULL) return NO_INIT;
-    mHeap = 0;
-    return s->captureScreen(display, &mHeap,
-            &mWidth, &mHeight, &mFormat, reqWidth, reqHeight,
-            0, -1UL);
+sp<CpuConsumer> ScreenshotClient::getCpuConsumer() const {
+    if (mCpuConsumer == NULL) {
+        mCpuConsumer = new CpuConsumer(1);
+        mCpuConsumer->setName(String8("ScreenshotClient"));
+    }
+    return mCpuConsumer;
 }
 
 status_t ScreenshotClient::update(const sp<IBinder>& display,
@@ -634,38 +640,66 @@
         uint32_t minLayerZ, uint32_t maxLayerZ) {
     sp<ISurfaceComposer> s(ComposerService::getComposerService());
     if (s == NULL) return NO_INIT;
-    mHeap = 0;
-    return s->captureScreen(display, &mHeap,
-            &mWidth, &mHeight, &mFormat, reqWidth, reqHeight,
-            minLayerZ, maxLayerZ);
+    sp<CpuConsumer> cpuConsumer = getCpuConsumer();
+
+    if (mHaveBuffer) {
+        mCpuConsumer->unlockBuffer(mBuffer);
+        memset(&mBuffer, 0, sizeof(mBuffer));
+        mHaveBuffer = false;
+    }
+
+    status_t err = s->captureScreen(display,cpuConsumer->getBufferQueue(),
+            reqWidth, reqHeight, minLayerZ, maxLayerZ, true);
+
+    if (err == NO_ERROR) {
+        err = mCpuConsumer->lockNextBuffer(&mBuffer);
+        if (err == NO_ERROR) {
+            mHaveBuffer = true;
+        }
+    }
+    return err;
+}
+
+status_t ScreenshotClient::update(const sp<IBinder>& display) {
+    return ScreenshotClient::update(display, 0, 0, 0, -1UL);
+}
+
+status_t ScreenshotClient::update(const sp<IBinder>& display,
+        uint32_t reqWidth, uint32_t reqHeight) {
+    return ScreenshotClient::update(display, reqWidth, reqHeight, 0, -1UL);
 }
 
 void ScreenshotClient::release() {
-    mHeap = 0;
+    if (mHaveBuffer) {
+        mCpuConsumer->unlockBuffer(mBuffer);
+        memset(&mBuffer, 0, sizeof(mBuffer));
+        mHaveBuffer = false;
+    }
+    mCpuConsumer.clear();
 }
 
 void const* ScreenshotClient::getPixels() const {
-    return mHeap->getBase();
+    return mBuffer.data;
 }
 
 uint32_t ScreenshotClient::getWidth() const {
-    return mWidth;
+    return mBuffer.width;
 }
 
 uint32_t ScreenshotClient::getHeight() const {
-    return mHeight;
+    return mBuffer.height;
 }
 
 PixelFormat ScreenshotClient::getFormat() const {
-    return mFormat;
+    return mBuffer.format;
 }
 
 uint32_t ScreenshotClient::getStride() const {
-    return mWidth;
+    return mBuffer.stride;
 }
 
 size_t ScreenshotClient::getSize() const {
-    return mHeap->getSize();
+    return mBuffer.stride * mBuffer.height * bytesPerPixel(mBuffer.format);
 }
 
 // ----------------------------------------------------------------------------
diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp
index ef52269..f4e88f5 100644
--- a/libs/gui/SurfaceControl.cpp
+++ b/libs/gui/SurfaceControl.cpp
@@ -34,7 +34,6 @@
 #include <ui/GraphicBuffer.h>
 #include <ui/Rect.h>
 
-#include <gui/ISurface.h>
 #include <gui/ISurfaceComposer.h>
 #include <gui/Surface.h>
 #include <gui/SurfaceComposerClient.h>
@@ -48,13 +47,10 @@
 
 SurfaceControl::SurfaceControl(
         const sp<SurfaceComposerClient>& client, 
-        const sp<ISurface>& surface)
-    : mClient(client)
+        const sp<IBinder>& handle,
+        const sp<IGraphicBufferProducer>& gbp)
+    : mClient(client), mHandle(handle), mGraphicBufferProducer(gbp)
 {
-    if (surface != 0) {
-        mSurface = surface->asBinder();
-        mGraphicBufferProducer = surface->getSurfaceTexture();
-    }
 }
         
 SurfaceControl::~SurfaceControl()
@@ -65,12 +61,12 @@
 void SurfaceControl::destroy()
 {
     if (isValid()) {
-        mClient->destroySurface(mSurface);
+        mClient->destroySurface(mHandle);
     }
     // clear all references and trigger an IPC now, to make sure things
     // happen without delay, since these resources are quite heavy.
     mClient.clear();
-    mSurface.clear();
+    mHandle.clear();
     mGraphicBufferProducer.clear();
     IPCThreadState::self()->flushCommands();
 }
@@ -91,81 +87,81 @@
 {
     if (lhs == 0 || rhs == 0)
         return false;
-    return lhs->mSurface == rhs->mSurface;
+    return lhs->mHandle == rhs->mHandle;
 }
 
 status_t SurfaceControl::setLayerStack(int32_t layerStack) {
     status_t err = validate();
     if (err < 0) return err;
     const sp<SurfaceComposerClient>& client(mClient);
-    return client->setLayerStack(mSurface, layerStack);
+    return client->setLayerStack(mHandle, layerStack);
 }
 status_t SurfaceControl::setLayer(int32_t layer) {
     status_t err = validate();
     if (err < 0) return err;
     const sp<SurfaceComposerClient>& client(mClient);
-    return client->setLayer(mSurface, layer);
+    return client->setLayer(mHandle, layer);
 }
-status_t SurfaceControl::setPosition(int32_t x, int32_t y) {
+status_t SurfaceControl::setPosition(float x, float y) {
     status_t err = validate();
     if (err < 0) return err;
     const sp<SurfaceComposerClient>& client(mClient);
-    return client->setPosition(mSurface, x, y);
+    return client->setPosition(mHandle, x, y);
 }
 status_t SurfaceControl::setSize(uint32_t w, uint32_t h) {
     status_t err = validate();
     if (err < 0) return err;
     const sp<SurfaceComposerClient>& client(mClient);
-    return client->setSize(mSurface, w, h);
+    return client->setSize(mHandle, w, h);
 }
 status_t SurfaceControl::hide() {
     status_t err = validate();
     if (err < 0) return err;
     const sp<SurfaceComposerClient>& client(mClient);
-    return client->hide(mSurface);
+    return client->hide(mHandle);
 }
 status_t SurfaceControl::show() {
     status_t err = validate();
     if (err < 0) return err;
     const sp<SurfaceComposerClient>& client(mClient);
-    return client->show(mSurface);
+    return client->show(mHandle);
 }
 status_t SurfaceControl::setFlags(uint32_t flags, uint32_t mask) {
     status_t err = validate();
     if (err < 0) return err;
     const sp<SurfaceComposerClient>& client(mClient);
-    return client->setFlags(mSurface, flags, mask);
+    return client->setFlags(mHandle, flags, mask);
 }
 status_t SurfaceControl::setTransparentRegionHint(const Region& transparent) {
     status_t err = validate();
     if (err < 0) return err;
     const sp<SurfaceComposerClient>& client(mClient);
-    return client->setTransparentRegionHint(mSurface, transparent);
+    return client->setTransparentRegionHint(mHandle, transparent);
 }
 status_t SurfaceControl::setAlpha(float alpha) {
     status_t err = validate();
     if (err < 0) return err;
     const sp<SurfaceComposerClient>& client(mClient);
-    return client->setAlpha(mSurface, alpha);
+    return client->setAlpha(mHandle, alpha);
 }
 status_t SurfaceControl::setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
     status_t err = validate();
     if (err < 0) return err;
     const sp<SurfaceComposerClient>& client(mClient);
-    return client->setMatrix(mSurface, dsdx, dtdx, dsdy, dtdy);
+    return client->setMatrix(mHandle, dsdx, dtdx, dsdy, dtdy);
 }
 status_t SurfaceControl::setCrop(const Rect& crop) {
     status_t err = validate();
     if (err < 0) return err;
     const sp<SurfaceComposerClient>& client(mClient);
-    return client->setCrop(mSurface, crop);
+    return client->setCrop(mHandle, crop);
 }
 
 status_t SurfaceControl::validate() const
 {
-    if (mSurface==0 || mClient==0) {
-        ALOGE("invalid ISurface (%p) or client (%p)",
-                mSurface.get(), mClient.get());
+    if (mHandle==0 || mClient==0) {
+        ALOGE("invalid handle (%p) or client (%p)",
+                mHandle.get(), mClient.get());
         return NO_INIT;
     }
     return NO_ERROR;
diff --git a/libs/gui/tests/BufferQueue_test.cpp b/libs/gui/tests/BufferQueue_test.cpp
index 93f8faf..62d215b 100644
--- a/libs/gui/tests/BufferQueue_test.cpp
+++ b/libs/gui/tests/BufferQueue_test.cpp
@@ -76,7 +76,7 @@
 
     for (int i = 0; i < 2; i++) {
         ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-                mBQ->dequeueBuffer(&slot, fence, 1, 1, 0,
+                mBQ->dequeueBuffer(&slot, &fence, 1, 1, 0,
                     GRALLOC_USAGE_SW_READ_OFTEN));
         ASSERT_EQ(OK, mBQ->requestBuffer(slot, &buf));
         ASSERT_EQ(OK, mBQ->queueBuffer(slot, qbi, &qbo));
@@ -84,7 +84,7 @@
     }
 
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            mBQ->dequeueBuffer(&slot, fence, 1, 1, 0,
+            mBQ->dequeueBuffer(&slot, &fence, 1, 1, 0,
                 GRALLOC_USAGE_SW_READ_OFTEN));
     ASSERT_EQ(OK, mBQ->requestBuffer(slot, &buf));
     ASSERT_EQ(OK, mBQ->queueBuffer(slot, qbi, &qbo));
diff --git a/libs/gui/tests/CpuConsumer_test.cpp b/libs/gui/tests/CpuConsumer_test.cpp
index 12ae19c..73fdd04 100644
--- a/libs/gui/tests/CpuConsumer_test.cpp
+++ b/libs/gui/tests/CpuConsumer_test.cpp
@@ -35,6 +35,11 @@
 
 #include <ui/FramebufferNativeWindow.h>
 
+#define CPU_CONSUMER_TEST_FORMAT_RAW 0
+#define CPU_CONSUMER_TEST_FORMAT_Y8 0
+#define CPU_CONSUMER_TEST_FORMAT_Y16 0
+#define CPU_CONSUMER_TEST_FORMAT_RGBA_8888 1
+
 namespace android {
 
 struct CpuConsumerTestParams {
@@ -157,7 +162,7 @@
     ASSERT_EQ(NO_ERROR, err) << msg << strerror(-err)
 
 void checkPixel(const CpuConsumer::LockedBuffer &buf,
-        uint32_t x, uint32_t y, uint32_t r, uint32_t g, uint32_t b) {
+        uint32_t x, uint32_t y, uint32_t r, uint32_t g=0, uint32_t b=0) {
     // Ignores components that don't exist for given pixel
     switch(buf.format) {
         case HAL_PIXEL_FORMAT_RAW_SENSOR: {
@@ -179,6 +184,31 @@
             }
             break;
         }
+        // ignores g,b
+        case HAL_PIXEL_FORMAT_Y8: {
+            uint8_t *bPtr = (uint8_t*)buf.data;
+            bPtr += y * buf.stride + x;
+            EXPECT_EQ(r, *bPtr) << "at x = " << x << " y = " << y;
+            break;
+        }
+        // ignores g,b
+        case HAL_PIXEL_FORMAT_Y16: {
+            // stride is in pixels, not in bytes
+            uint16_t *bPtr = ((uint16_t*)buf.data) + y * buf.stride + x;
+
+            EXPECT_EQ(r, *bPtr) << "at x = " << x << " y = " << y;
+            break;
+        }
+        case HAL_PIXEL_FORMAT_RGBA_8888: {
+            const int bytesPerPixel = 4;
+            uint8_t *bPtr = (uint8_t*)buf.data;
+            bPtr += (y * buf.stride + x) * bytesPerPixel;
+
+            EXPECT_EQ(r, bPtr[0]) << "at x = " << x << " y = " << y;
+            EXPECT_EQ(g, bPtr[1]) << "at x = " << x << " y = " << y;
+            EXPECT_EQ(b, bPtr[2]) << "at x = " << x << " y = " << y;
+            break;
+        }
         default: {
             ADD_FAILURE() << "Unknown format for check:" << buf.format;
             break;
@@ -189,6 +219,61 @@
 // Fill a YV12 buffer with a multi-colored checkerboard pattern
 void fillYV12Buffer(uint8_t* buf, int w, int h, int stride);
 
+// Fill a Y8/Y16 buffer with a multi-colored checkerboard pattern
+template <typename T> // T == uint8_t or uint16_t
+void fillGreyscaleBuffer(T* buf, int w, int h, int stride, int bpp) {
+    const int blockWidth = w > 16 ? w / 16 : 1;
+    const int blockHeight = h > 16 ? h / 16 : 1;
+    const int yuvTexOffsetY = 0;
+
+    ASSERT_TRUE(bpp == 8 || bpp == 16);
+    ASSERT_TRUE(sizeof(T)*8 == bpp);
+
+    // stride is in pixels, not in bytes
+    int yuvTexStrideY = stride;
+    for (int x = 0; x < w; x++) {
+        for (int y = 0; y < h; y++) {
+            int parityX = (x / blockWidth) & 1;
+            int parityY = (y / blockHeight) & 1;
+            T intensity = (parityX ^ parityY) ? 63 : 191;
+            buf[yuvTexOffsetY + (y * yuvTexStrideY) + x] = intensity;
+        }
+    }
+}
+
+inline uint8_t chooseColorRgba8888(int blockX, int blockY, uint8_t channel) {
+    const int colorVariations = 3;
+    uint8_t color = ((blockX % colorVariations) + (blockY % colorVariations))
+                        % (colorVariations) == channel ? 191: 63;
+
+    return color;
+}
+
+// Fill a RGBA8888 buffer with a multi-colored checkerboard pattern
+void fillRgba8888Buffer(uint8_t* buf, int w, int h, int stride)
+{
+    const int blockWidth = w > 16 ? w / 16 : 1;
+    const int blockHeight = h > 16 ? h / 16 : 1;
+    const int bytesPerPixel = 4;
+
+    // stride is in pixels, not in bytes
+    for (int x = 0; x < w; ++x) {
+        for (int y = 0; y < h; ++y) {
+            int blockX = (x / blockWidth);
+            int blockY = (y / blockHeight);
+
+            uint8_t r = chooseColorRgba8888(blockX, blockY, 0);
+            uint8_t g = chooseColorRgba8888(blockX, blockY, 1);
+            uint8_t b = chooseColorRgba8888(blockX, blockY, 2);
+
+            buf[(y*stride + x)*bytesPerPixel + 0] = r;
+            buf[(y*stride + x)*bytesPerPixel + 1] = g;
+            buf[(y*stride + x)*bytesPerPixel + 2] = b;
+            buf[(y*stride + x)*bytesPerPixel + 3] = 255;
+        }
+    }
+}
+
 // Fill a RAW sensor buffer with a multi-colored checkerboard pattern.
 // Assumes GRBG mosaic ordering. Result should be a grid in a 2x2 pattern
 // of [ R, B; G, W]
@@ -217,6 +302,89 @@
 
 }
 
+template<typename T> // uint8_t or uint16_t
+void checkGreyscaleBuffer(const CpuConsumer::LockedBuffer &buf) {
+    uint32_t w = buf.width;
+    uint32_t h = buf.height;
+    const int blockWidth = w > 16 ? w / 16 : 1;
+    const int blockHeight = h > 16 ? h / 16 : 1;
+    const int blockRows = h / blockHeight;
+    const int blockCols = w / blockWidth;
+
+    // Top-left square is bright
+    checkPixel(buf, 0, 0, 191);
+    checkPixel(buf, 1, 0, 191);
+    checkPixel(buf, 0, 1, 191);
+    checkPixel(buf, 1, 1, 191);
+
+    // One-right square is dark
+    checkPixel(buf, blockWidth,     0, 63);
+    checkPixel(buf, blockWidth + 1, 0, 63);
+    checkPixel(buf, blockWidth,     1, 63);
+    checkPixel(buf, blockWidth + 1, 1, 63);
+
+    // One-down square is dark
+    checkPixel(buf, 0, blockHeight, 63);
+    checkPixel(buf, 1, blockHeight, 63);
+    checkPixel(buf, 0, blockHeight + 1, 63);
+    checkPixel(buf, 1, blockHeight + 1, 63);
+
+    // One-diag square is bright
+    checkPixel(buf, blockWidth,     blockHeight, 191);
+    checkPixel(buf, blockWidth + 1, blockHeight, 191);
+    checkPixel(buf, blockWidth,     blockHeight + 1, 191);
+    checkPixel(buf, blockWidth + 1, blockHeight + 1, 191);
+
+    // Test bottom-right pixel
+    const int maxBlockX = ((w-1 + (blockWidth-1)) / blockWidth) & 0x1;
+    const int maxBlockY = ((h-1 + (blockHeight-1)) / blockHeight) & 0x1;
+    uint32_t pixelValue = ((maxBlockX % 2) == (maxBlockY % 2)) ? 191 : 63;
+    checkPixel(buf, w-1, h-1, pixelValue);
+}
+
+void checkRgba8888Buffer(const CpuConsumer::LockedBuffer &buf) {
+    uint32_t w = buf.width;
+    uint32_t h = buf.height;
+    const int blockWidth = w > 16 ? w / 16 : 1;
+    const int blockHeight = h > 16 ? h / 16 : 1;
+    const int blockRows = h / blockHeight;
+    const int blockCols = w / blockWidth;
+
+    // Top-left square is bright red
+    checkPixel(buf, 0, 0, 191, 63, 63);
+    checkPixel(buf, 1, 0, 191, 63, 63);
+    checkPixel(buf, 0, 1, 191, 63, 63);
+    checkPixel(buf, 1, 1, 191, 63, 63);
+
+    // One-right square is bright green
+    checkPixel(buf, blockWidth,     0, 63, 191, 63);
+    checkPixel(buf, blockWidth + 1, 0, 63, 191, 63);
+    checkPixel(buf, blockWidth,     1, 63, 191, 63);
+    checkPixel(buf, blockWidth + 1, 1, 63, 191, 63);
+
+    // One-down square is bright green
+    checkPixel(buf, 0, blockHeight, 63, 191, 63);
+    checkPixel(buf, 1, blockHeight, 63, 191, 63);
+    checkPixel(buf, 0, blockHeight + 1, 63, 191, 63);
+    checkPixel(buf, 1, blockHeight + 1, 63, 191, 63);
+
+    // One-diag square is bright blue
+    checkPixel(buf, blockWidth,     blockHeight, 63, 63, 191);
+    checkPixel(buf, blockWidth + 1, blockHeight, 63, 63, 191);
+    checkPixel(buf, blockWidth,     blockHeight + 1, 63, 63, 191);
+    checkPixel(buf, blockWidth + 1, blockHeight + 1, 63, 63, 191);
+
+    // Test bottom-right pixel
+    {
+        const int maxBlockX = ((w-1) / blockWidth);
+        const int maxBlockY = ((h-1) / blockHeight);
+        uint8_t r = chooseColorRgba8888(maxBlockX, maxBlockY, 0);
+        uint8_t g = chooseColorRgba8888(maxBlockX, maxBlockY, 1);
+        uint8_t b = chooseColorRgba8888(maxBlockX, maxBlockY, 2);
+        checkPixel(buf, w-1, h-1, r, g, b);
+    }
+}
+
 void checkBayerRawBuffer(const CpuConsumer::LockedBuffer &buf) {
     uint32_t w = buf.width;
     uint32_t h = buf.height;
@@ -258,6 +426,23 @@
     checkPixel(buf, w-1, h-1, maxR, maxG, maxB);
 }
 
+void checkAnyBuffer(const CpuConsumer::LockedBuffer &buf, int format) {
+    switch (format) {
+        case HAL_PIXEL_FORMAT_RAW_SENSOR:
+            checkBayerRawBuffer(buf);
+            break;
+        case HAL_PIXEL_FORMAT_Y8:
+            checkGreyscaleBuffer<uint8_t>(buf);
+            break;
+        case HAL_PIXEL_FORMAT_Y16:
+            checkGreyscaleBuffer<uint16_t>(buf);
+            break;
+        case HAL_PIXEL_FORMAT_RGBA_8888:
+            checkRgba8888Buffer(buf);
+            break;
+    }
+}
+
 void fillYV12BufferRect(uint8_t* buf, int w, int h, int stride,
         const android_native_rect_t& rect);
 
@@ -322,6 +507,18 @@
         case HAL_PIXEL_FORMAT_RAW_SENSOR:
             fillBayerRawBuffer(img, params.width, params.height, buf->getStride());
             break;
+        case HAL_PIXEL_FORMAT_Y8:
+            fillGreyscaleBuffer<uint8_t>(img, params.width, params.height,
+                                         buf->getStride(), /*bpp*/8);
+            break;
+        case HAL_PIXEL_FORMAT_Y16:
+            fillGreyscaleBuffer<uint16_t>((uint16_t*)img, params.width,
+                                          params.height, buf->getStride(),
+                                          /*bpp*/16);
+            break;
+        case HAL_PIXEL_FORMAT_RGBA_8888:
+            fillRgba8888Buffer(img, params.width, params.height, buf->getStride());
+            break;
         default:
             FAIL() << "Unknown pixel format under test!";
             break;
@@ -341,7 +538,7 @@
 
 // This test is disabled because the HAL_PIXEL_FORMAT_RAW_SENSOR format is not
 // supported on all devices.
-TEST_P(CpuConsumerTest, DISABLED_FromCpuSingle) {
+TEST_P(CpuConsumerTest, FromCpuSingle) {
     status_t err;
     CpuConsumerTestParams params = GetParam();
 
@@ -369,13 +566,13 @@
     EXPECT_EQ(stride, b.stride);
     EXPECT_EQ(time, b.timestamp);
 
-    checkBayerRawBuffer(b);
+    checkAnyBuffer(b, GetParam().format);
     mCC->unlockBuffer(b);
 }
 
 // This test is disabled because the HAL_PIXEL_FORMAT_RAW_SENSOR format is not
 // supported on all devices.
-TEST_P(CpuConsumerTest, DISABLED_FromCpuManyInQueue) {
+TEST_P(CpuConsumerTest, FromCpuManyInQueue) {
     status_t err;
     CpuConsumerTestParams params = GetParam();
 
@@ -410,7 +607,7 @@
         EXPECT_EQ(stride[i], b.stride);
         EXPECT_EQ(time[i], b.timestamp);
 
-        checkBayerRawBuffer(b);
+        checkAnyBuffer(b, GetParam().format);
 
         mCC->unlockBuffer(b);
     }
@@ -418,7 +615,7 @@
 
 // This test is disabled because the HAL_PIXEL_FORMAT_RAW_SENSOR format is not
 // supported on all devices.
-TEST_P(CpuConsumerTest, DISABLED_FromCpuLockMax) {
+TEST_P(CpuConsumerTest, FromCpuLockMax) {
     status_t err;
     CpuConsumerTestParams params = GetParam();
 
@@ -452,7 +649,7 @@
         EXPECT_EQ(stride, b[i].stride);
         EXPECT_EQ(time, b[i].timestamp);
 
-        checkBayerRawBuffer(b[i]);
+        checkAnyBuffer(b[i], GetParam().format);
     }
 
     ALOGV("Locking frame %d (too many)", params.maxLockedBuffers);
@@ -475,7 +672,7 @@
     EXPECT_EQ(stride, bTooMuch.stride);
     EXPECT_EQ(time, bTooMuch.timestamp);
 
-    checkBayerRawBuffer(bTooMuch);
+    checkAnyBuffer(bTooMuch, GetParam().format);
 
     ALOGV("Unlocking extra buffer");
     err = mCC->unlockBuffer(bTooMuch);
@@ -493,17 +690,66 @@
 
 }
 
+CpuConsumerTestParams y8TestSets[] = {
+    { 512,   512, 1, HAL_PIXEL_FORMAT_Y8},
+    { 512,   512, 3, HAL_PIXEL_FORMAT_Y8},
+    { 2608, 1960, 1, HAL_PIXEL_FORMAT_Y8},
+    { 2608, 1960, 3, HAL_PIXEL_FORMAT_Y8},
+    { 100,   100, 1, HAL_PIXEL_FORMAT_Y8},
+    { 100,   100, 3, HAL_PIXEL_FORMAT_Y8},
+};
+
+CpuConsumerTestParams y16TestSets[] = {
+    { 512,   512, 1, HAL_PIXEL_FORMAT_Y16},
+    { 512,   512, 3, HAL_PIXEL_FORMAT_Y16},
+    { 2608, 1960, 1, HAL_PIXEL_FORMAT_Y16},
+    { 2608, 1960, 3, HAL_PIXEL_FORMAT_Y16},
+    { 100,   100, 1, HAL_PIXEL_FORMAT_Y16},
+    { 100,   100, 3, HAL_PIXEL_FORMAT_Y16},
+};
+
 CpuConsumerTestParams rawTestSets[] = {
     { 512,   512, 1, HAL_PIXEL_FORMAT_RAW_SENSOR},
     { 512,   512, 3, HAL_PIXEL_FORMAT_RAW_SENSOR},
     { 2608, 1960, 1, HAL_PIXEL_FORMAT_RAW_SENSOR},
     { 2608, 1960, 3, HAL_PIXEL_FORMAT_RAW_SENSOR},
     { 100,   100, 1, HAL_PIXEL_FORMAT_RAW_SENSOR},
-    { 100,   100, 3, HAL_PIXEL_FORMAT_RAW_SENSOR}
+    { 100,   100, 3, HAL_PIXEL_FORMAT_RAW_SENSOR},
 };
 
+CpuConsumerTestParams rgba8888TestSets[] = {
+    { 512,   512, 1, HAL_PIXEL_FORMAT_RGBA_8888},
+    { 512,   512, 3, HAL_PIXEL_FORMAT_RGBA_8888},
+    { 2608, 1960, 1, HAL_PIXEL_FORMAT_RGBA_8888},
+    { 2608, 1960, 3, HAL_PIXEL_FORMAT_RGBA_8888},
+    { 100,   100, 1, HAL_PIXEL_FORMAT_RGBA_8888},
+    { 100,   100, 3, HAL_PIXEL_FORMAT_RGBA_8888},
+};
+
+#if CPU_CONSUMER_TEST_FORMAT_Y8
+INSTANTIATE_TEST_CASE_P(Y8Tests,
+        CpuConsumerTest,
+        ::testing::ValuesIn(y8TestSets));
+#endif
+
+#if CPU_CONSUMER_TEST_FORMAT_Y16
+INSTANTIATE_TEST_CASE_P(Y16Tests,
+        CpuConsumerTest,
+        ::testing::ValuesIn(y16TestSets));
+#endif
+
+#if CPU_CONSUMER_TEST_FORMAT_RAW
 INSTANTIATE_TEST_CASE_P(RawTests,
         CpuConsumerTest,
         ::testing::ValuesIn(rawTestSets));
+#endif
+
+#if CPU_CONSUMER_TEST_FORMAT_RGBA_8888
+INSTANTIATE_TEST_CASE_P(Rgba8888Tests,
+        CpuConsumerTest,
+        ::testing::ValuesIn(rgba8888TestSets));
+#endif
+
+
 
 } // namespace android
diff --git a/libs/gui/tests/SurfaceTexture_test.cpp b/libs/gui/tests/SurfaceTexture_test.cpp
index fbaf6aa..2d30305 100644
--- a/libs/gui/tests/SurfaceTexture_test.cpp
+++ b/libs/gui/tests/SurfaceTexture_test.cpp
@@ -1636,6 +1636,81 @@
     }
 }
 
+TEST_F(SurfaceTextureGLToGLTest, EglMakeCurrentBeforeConsumerDeathUnrefsBuffers) {
+    sp<GraphicBuffer> buffer;
+
+    EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface,
+            mProducerEglSurface, mProducerEglContext));
+
+    // Produce a frame
+    glClear(GL_COLOR_BUFFER_BIT);
+    EXPECT_TRUE(eglSwapBuffers(mEglDisplay, mProducerEglSurface));
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+    // Destroy the EGLSurface.
+    EXPECT_TRUE(eglDestroySurface(mEglDisplay, mProducerEglSurface));
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    mProducerEglSurface = EGL_NO_SURFACE;
+    mSTC.clear();
+    mANW.clear();
+    mTextureRenderer.clear();
+
+    // Consume a frame
+    ASSERT_EQ(NO_ERROR, mST->updateTexImage());
+    buffer = mST->getCurrentBuffer();
+
+    // Destroy the GL texture object to release its ref
+    GLuint texID = TEX_ID;
+    glDeleteTextures(1, &texID);
+
+    // make un-current, all references to buffer should be gone
+    EXPECT_TRUE(eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE,
+            EGL_NO_SURFACE, EGL_NO_CONTEXT));
+
+    // Destroy consumer
+    mST.clear();
+
+    EXPECT_EQ(1, buffer->getStrongCount());
+}
+
+TEST_F(SurfaceTextureGLToGLTest, EglMakeCurrentAfterConsumerDeathUnrefsBuffers) {
+    sp<GraphicBuffer> buffer;
+
+    EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface,
+            mProducerEglSurface, mProducerEglContext));
+
+    // Produce a frame
+    glClear(GL_COLOR_BUFFER_BIT);
+    EXPECT_TRUE(eglSwapBuffers(mEglDisplay, mProducerEglSurface));
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+    // Destroy the EGLSurface.
+    EXPECT_TRUE(eglDestroySurface(mEglDisplay, mProducerEglSurface));
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    mProducerEglSurface = EGL_NO_SURFACE;
+    mSTC.clear();
+    mANW.clear();
+    mTextureRenderer.clear();
+
+    // Consume a frame
+    ASSERT_EQ(NO_ERROR, mST->updateTexImage());
+    buffer = mST->getCurrentBuffer();
+
+    // Destroy the GL texture object to release its ref
+    GLuint texID = TEX_ID;
+    glDeleteTextures(1, &texID);
+
+    // Destroy consumer
+    mST.clear();
+
+    // make un-current, all references to buffer should be gone
+    EXPECT_TRUE(eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE,
+            EGL_NO_SURFACE, EGL_NO_CONTEXT));
+
+    EXPECT_EQ(1, buffer->getStrongCount());
+}
+
+
 TEST_F(SurfaceTextureGLToGLTest, EglSurfaceDefaultsToSynchronousMode) {
     // This test requires 3 buffers to run on a single thread.
     mST->setDefaultMaxBufferCount(3);
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 545b547..429becf 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -23,11 +23,17 @@
 #include <utils/String8.h>
 
 #include <private/gui/ComposerService.h>
+#include <binder/ProcessState.h>
 
 namespace android {
 
 class SurfaceTest : public ::testing::Test {
 protected:
+
+    SurfaceTest() {
+        ProcessState::self()->startThreadPool();
+    }
+
     virtual void SetUp() {
         mComposerClient = new SurfaceComposerClient;
         ASSERT_EQ(NO_ERROR, mComposerClient->initCheck());
@@ -81,14 +87,11 @@
     sp<ANativeWindow> anw(mSurface);
 
     // Verify the screenshot works with no protected buffers.
-    sp<IMemoryHeap> heap;
-    uint32_t w=0, h=0;
-    PixelFormat fmt=0;
+    sp<CpuConsumer> consumer = new CpuConsumer(1);
     sp<ISurfaceComposer> sf(ComposerService::getComposerService());
     sp<IBinder> display(sf->getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
-    ASSERT_EQ(NO_ERROR, sf->captureScreen(display, &heap, &w, &h, &fmt, 64, 64, 0,
-            0x7fffffff));
-    ASSERT_TRUE(heap != NULL);
+    ASSERT_EQ(NO_ERROR, sf->captureScreen(display, consumer->getBufferQueue(),
+            64, 64, 0, 0x7fffffff, true));
 
     // Set the PROTECTED usage bit and verify that the screenshot fails.  Note
     // that we need to dequeue a buffer in order for it to actually get
@@ -116,11 +119,8 @@
                 &buf));
         ASSERT_EQ(NO_ERROR, anw->queueBuffer(anw.get(), buf, -1));
     }
-    heap = 0;
-    w = h = fmt = 0;
-    ASSERT_EQ(NO_ERROR, sf->captureScreen(display, &heap, &w, &h, &fmt,
-            64, 64, 0, 0x7fffffff));
-    ASSERT_TRUE(heap != NULL);
+    ASSERT_EQ(NO_ERROR, sf->captureScreen(display, consumer->getBufferQueue(),
+            64, 64, 0, 0x7fffffff, true));
 }
 
 TEST_F(SurfaceTest, ConcreteTypeIsSurface) {
diff --git a/libs/utils/RefBase.cpp b/libs/utils/RefBase.cpp
index e80a795..3d3a595 100644
--- a/libs/utils/RefBase.cpp
+++ b/libs/utils/RefBase.cpp
@@ -15,6 +15,7 @@
  */
 
 #define LOG_TAG "RefBase"
+// #define LOG_NDEBUG 0
 
 #include <utils/RefBase.h>
 
@@ -34,10 +35,18 @@
 
 // compile with refcounting debugging enabled
 #define DEBUG_REFS                      0
-#define DEBUG_REFS_FATAL_SANITY_CHECKS  0
-#define DEBUG_REFS_ENABLED_BY_DEFAULT   1
+
+// whether ref-tracking is enabled by default, if not, trackMe(true, false)
+// needs to be called explicitly
+#define DEBUG_REFS_ENABLED_BY_DEFAULT   0
+
+// whether callstack are collected (significantly slows things down)
 #define DEBUG_REFS_CALLSTACK_ENABLED    1
 
+// folder where stack traces are saved when DEBUG_REFS is enabled
+// this folder needs to exist and be writable
+#define DEBUG_REFS_CALLSTACK_PATH       "/data/debug"
+
 // log all reference counting operations
 #define PRINT_REFS                      0
 
@@ -95,11 +104,7 @@
         bool dumpStack = false;
         if (!mRetain && mStrongRefs != NULL) {
             dumpStack = true;
-#if DEBUG_REFS_FATAL_SANITY_CHECKS
-            LOG_ALWAYS_FATAL("Strong references remain!");
-#else
             ALOGE("Strong references remain:");
-#endif
             ref_entry* refs = mStrongRefs;
             while (refs) {
                 char inc = refs->ref >= 0 ? '+' : '-';
@@ -113,11 +118,7 @@
 
         if (!mRetain && mWeakRefs != NULL) {
             dumpStack = true;
-#if DEBUG_REFS_FATAL_SANITY_CHECKS
-            LOG_ALWAYS_FATAL("Weak references remain:");
-#else
             ALOGE("Weak references remain!");
-#endif
             ref_entry* refs = mWeakRefs;
             while (refs) {
                 char inc = refs->ref >= 0 ? '+' : '-';
@@ -198,8 +199,8 @@
 
         {
             char name[100];
-            snprintf(name, 100, "/data/%p.stack", this);
-            int rc = open(name, O_RDWR | O_CREAT | O_APPEND);
+            snprintf(name, 100, DEBUG_REFS_CALLSTACK_PATH "/%p.stack", this);
+            int rc = open(name, O_RDWR | O_CREAT | O_APPEND, 644);
             if (rc >= 0) {
                 write(rc, text.string(), text.length());
                 close(rc);
@@ -257,12 +258,6 @@
                 ref = *refs;
             }
 
-#if DEBUG_REFS_FATAL_SANITY_CHECKS
-            LOG_ALWAYS_FATAL("RefBase: removing id %p on RefBase %p"
-                    "(weakref_type %p) that doesn't exist!",
-                    id, mBase, this);
-#endif
-
             ALOGE("RefBase: removing id %p on RefBase %p"
                     "(weakref_type %p) that doesn't exist!",
                     id, mBase, this);
@@ -440,39 +435,68 @@
     incWeak(id);
     
     weakref_impl* const impl = static_cast<weakref_impl*>(this);
-    
     int32_t curCount = impl->mStrong;
-    ALOG_ASSERT(curCount >= 0, "attemptIncStrong called on %p after underflow",
-               this);
+
+    ALOG_ASSERT(curCount >= 0,
+            "attemptIncStrong called on %p after underflow", this);
+
     while (curCount > 0 && curCount != INITIAL_STRONG_VALUE) {
+        // we're in the easy/common case of promoting a weak-reference
+        // from an existing strong reference.
         if (android_atomic_cmpxchg(curCount, curCount+1, &impl->mStrong) == 0) {
             break;
         }
+        // the strong count has changed on us, we need to re-assert our
+        // situation.
         curCount = impl->mStrong;
     }
     
     if (curCount <= 0 || curCount == INITIAL_STRONG_VALUE) {
-        bool allow;
-        if (curCount == INITIAL_STRONG_VALUE) {
-            // Attempting to acquire first strong reference...  this is allowed
-            // if the object does NOT have a longer lifetime (meaning the
-            // implementation doesn't need to see this), or if the implementation
-            // allows it to happen.
-            allow = (impl->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK
-                  || impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id);
+        // we're now in the harder case of either:
+        // - there never was a strong reference on us
+        // - or, all strong references have been released
+        if ((impl->mFlags&OBJECT_LIFETIME_WEAK) == OBJECT_LIFETIME_STRONG) {
+            // this object has a "normal" life-time, i.e.: it gets destroyed
+            // when the last strong reference goes away
+            if (curCount <= 0) {
+                // the last strong-reference got released, the object cannot
+                // be revived.
+                decWeak(id);
+                return false;
+            }
+
+            // here, curCount == INITIAL_STRONG_VALUE, which means
+            // there never was a strong-reference, so we can try to
+            // promote this object; we need to do that atomically.
+            while (curCount > 0) {
+                if (android_atomic_cmpxchg(curCount, curCount + 1,
+                        &impl->mStrong) == 0) {
+                    break;
+                }
+                // the strong count has changed on us, we need to re-assert our
+                // situation (e.g.: another thread has inc/decStrong'ed us)
+                curCount = impl->mStrong;
+            }
+
+            if (curCount <= 0) {
+                // promote() failed, some other thread destroyed us in the
+                // meantime (i.e.: strong count reached zero).
+                decWeak(id);
+                return false;
+            }
         } else {
-            // Attempting to revive the object...  this is allowed
-            // if the object DOES have a longer lifetime (so we can safely
-            // call the object with only a weak ref) and the implementation
-            // allows it to happen.
-            allow = (impl->mFlags&OBJECT_LIFETIME_WEAK) == OBJECT_LIFETIME_WEAK
-                  && impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id);
+            // this object has an "extended" life-time, i.e.: it can be
+            // revived from a weak-reference only.
+            // Ask the object's implementation if it agrees to be revived
+            if (!impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id)) {
+                // it didn't so give-up.
+                decWeak(id);
+                return false;
+            }
+            // grab a strong-reference, which is always safe due to the
+            // extended life-time.
+            curCount = android_atomic_inc(&impl->mStrong);
         }
-        if (!allow) {
-            decWeak(id);
-            return false;
-        }
-        curCount = android_atomic_inc(&impl->mStrong);
 
         // If the strong reference count has already been incremented by
         // someone else, the implementor of onIncStrongAttempted() is holding
@@ -490,11 +514,23 @@
     ALOGD("attemptIncStrong of %p from %p: cnt=%d\n", this, id, curCount);
 #endif
 
-    if (curCount == INITIAL_STRONG_VALUE) {
-        android_atomic_add(-INITIAL_STRONG_VALUE, &impl->mStrong);
-        impl->mBase->onFirstRef();
+    // now we need to fix-up the count if it was INITIAL_STRONG_VALUE
+    // this must be done safely, i.e.: handle the case where several threads
+    // were here in attemptIncStrong().
+    curCount = impl->mStrong;
+    while (curCount >= INITIAL_STRONG_VALUE) {
+        ALOG_ASSERT(curCount > INITIAL_STRONG_VALUE,
+                "attemptIncStrong in %p underflowed to INITIAL_STRONG_VALUE",
+                this);
+        if (android_atomic_cmpxchg(curCount, curCount-INITIAL_STRONG_VALUE,
+                &impl->mStrong) == 0) {
+            break;
+        }
+        // the strong-count changed on us, we need to re-assert the situation,
+        // for e.g.: it's possible the fix-up happened in another thread.
+        curCount = impl->mStrong;
     }
-    
+
     return true;
 }
 
@@ -595,21 +631,27 @@
 
 // ---------------------------------------------------------------------------
 
-void RefBase::moveReferences(void* dst, void const* src, size_t n,
-        const ReferenceConverterBase& caster)
-{
+void RefBase::renameRefs(size_t n, const ReferenceRenamer& renamer) {
 #if DEBUG_REFS
-    const size_t itemSize = caster.getReferenceTypeSize();
     for (size_t i=0 ; i<n ; i++) {
-        void*       d = reinterpret_cast<void      *>(intptr_t(dst) + i*itemSize);
-        void const* s = reinterpret_cast<void const*>(intptr_t(src) + i*itemSize);
-        RefBase* ref(reinterpret_cast<RefBase*>(caster.getReferenceBase(d)));
-        ref->mRefs->renameStrongRefId(s, d);
-        ref->mRefs->renameWeakRefId(s, d);
+        renamer(i);
     }
 #endif
 }
 
+void RefBase::renameRefId(weakref_type* ref,
+        const void* old_id, const void* new_id) {
+    weakref_impl* const impl = static_cast<weakref_impl*>(ref);
+    impl->renameStrongRefId(old_id, new_id);
+    impl->renameWeakRefId(old_id, new_id);
+}
+
+void RefBase::renameRefId(RefBase* ref,
+        const void* old_id, const void* new_id) {
+    ref->mRefs->renameStrongRefId(old_id, new_id);
+    ref->mRefs->renameWeakRefId(old_id, new_id);
+}
+
 // ---------------------------------------------------------------------------
 
 TextOutput& printStrongPointer(TextOutput& to, const void* val)
diff --git a/libs/utils/Threads.cpp b/libs/utils/Threads.cpp
index a25a81f..7b877e0 100644
--- a/libs/utils/Threads.cpp
+++ b/libs/utils/Threads.cpp
@@ -109,30 +109,34 @@
         }
         
         if (name) {
-#if defined(HAVE_PRCTL)
-            // Mac OS doesn't have this, and we build libutil for the host too
-            int hasAt = 0;
-            int hasDot = 0;
-            char *s = name;
-            while (*s) {
-                if (*s == '.') hasDot = 1;
-                else if (*s == '@') hasAt = 1;
-                s++;
-            }
-            int len = s - name;
-            if (len < 15 || hasAt || !hasDot) {
-                s = name;
-            } else {
-                s = name + len - 15;
-            }
-            prctl(PR_SET_NAME, (unsigned long) s, 0, 0, 0);
-#endif
+            androidSetThreadName(name);
             free(name);
         }
         return f(u);
     }
 };
 
+void androidSetThreadName(const char* name) {
+#if defined(HAVE_PRCTL)
+    // Mac OS doesn't have this, and we build libutil for the host too
+    int hasAt = 0;
+    int hasDot = 0;
+    const char *s = name;
+    while (*s) {
+        if (*s == '.') hasDot = 1;
+        else if (*s == '@') hasAt = 1;
+        s++;
+    }
+    int len = s - name;
+    if (len < 15 || hasAt || !hasDot) {
+        s = name;
+    } else {
+        s = name + len - 15;
+    }
+    prctl(PR_SET_NAME, (unsigned long) s, 0, 0, 0);
+#endif
+}
+
 int androidCreateRawThreadEtc(android_thread_func_t entryFunction,
                                void *userData,
                                const char* threadName,
@@ -871,6 +875,11 @@
     return mStatus;
 }
 
+bool Thread::isRunning() const {
+    Mutex::Autolock _l(mLock);
+    return mRunning;
+}
+
 #ifdef HAVE_ANDROID_OS
 pid_t Thread::getTid() const
 {
diff --git a/libs/utils/VectorImpl.cpp b/libs/utils/VectorImpl.cpp
index c3257bb..70f49de 100644
--- a/libs/utils/VectorImpl.cpp
+++ b/libs/utils/VectorImpl.cpp
@@ -343,6 +343,16 @@
     return new_capacity;
 }
 
+ssize_t VectorImpl::resize(size_t size) {
+    ssize_t result = NO_ERROR;
+    if (size > mCount) {
+        result = insertAt(mCount, size - mCount);
+    } else if (size < mCount) {
+        result = removeItemsAt(size, mCount - size);
+    }
+    return result < 0 ? result : size;
+}
+
 void VectorImpl::release_storage()
 {
     if (mStorage) {
diff --git a/opengl/include/EGL/eglext.h b/opengl/include/EGL/eglext.h
index 8578874..c8d228c 100644
--- a/opengl/include/EGL/eglext.h
+++ b/opengl/include/EGL/eglext.h
@@ -311,6 +311,18 @@
 #define EGL_FRAMEBUFFER_TARGET_ANDROID                0x3147
 #endif
 
+/* EGL_ANDROID_presentation_time
+ */
+#ifndef EGL_ANDROID_presentation_time
+#define EGL_ANDROID_presentation_time 1
+typedef khronos_stime_nanoseconds_t EGLnsecsANDROID;
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean eglPresentationTimeANDROID(EGLDisplay dpy, EGLSurface sur, EGLnsecsANDROID time);
+#else
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLPRESENTATIONTIMEANDROID) (EGLDisplay dpy, EGLSurface sur, EGLnsecsANDROID time);
+#endif
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp
index 172ef95..0ed5727 100644
--- a/opengl/libagl/egl.cpp
+++ b/opengl/libagl/egl.cpp
@@ -147,6 +147,7 @@
     EGLDisplay          dpy;
     EGLConfig           config;
     EGLContext          ctx;
+    bool                zombie;
 
                 egl_surface_t(EGLDisplay dpy, EGLConfig config, int32_t depthFormat);
     virtual     ~egl_surface_t();
@@ -173,7 +174,7 @@
 egl_surface_t::egl_surface_t(EGLDisplay dpy,
         EGLConfig config,
         int32_t depthFormat)
-    : magic(MAGIC), dpy(dpy), config(config), ctx(0)
+    : magic(MAGIC), dpy(dpy), config(config), ctx(0), zombie(false)
 {
     depth.version = sizeof(GGLSurface);
     depth.data = 0;
@@ -419,9 +420,8 @@
         bits = NULL;
         unlock(buffer);
     }
-    // enqueue the last frame
-    nativeWindow->queueBuffer(nativeWindow, buffer, -1);
     if (buffer) {
+        nativeWindow->cancelBuffer(nativeWindow, buffer, -1);
         buffer->common.decRef(&buffer->common);
         buffer = 0;
     }
@@ -1580,11 +1580,12 @@
         if (surface->dpy != dpy)
             return setError(EGL_BAD_DISPLAY, EGL_FALSE);
         if (surface->ctx) {
-            // FIXME: this surface is current check what the spec says
+            // defer disconnect/delete until no longer current
+            surface->zombie = true;
+        } else {
             surface->disconnect();
-            surface->ctx = 0;
+            delete surface;
         }
-        delete surface;
     }
     return EGL_TRUE;
 }
@@ -1736,6 +1737,9 @@
             if (c->draw) {
                 egl_surface_t* s = reinterpret_cast<egl_surface_t*>(c->draw);
                 s->disconnect();
+                s->ctx = EGL_NO_CONTEXT;
+                if (s->zombie)
+                    delete s;
             }
             if (c->read) {
                 // FIXME: unlock/disconnect the read surface too 
@@ -1777,8 +1781,10 @@
                 egl_surface_t* r = (egl_surface_t*)c->read;
                 if (d) {
                     c->draw = 0;
-                    d->ctx = EGL_NO_CONTEXT;
                     d->disconnect();
+                    d->ctx = EGL_NO_CONTEXT;
+                    if (d->zombie)
+                        delete d;
                 }
                 if (r) {
                     c->read = 0;
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index ed9db94..978ab04 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -1307,6 +1307,28 @@
     return result;
 }
 
+EGLBoolean eglPresentationTimeANDROID(EGLDisplay dpy, EGLSurface surface,
+        EGLnsecsANDROID time)
+{
+    clearError();
+
+    const egl_display_ptr dp = validate_display(dpy);
+    if (!dp) {
+        return EGL_FALSE;
+    }
+
+    SurfaceRef _s(dp.get(), surface);
+    if (!_s.get()) {
+        setError(EGL_BAD_SURFACE, EGL_FALSE);
+        return EGL_FALSE;
+    }
+
+    egl_surface_t const * const s = get_surface(surface);
+    native_window_set_buffers_timestamp(s->win.get(), time);
+
+    return EGL_TRUE;
+}
+
 // ----------------------------------------------------------------------------
 // NVIDIA extensions
 // ----------------------------------------------------------------------------
diff --git a/opengl/tests/gl2_yuvtex/Android.mk b/opengl/tests/gl2_yuvtex/Android.mk
index 7d43759..bb3cc0c 100644
--- a/opengl/tests/gl2_yuvtex/Android.mk
+++ b/opengl/tests/gl2_yuvtex/Android.mk
@@ -5,9 +5,10 @@
 	gl2_yuvtex.cpp
 
 LOCAL_SHARED_LIBRARIES := \
-	libcutils \
+    libcutils \
     libEGL \
     libGLESv2 \
+    libutils \
     libui
 
 LOCAL_C_INCLUDES += $(call include-path-for, opengl-tests-includes)
diff --git a/opengl/tests/gl_yuvtex/Android.mk b/opengl/tests/gl_yuvtex/Android.mk
index 9e5dba0..e0e2c16 100644
--- a/opengl/tests/gl_yuvtex/Android.mk
+++ b/opengl/tests/gl_yuvtex/Android.mk
@@ -5,9 +5,10 @@
 	gl_yuvtex.cpp
 
 LOCAL_SHARED_LIBRARIES := \
-	libcutils \
+    libcutils \
     libEGL \
     libGLESv1_CM \
+    libutils \
     libui
 
 LOCAL_C_INCLUDES += $(call include-path-for, opengl-tests-includes)
diff --git a/opengl/tests/hwc/Android.mk b/opengl/tests/hwc/Android.mk
index 9eb58b1..177eb63 100644
--- a/opengl/tests/hwc/Android.mk
+++ b/opengl/tests/hwc/Android.mk
@@ -39,6 +39,7 @@
     libcutils \
     libEGL \
     libGLESv2 \
+    libutils \
     libui \
     libhardware \
 
@@ -70,6 +71,7 @@
     libcutils \
     libEGL \
     libGLESv2 \
+    libutils \
     libui \
     libhardware \
 
@@ -99,6 +101,7 @@
     libcutils \
     libEGL \
     libGLESv2 \
+    libutils \
     libui \
     libhardware \
 
@@ -128,6 +131,7 @@
     libcutils \
     libEGL \
     libGLESv2 \
+    libutils \
     libui \
     libhardware \
 
diff --git a/opengl/tools/glgen/specs/egl/EGL14.spec b/opengl/tools/glgen/specs/egl/EGL14.spec
index 828e114..aef0bcb 100644
--- a/opengl/tools/glgen/specs/egl/EGL14.spec
+++ b/opengl/tools/glgen/specs/egl/EGL14.spec
@@ -31,3 +31,4 @@
 EGLBoolean eglWaitNative ( EGLint engine )
 EGLBoolean eglSwapBuffers ( EGLDisplay dpy, EGLSurface surface )
 EGLBoolean eglCopyBuffers ( EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target )
+EGLBoolean eglPresentationTimeANDROID ( EGLDisplay dpy, EGLSurface sur, EGLnsecsANDROID time )
diff --git a/opengl/tools/glgen/src/JType.java b/opengl/tools/glgen/src/JType.java
index 3f7cb73..994e609 100644
--- a/opengl/tools/glgen/src/JType.java
+++ b/opengl/tools/glgen/src/JType.java
@@ -56,6 +56,7 @@
     typeMapping.put(new CType("EGLNativeWindowType"), new JType("int"));
     typeMapping.put(new CType("EGLNativeDisplayType"), new JType("int"));
     typeMapping.put(new CType("EGLClientBuffer"), new JType("int"));
+    typeMapping.put(new CType("EGLnsecsANDROID"), new JType("long"));
 
     // EGL nonprimitive types
     typeMapping.put(new CType("EGLConfig"), new JType("EGLConfig", true, false));
diff --git a/opengl/tools/glgen/src/JniCodeEmitter.java b/opengl/tools/glgen/src/JniCodeEmitter.java
index 01c5c48..ffe3767 100644
--- a/opengl/tools/glgen/src/JniCodeEmitter.java
+++ b/opengl/tools/glgen/src/JniCodeEmitter.java
@@ -54,7 +54,7 @@
         } else if (baseType.equals("short")) {
             jniName += "S";
         } else if (baseType.equals("long")) {
-            jniName += "L";
+            jniName += "J";
         } else if (baseType.equals("byte")) {
             jniName += "B";
         } else if (baseType.equals("String")) {
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index b4b19b4..30a01be 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -2,24 +2,23 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:= \
-    Client.cpp                              \
-    DisplayDevice.cpp                       \
-    EventThread.cpp                         \
-    FrameTracker.cpp                        \
-    Layer.cpp                               \
-    LayerBase.cpp                           \
-    LayerDim.cpp                            \
-    LayerScreenshot.cpp                     \
-    DisplayHardware/FramebufferSurface.cpp  \
-    DisplayHardware/HWComposer.cpp          \
-    DisplayHardware/PowerHAL.cpp            \
-    GLExtensions.cpp                        \
-    MessageQueue.cpp                        \
-    SurfaceFlinger.cpp                      \
-    SurfaceFlingerConsumer.cpp              \
-    SurfaceTextureLayer.cpp                 \
-    Transform.cpp                           \
-    
+    Client.cpp \
+    DisplayDevice.cpp \
+    EventThread.cpp \
+    FrameTracker.cpp \
+    GLExtensions.cpp \
+    Layer.cpp \
+    LayerDim.cpp \
+    MessageQueue.cpp \
+    SurfaceFlinger.cpp \
+    SurfaceFlingerConsumer.cpp \
+    SurfaceTextureLayer.cpp \
+    Transform.cpp \
+    DisplayHardware/BufferQueueInterposer.cpp \
+    DisplayHardware/FramebufferSurface.cpp \
+    DisplayHardware/HWComposer.cpp \
+    DisplayHardware/PowerHAL.cpp \
+    DisplayHardware/VirtualDisplaySurface.cpp \
 
 LOCAL_CFLAGS:= -DLOG_TAG=\"SurfaceFlinger\"
 LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
diff --git a/services/surfaceflinger/Client.cpp b/services/surfaceflinger/Client.cpp
index 0f56f99..dd65348 100644
--- a/services/surfaceflinger/Client.cpp
+++ b/services/surfaceflinger/Client.cpp
@@ -23,7 +23,6 @@
 
 #include "Client.h"
 #include "Layer.h"
-#include "LayerBase.h"
 #include "SurfaceFlinger.h"
 
 namespace android {
@@ -43,7 +42,7 @@
 {
     const size_t count = mLayers.size();
     for (size_t i=0 ; i<count ; i++) {
-        sp<LayerBaseClient> layer(mLayers.valueAt(i).promote());
+        sp<Layer> layer(mLayers.valueAt(i).promote());
         if (layer != 0) {
             mFlinger->removeLayer(layer);
         }
@@ -54,13 +53,13 @@
     return NO_ERROR;
 }
 
-void Client::attachLayer(const sp<IBinder>& handle, const sp<LayerBaseClient>& layer)
+void Client::attachLayer(const sp<IBinder>& handle, const sp<Layer>& layer)
 {
     Mutex::Autolock _l(mLock);
     mLayers.add(handle, layer);
 }
 
-void Client::detachLayer(const LayerBaseClient* layer)
+void Client::detachLayer(const Layer* layer)
 {
     Mutex::Autolock _l(mLock);
     // we do a linear search here, because this doesn't happen often
@@ -72,11 +71,11 @@
         }
     }
 }
-sp<LayerBaseClient> Client::getLayerUser(const sp<IBinder>& handle) const
+sp<Layer> Client::getLayerUser(const sp<IBinder>& handle) const
 {
     Mutex::Autolock _l(mLock);
-    sp<LayerBaseClient> lbc;
-    wp<LayerBaseClient> layer(mLayers.valueFor(handle));
+    sp<Layer> lbc;
+    wp<Layer> layer(mLayers.valueFor(handle));
     if (layer != 0) {
         lbc = layer.promote();
         ALOGE_IF(lbc==0, "getLayerUser(name=%p) is dead", handle.get());
@@ -106,10 +105,11 @@
 }
 
 
-sp<ISurface> Client::createSurface(
+status_t Client::createSurface(
         const String8& name,
-        uint32_t w, uint32_t h, PixelFormat format,
-        uint32_t flags)
+        uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
+        sp<IBinder>* handle,
+        sp<IGraphicBufferProducer>* gbp)
 {
     /*
      * createSurface must be called from the GL thread so that it can
@@ -117,9 +117,11 @@
      */
 
     class MessageCreateLayer : public MessageBase {
-        sp<ISurface> result;
         SurfaceFlinger* flinger;
         Client* client;
+        sp<IBinder>* handle;
+        sp<IGraphicBufferProducer>* gbp;
+        status_t result;
         const String8& name;
         uint32_t w, h;
         PixelFormat format;
@@ -127,21 +129,23 @@
     public:
         MessageCreateLayer(SurfaceFlinger* flinger,
                 const String8& name, Client* client,
-                uint32_t w, uint32_t h, PixelFormat format,
-                uint32_t flags)
-            : flinger(flinger), client(client), name(name),
-              w(w), h(h), format(format), flags(flags)
-        {
+                uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
+                sp<IBinder>* handle,
+                sp<IGraphicBufferProducer>* gbp)
+            : flinger(flinger), client(client),
+              handle(handle), gbp(gbp),
+              name(name), w(w), h(h), format(format), flags(flags) {
         }
-        sp<ISurface> getResult() const { return result; }
+        status_t getResult() const { return result; }
         virtual bool handler() {
-            result = flinger->createLayer(name, client, w, h, format, flags);
+            result = flinger->createLayer(name, client, w, h, format, flags,
+                    handle, gbp);
             return true;
         }
     };
 
     sp<MessageBase> msg = new MessageCreateLayer(mFlinger.get(),
-            name, this, w, h, format, flags);
+            name, this, w, h, format, flags, handle, gbp);
     mFlinger->postMessageSync(msg);
     return static_cast<MessageCreateLayer*>( msg.get() )->getResult();
 }
diff --git a/services/surfaceflinger/Client.h b/services/surfaceflinger/Client.h
index e6a7165..84e649f 100644
--- a/services/surfaceflinger/Client.h
+++ b/services/surfaceflinger/Client.h
@@ -30,7 +30,7 @@
 
 // ---------------------------------------------------------------------------
 
-class LayerBaseClient;
+class Layer;
 class SurfaceFlinger;
 
 // ---------------------------------------------------------------------------
@@ -44,18 +44,19 @@
     status_t initCheck() const;
 
     // protected by SurfaceFlinger::mStateLock
-    void attachLayer(const sp<IBinder>& handle, const sp<LayerBaseClient>& layer);
+    void attachLayer(const sp<IBinder>& handle, const sp<Layer>& layer);
 
-    void detachLayer(const LayerBaseClient* layer);
+    void detachLayer(const Layer* layer);
 
-    sp<LayerBaseClient> getLayerUser(const sp<IBinder>& handle) const;
+    sp<Layer> getLayerUser(const sp<IBinder>& handle) const;
 
 private:
     // ISurfaceComposerClient interface
-    virtual sp<ISurface> createSurface(
+    virtual status_t createSurface(
             const String8& name,
-            uint32_t w, uint32_t h,PixelFormat format,
-            uint32_t flags);
+            uint32_t w, uint32_t h,PixelFormat format, uint32_t flags,
+            sp<IBinder>* handle,
+            sp<IGraphicBufferProducer>* gbp);
 
     virtual status_t destroySurface(const sp<IBinder>& handle);
 
@@ -66,7 +67,7 @@
     sp<SurfaceFlinger> mFlinger;
 
     // protected by mLock
-    DefaultKeyedVector< wp<IBinder>, wp<LayerBaseClient> > mLayers;
+    DefaultKeyedVector< wp<IBinder>, wp<Layer> > mLayers;
 
     // thread-safe
     mutable Mutex mLock;
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 9466944..ecd12d0 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -35,14 +35,14 @@
 
 #include <hardware/gralloc.h>
 
-#include "DisplayHardware/FramebufferSurface.h"
+#include "DisplayHardware/DisplaySurface.h"
 #include "DisplayHardware/HWComposer.h"
 
 #include "clz.h"
 #include "DisplayDevice.h"
 #include "GLExtensions.h"
 #include "SurfaceFlinger.h"
-#include "LayerBase.h"
+#include "Layer.h"
 
 // ----------------------------------------------------------------------------
 using namespace android;
@@ -72,14 +72,12 @@
         DisplayType type,
         bool isSecure,
         const wp<IBinder>& displayToken,
-        const sp<ANativeWindow>& nativeWindow,
-        const sp<FramebufferSurface>& framebufferSurface,
+        const sp<DisplaySurface>& displaySurface,
         EGLConfig config)
     : mFlinger(flinger),
       mType(type), mHwcDisplayId(-1),
       mDisplayToken(displayToken),
-      mNativeWindow(nativeWindow),
-      mFramebufferSurface(framebufferSurface),
+      mDisplaySurface(displaySurface),
       mDisplay(EGL_NO_DISPLAY),
       mSurface(EGL_NO_SURFACE),
       mContext(EGL_NO_CONTEXT),
@@ -89,9 +87,10 @@
       mIsSecure(isSecure),
       mSecureLayerVisible(false),
       mScreenAcquired(false),
-      mLayerStack(0),
+      mLayerStack(NO_LAYER_STACK),
       mOrientation()
 {
+    mNativeWindow = new Surface(mDisplaySurface->getIGraphicBufferProducer());
     init(config);
 }
 
@@ -183,10 +182,7 @@
 }
 
 status_t DisplayDevice::compositionComplete() const {
-    if (mFramebufferSurface == NULL) {
-        return NO_ERROR;
-    }
-    return mFramebufferSurface->compositionComplete();
+    return mDisplaySurface->compositionComplete();
 }
 
 void DisplayDevice::flip(const Region& dirty) const
@@ -196,58 +192,51 @@
     EGLDisplay dpy = mDisplay;
     EGLSurface surface = mSurface;
 
-#ifdef EGL_ANDROID_swap_rectangle    
+#ifdef EGL_ANDROID_swap_rectangle
     if (mFlags & SWAP_RECTANGLE) {
         const Region newDirty(dirty.intersect(bounds()));
         const Rect b(newDirty.getBounds());
         eglSetSwapRectangleANDROID(dpy, surface,
                 b.left, b.top, b.width(), b.height());
-    } 
+    }
 #endif
 
     mPageFlipCount++;
 }
 
 void DisplayDevice::swapBuffers(HWComposer& hwc) const {
-    EGLBoolean success = EGL_TRUE;
-    if (hwc.initCheck() != NO_ERROR) {
-        // no HWC, we call eglSwapBuffers()
-        success = eglSwapBuffers(mDisplay, mSurface);
-    } else {
-        // We have a valid HWC, but not all displays can use it, in particular
-        // the virtual displays are on their own.
-        // TODO: HWC 1.2 will allow virtual displays
-        if (mType >= DisplayDevice::DISPLAY_VIRTUAL) {
-            // always call eglSwapBuffers() for virtual displays
-            success = eglSwapBuffers(mDisplay, mSurface);
-        } else if (hwc.supportsFramebufferTarget()) {
-            // as of hwc 1.1 we always call eglSwapBuffers if we have some
-            // GLES layers
-            if (hwc.hasGlesComposition(mType)) {
-                success = eglSwapBuffers(mDisplay, mSurface);
+    // We need to call eglSwapBuffers() unless:
+    // (a) there was no GLES composition this frame, or
+    // (b) we're using a legacy HWC with no framebuffer target support (in
+    //     which case HWComposer::commit() handles things).
+    if (hwc.initCheck() != NO_ERROR ||
+            (hwc.hasGlesComposition(mHwcDisplayId) &&
+             hwc.supportsFramebufferTarget())) {
+        EGLBoolean success = eglSwapBuffers(mDisplay, mSurface);
+        if (!success) {
+            EGLint error = eglGetError();
+            if (error == EGL_CONTEXT_LOST ||
+                    mType == DisplayDevice::DISPLAY_PRIMARY) {
+                LOG_ALWAYS_FATAL("eglSwapBuffers(%p, %p) failed with 0x%08x",
+                        mDisplay, mSurface, error);
+            } else {
+                ALOGE("eglSwapBuffers(%p, %p) failed with 0x%08x",
+                        mDisplay, mSurface, error);
             }
-        } else {
-            // HWC doesn't have the framebuffer target, we don't call
-            // eglSwapBuffers(), since this is handled by HWComposer::commit().
         }
     }
 
-    if (!success) {
-        EGLint error = eglGetError();
-        if (error == EGL_CONTEXT_LOST ||
-                mType == DisplayDevice::DISPLAY_PRIMARY) {
-            LOG_ALWAYS_FATAL("eglSwapBuffers(%p, %p) failed with 0x%08x",
-                    mDisplay, mSurface, error);
-        }
+    status_t result = mDisplaySurface->advanceFrame();
+    if (result != NO_ERROR) {
+        ALOGE("[%s] failed pushing new frame to HWC: %d",
+                mDisplayName.string(), result);
     }
 }
 
 void DisplayDevice::onSwapBuffersCompleted(HWComposer& hwc) const {
     if (hwc.initCheck() == NO_ERROR) {
-        if (hwc.supportsFramebufferTarget()) {
-            int fd = hwc.getAndResetReleaseFenceFd(mType);
-            mFramebufferSurface->setReleaseFenceFd(fd);
-        }
+        int fd = hwc.getAndResetReleaseFenceFd(mType);
+        mDisplaySurface->setReleaseFenceFd(fd);
     }
 }
 
@@ -282,18 +271,19 @@
 
 // ----------------------------------------------------------------------------
 
-void DisplayDevice::setVisibleLayersSortedByZ(const Vector< sp<LayerBase> >& layers) {
+void DisplayDevice::setVisibleLayersSortedByZ(const Vector< sp<Layer> >& layers) {
     mVisibleLayersSortedByZ = layers;
     mSecureLayerVisible = false;
     size_t count = layers.size();
     for (size_t i=0 ; i<count ; i++) {
-        if (layers[i]->isSecure()) {
+        const sp<Layer>& layer(layers[i]);
+        if (layer->isSecure()) {
             mSecureLayerVisible = true;
         }
     }
 }
 
-const Vector< sp<LayerBase> >& DisplayDevice::getVisibleLayersSortedByZ() const {
+const Vector< sp<Layer> >& DisplayDevice::getVisibleLayersSortedByZ() const {
     return mVisibleLayersSortedByZ;
 }
 
@@ -365,74 +355,72 @@
 }
 
 void DisplayDevice::setProjection(int orientation,
-        const Rect& viewport, const Rect& frame) {
+        const Rect& newViewport, const Rect& newFrame) {
+    Rect viewport(newViewport);
+    Rect frame(newFrame);
+
+    const int w = mDisplayWidth;
+    const int h = mDisplayHeight;
+
+    Transform R;
+    DisplayDevice::orientationToTransfrom(orientation, w, h, &R);
+
+    if (!frame.isValid()) {
+        // the destination frame can be invalid if it has never been set,
+        // in that case we assume the whole display frame.
+        frame = Rect(w, h);
+    }
+
+    if (viewport.isEmpty()) {
+        // viewport can be invalid if it has never been set, in that case
+        // we assume the whole display size.
+        // it's also invalid to have an empty viewport, so we handle that
+        // case in the same way.
+        viewport = Rect(w, h);
+        if (R.getOrientation() & Transform::ROT_90) {
+            // viewport is always specified in the logical orientation
+            // of the display (ie: post-rotation).
+            swap(viewport.right, viewport.bottom);
+        }
+    }
+
+    dirtyRegion.set(getBounds());
+
+    Transform TL, TP, S;
+    float src_width  = viewport.width();
+    float src_height = viewport.height();
+    float dst_width  = frame.width();
+    float dst_height = frame.height();
+    if (src_width != dst_width || src_height != dst_height) {
+        float sx = dst_width  / src_width;
+        float sy = dst_height / src_height;
+        S.set(sx, 0, 0, sy);
+    }
+
+    float src_x = viewport.left;
+    float src_y = viewport.top;
+    float dst_x = frame.left;
+    float dst_y = frame.top;
+    TL.set(-src_x, -src_y);
+    TP.set(dst_x, dst_y);
+
+    // The viewport and frame are both in the logical orientation.
+    // Apply the logical translation, scale to physical size, apply the
+    // physical translation and finally rotate to the physical orientation.
+    mGlobalTransform = R * TP * S * TL;
+
+    const uint8_t type = mGlobalTransform.getType();
+    mNeedsFiltering = (!mGlobalTransform.preserveRects() ||
+            (type >= Transform::SCALE));
+
+    mScissor = mGlobalTransform.transform(viewport);
+    if (mScissor.isEmpty()) {
+        mScissor.set(getBounds());
+    }
+
     mOrientation = orientation;
     mViewport = viewport;
     mFrame = frame;
-    updateGeometryTransform();
-}
-
-void DisplayDevice::updateGeometryTransform() {
-    int w = mDisplayWidth;
-    int h = mDisplayHeight;
-    Transform TL, TP, R, S;
-    if (DisplayDevice::orientationToTransfrom(
-            mOrientation, w, h, &R) == NO_ERROR) {
-        dirtyRegion.set(bounds());
-
-        Rect viewport(mViewport);
-        Rect frame(mFrame);
-
-        if (!frame.isValid()) {
-            // the destination frame can be invalid if it has never been set,
-            // in that case we assume the whole display frame.
-            frame = Rect(w, h);
-        }
-
-        if (viewport.isEmpty()) {
-            // viewport can be invalid if it has never been set, in that case
-            // we assume the whole display size.
-            // it's also invalid to have an empty viewport, so we handle that
-            // case in the same way.
-            viewport = Rect(w, h);
-            if (R.getOrientation() & Transform::ROT_90) {
-                // viewport is always specified in the logical orientation
-                // of the display (ie: post-rotation).
-                swap(viewport.right, viewport.bottom);
-            }
-        }
-
-        float src_width  = viewport.width();
-        float src_height = viewport.height();
-        float dst_width  = frame.width();
-        float dst_height = frame.height();
-        if (src_width != dst_width || src_height != dst_height) {
-            float sx = dst_width  / src_width;
-            float sy = dst_height / src_height;
-            S.set(sx, 0, 0, sy);
-        }
-
-        float src_x = viewport.left;
-        float src_y = viewport.top;
-        float dst_x = frame.left;
-        float dst_y = frame.top;
-        TL.set(-src_x, -src_y);
-        TP.set(dst_x, dst_y);
-
-        // The viewport and frame are both in the logical orientation.
-        // Apply the logical translation, scale to physical size, apply the
-        // physical translation and finally rotate to the physical orientation.
-        mGlobalTransform = R * TP * S * TL;
-
-        const uint8_t type = mGlobalTransform.getType();
-        mNeedsFiltering = (!mGlobalTransform.preserveRects() ||
-                (type >= Transform::SCALE));
-
-        mScissor = mGlobalTransform.transform(mViewport);
-        if (mScissor.isEmpty()) {
-            mScissor.set(getBounds());
-        }
-    }
 }
 
 void DisplayDevice::dump(String8& result, char* buffer, size_t SIZE) const {
@@ -456,9 +444,7 @@
 
     result.append(buffer);
 
-    String8 fbtargetDump;
-    if (mFramebufferSurface != NULL) {
-        mFramebufferSurface->dump(fbtargetDump);
-        result.append(fbtargetDump);
-    }
+    String8 surfaceDump;
+    mDisplaySurface->dump(surfaceDump);
+    result.append(surfaceDump);
 }
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index bb6eb70..d8f55b4 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -37,8 +37,8 @@
 namespace android {
 
 class DisplayInfo;
-class FramebufferSurface;
-class LayerBase;
+class DisplaySurface;
+class Layer;
 class SurfaceFlinger;
 class HWComposer;
 
@@ -65,13 +65,16 @@
         SWAP_RECTANGLE  = 0x00080000,
     };
 
+    enum {
+        NO_LAYER_STACK = 0xFFFFFFFF,
+    };
+
     DisplayDevice(
             const sp<SurfaceFlinger>& flinger,
             DisplayType type,
             bool isSecure,
             const wp<IBinder>& displayToken,
-            const sp<ANativeWindow>& nativeWindow,
-            const sp<FramebufferSurface>& framebufferSurface,
+            const sp<DisplaySurface>& displaySurface,
             EGLConfig config);
 
     ~DisplayDevice();
@@ -95,8 +98,8 @@
 
     EGLSurface  getEGLSurface() const;
 
-    void                    setVisibleLayersSortedByZ(const Vector< sp<LayerBase> >& layers);
-    const Vector< sp<LayerBase> >& getVisibleLayersSortedByZ() const;
+    void                    setVisibleLayersSortedByZ(const Vector< sp<Layer> >& layers);
+    const Vector< sp<Layer> >& getVisibleLayersSortedByZ() const;
     bool                    getSecureLayerVisible() const;
     Region                  getDirtyRegion(bool repaintEverything) const;
 
@@ -105,8 +108,8 @@
 
     int                     getOrientation() const { return mOrientation; }
     const Transform&        getTransform() const { return mGlobalTransform; }
-    const Rect&             getViewport() const { return mViewport; }
-    const Rect&             getFrame() const { return mFrame; }
+    const Rect              getViewport() const { return mViewport; }
+    const Rect              getFrame() const { return mFrame; }
     const Rect&             getScissor() const { return mScissor; }
     bool                    needsFiltering() const { return mNeedsFiltering; }
 
@@ -117,7 +120,7 @@
 
     void swapBuffers(HWComposer& hwc) const;
     status_t compositionComplete() const;
-    
+
     // called after h/w composer has completed its set() call
     void onSwapBuffersCompleted(HWComposer& hwc) const;
 
@@ -161,9 +164,7 @@
 
     // ANativeWindow this display is rendering into
     sp<ANativeWindow> mNativeWindow;
-
-    // set if mNativeWindow is a FramebufferSurface
-    sp<FramebufferSurface> mFramebufferSurface;
+    sp<DisplaySurface> mDisplaySurface;
 
     EGLDisplay      mDisplay;
     EGLSurface      mSurface;
@@ -182,7 +183,7 @@
      */
 
     // list of visible layers on that display
-    Vector< sp<LayerBase> > mVisibleLayersSortedByZ;
+    Vector< sp<Layer> > mVisibleLayersSortedByZ;
 
     // Whether we have a visible secure layer on this display
     bool mSecureLayerVisible;
@@ -197,8 +198,6 @@
     static status_t orientationToTransfrom(int orientation,
             int w, int h, Transform* tr);
 
-    void updateGeometryTransform();
-
     uint32_t mLayerStack;
     int mOrientation;
     // user-provided visible area of the layer stack
diff --git a/services/surfaceflinger/DisplayHardware/BufferQueueInterposer.cpp b/services/surfaceflinger/DisplayHardware/BufferQueueInterposer.cpp
new file mode 100644
index 0000000..d8ad224
--- /dev/null
+++ b/services/surfaceflinger/DisplayHardware/BufferQueueInterposer.cpp
@@ -0,0 +1,238 @@
+/*
+ * 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.
+ */
+
+#undef LOG_TAG
+#define LOG_TAG "BQInterposer"
+
+#include "BufferQueueInterposer.h"
+
+// ---------------------------------------------------------------------------
+namespace android {
+// ---------------------------------------------------------------------------
+
+#define BQI_LOGV(x, ...) ALOGV("[%s] "x, mName.string(), ##__VA_ARGS__)
+#define BQI_LOGD(x, ...) ALOGD("[%s] "x, mName.string(), ##__VA_ARGS__)
+#define BQI_LOGI(x, ...) ALOGI("[%s] "x, mName.string(), ##__VA_ARGS__)
+#define BQI_LOGW(x, ...) ALOGW("[%s] "x, mName.string(), ##__VA_ARGS__)
+#define BQI_LOGE(x, ...) ALOGE("[%s] "x, mName.string(), ##__VA_ARGS__)
+
+// Get an ID that's unique within this process.
+static int32_t createProcessUniqueId() {
+    static volatile int32_t globalCounter = 0;
+    return android_atomic_inc(&globalCounter);
+}
+
+BufferQueueInterposer::BufferQueueInterposer(
+        const sp<IGraphicBufferProducer>& sink, const String8& name)
+:   mSink(sink),
+    mName(name),
+    mAcquired(false)
+{
+    BQI_LOGV("BufferQueueInterposer sink=%p", sink.get());
+
+    // We need one additional dequeued buffer beyond what the source needs.
+    // To have more than one (the default), we must call setBufferCount. But
+    // we have no way of knowing what the sink has set as the minimum buffer
+    // count, so if we just call setBufferCount(3) it may fail (and does, on
+    // one device using a video encoder sink). So far on the devices we care
+    // about, this is the smallest value that works.
+    //
+    // TODO: Change IGraphicBufferProducer and implementations to support this.
+    // Maybe change it so both the consumer and producer declare how many
+    // buffers they need, and the IGBP adds them? Then BQInterposer would just
+    // add 1 to the source's buffer count.
+    mSink->setBufferCount(6);
+}
+
+BufferQueueInterposer::~BufferQueueInterposer() {
+    Mutex::Autolock lock(mMutex);
+    flushQueuedBuffersLocked();
+    BQI_LOGV("~BufferQueueInterposer");
+}
+
+status_t BufferQueueInterposer::requestBuffer(int slot,
+        sp<GraphicBuffer>* outBuf) {
+    BQI_LOGV("requestBuffer slot=%d", slot);
+    Mutex::Autolock lock(mMutex);
+
+    if (size_t(slot) >= mBuffers.size()) {
+        size_t size = mBuffers.size();
+        mBuffers.insertAt(size, size - slot + 1);
+    }
+    sp<GraphicBuffer>& buf = mBuffers.editItemAt(slot);
+
+    status_t result = mSink->requestBuffer(slot, &buf);
+    *outBuf = buf;
+    return result;
+}
+
+status_t BufferQueueInterposer::setBufferCount(int bufferCount) {
+    BQI_LOGV("setBufferCount count=%d", bufferCount);
+    Mutex::Autolock lock(mMutex);
+
+    bufferCount += 1;
+
+    status_t result = flushQueuedBuffersLocked();
+    if (result != NO_ERROR)
+        return result;
+
+    result = mSink->setBufferCount(bufferCount);
+    if (result != NO_ERROR)
+        return result;
+
+    for (size_t i = 0; i < mBuffers.size(); i++)
+        mBuffers.editItemAt(i).clear();
+    ssize_t n = mBuffers.resize(bufferCount);
+    result = (n < 0) ? n : result;
+
+    return result;
+}
+
+status_t BufferQueueInterposer::dequeueBuffer(int* slot, sp<Fence>* fence,
+            uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
+    BQI_LOGV("dequeueBuffer %ux%u fmt=%u usage=%#x", w, h, format, usage);
+    return mSink->dequeueBuffer(slot, fence, w, h, format, usage);
+}
+
+status_t BufferQueueInterposer::queueBuffer(int slot,
+            const QueueBufferInput& input, QueueBufferOutput* output) {
+    BQI_LOGV("queueBuffer slot=%d", slot);
+    Mutex::Autolock lock(mMutex);
+    mQueue.push(QueuedBuffer(slot, input));
+    *output = mQueueBufferOutput;
+    return NO_ERROR;
+}
+
+void BufferQueueInterposer::cancelBuffer(int slot, const sp<Fence>& fence) {
+    BQI_LOGV("cancelBuffer slot=%d", slot);
+    mSink->cancelBuffer(slot, fence);
+}
+
+int BufferQueueInterposer::query(int what, int* value) {
+    BQI_LOGV("query what=%d", what);
+    return mSink->query(what, value);
+}
+
+status_t BufferQueueInterposer::setSynchronousMode(bool enabled) {
+    BQI_LOGV("setSynchronousMode %s", enabled ? "true" : "false");
+    return mSink->setSynchronousMode(enabled);
+}
+
+status_t BufferQueueInterposer::connect(int api, QueueBufferOutput* output) {
+    BQI_LOGV("connect api=%d", api);
+    Mutex::Autolock lock(mMutex);
+    status_t result = mSink->connect(api, &mQueueBufferOutput);
+    if (result == NO_ERROR) {
+        *output = mQueueBufferOutput;
+    }
+    return result;
+}
+
+status_t BufferQueueInterposer::disconnect(int api) {
+    BQI_LOGV("disconnect: api=%d", api);
+    Mutex::Autolock lock(mMutex);
+    flushQueuedBuffersLocked();
+    return mSink->disconnect(api);
+}
+
+status_t BufferQueueInterposer::pullEmptyBuffer() {
+    status_t result;
+
+    int slot;
+    sp<Fence> fence;
+    result = dequeueBuffer(&slot, &fence, 0, 0, 0, 0);
+    if (result == IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) {
+        sp<GraphicBuffer> buffer;
+        result = requestBuffer(slot, &buffer);
+    } else if (result != NO_ERROR) {
+        return result;
+    }
+
+    uint32_t w, h, transformHint, numPendingBuffers;
+    mQueueBufferOutput.deflate(&w, &h, &transformHint, &numPendingBuffers);
+
+    IGraphicBufferProducer::QueueBufferInput qbi(0, Rect(w, h),
+            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, fence);
+    IGraphicBufferProducer::QueueBufferOutput qbo;
+    result = queueBuffer(slot, qbi, &qbo);
+    if (result != NO_ERROR)
+        return result;
+
+    return NO_ERROR;
+}
+
+status_t BufferQueueInterposer::acquireBuffer(sp<GraphicBuffer>* buf,
+        sp<Fence>* fence) {
+    Mutex::Autolock lock(mMutex);
+    if (mQueue.empty()) {
+        BQI_LOGV("acquireBuffer: no buffers available");
+        return NO_BUFFER_AVAILABLE;
+    }
+    if (mAcquired) {
+        BQI_LOGE("acquireBuffer: buffer already acquired");
+        return BUFFER_ALREADY_ACQUIRED;
+    }
+    BQI_LOGV("acquireBuffer: acquiring slot %d", mQueue[0].slot);
+
+    *buf = mBuffers[mQueue[0].slot];
+    *fence = mQueue[0].fence;
+    mAcquired = true;
+    return NO_ERROR;
+}
+
+status_t BufferQueueInterposer::releaseBuffer(const sp<Fence>& fence) {
+    Mutex::Autolock lock(mMutex);
+    if (!mAcquired) {
+        BQI_LOGE("releaseBuffer: releasing a non-acquired buffer");
+        return BUFFER_NOT_ACQUIRED;
+    }
+    BQI_LOGV("releaseBuffer: releasing slot %d to sink", mQueue[0].slot);
+
+    const QueuedBuffer& b = mQueue[0];
+    status_t result = mSink->queueBuffer(b.slot,
+            QueueBufferInput(b.timestamp, b.crop, b.scalingMode,
+                b.transform, b.fence),
+            &mQueueBufferOutput);
+    mQueue.removeAt(0);
+    mAcquired = false;
+
+    return result;
+}
+
+status_t BufferQueueInterposer::flushQueuedBuffersLocked() {
+    if (mAcquired) {
+        BQI_LOGE("flushQueuedBuffersLocked: buffer acquired, can't flush");
+        return INVALID_OPERATION;
+    }
+
+    status_t result = NO_ERROR;
+    for (size_t i = 0; i < mQueue.size(); i++) {
+        const QueuedBuffer& b = mQueue[i];
+        BQI_LOGV("flushing queued slot %d to sink", b.slot);
+        status_t err = mSink->queueBuffer(b.slot,
+                QueueBufferInput(b.timestamp, b.crop, b.scalingMode,
+                    b.transform, b.fence),
+                &mQueueBufferOutput);
+        if (err != NO_ERROR && result == NO_ERROR) // latch first error
+            result = err;
+    }
+    mQueue.clear();
+    return result;
+}
+
+// ---------------------------------------------------------------------------
+} // namespace android
+// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/DisplayHardware/BufferQueueInterposer.h b/services/surfaceflinger/DisplayHardware/BufferQueueInterposer.h
new file mode 100644
index 0000000..7208630
--- /dev/null
+++ b/services/surfaceflinger/DisplayHardware/BufferQueueInterposer.h
@@ -0,0 +1,152 @@
+/*
+ * 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_SF_BUFFERQUEUEINTERPOSER_H
+#define ANDROID_SF_BUFFERQUEUEINTERPOSER_H
+
+#include <gui/IGraphicBufferProducer.h>
+#include <utils/Mutex.h>
+#include <utils/Vector.h>
+
+// ---------------------------------------------------------------------------
+namespace android {
+// ---------------------------------------------------------------------------
+
+// BufferQueueInterposers introduce an extra stage between a buffer producer
+// (the source) and a buffer consumer (the sink), which communicate via the
+// IGraphicBufferProducer interface. It is designed to be as transparent as
+// possible to both endpoints, so that they can work the same whether an
+// interposer is present or not.
+//
+// When the interpose is present, the source queues buffers to the
+// IGraphicBufferProducer implemented by BufferQueueInterposer. A client of
+// the BufferQueueInterposer can acquire each buffer in turn and read or
+// modify it, releasing the buffer when finished. When the buffer is released,
+// the BufferQueueInterposer queues it to the original IGraphicBufferProducer
+// interface representing the sink.
+//
+// A BufferQueueInterposer can be used to do additional rendering to a buffer
+// before it is consumed -- essentially pipelining two producers. As an
+// example, SurfaceFlinger uses this to implement mixed GLES and HWC
+// compositing to the same buffer for virtual displays. If it used two separate
+// buffer queues, then in GLES-only or mixed GLES+HWC compositing, the HWC
+// would have to copy the GLES output buffer to the HWC output buffer, using
+// more bandwidth than having HWC do additional composition "in place" on the
+// GLES output buffer.
+//
+// The goal for this class is to be usable in a variety of situations and be
+// part of libgui. But both the interface and implementation need some
+// iteration before then, so for now it should only be used by
+// VirtualDisplaySurface, which is why it's currently in SurfaceFlinger.
+//
+// Some of the problems that still need to be solved are:
+//
+// - Refactor the interposer interface along with BufferQueue and ConsumerBase,
+//   so that there is a common interface for the consumer end of a queue. The
+//   existing interfaces have some problems when the implementation isn't the
+//   final consumer.
+//
+// - The interposer needs at least one buffer in addition to those used by the
+//   source and sink. setBufferCount and QueueBufferOutput both need to
+//   account for this. It's not possible currently to do this generically,
+//   since we can't find out how many buffers the source and sink need. (See
+//   the horrible hack in the BufferQueueInterposer constructor).
+//
+// - Abandoning, disconnecting, and connecting need to pass through somehow.
+//   There needs to be a way to tell the interposer client to release its
+//   buffer immediately so it can be queued/released, e.g. when the source
+//   calls disconnect().
+//
+// - Right now the source->BQI queue is synchronous even if the BQI->sink
+//   queue is asynchronous. Need to figure out how asynchronous should behave
+//   and implement that.
+
+class BufferQueueInterposer : public BnGraphicBufferProducer {
+public:
+    BufferQueueInterposer(const sp<IGraphicBufferProducer>& sink,
+            const String8& name);
+
+    //
+    // IGraphicBufferProducer interface
+    //
+    virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* outBuf);
+    virtual status_t setBufferCount(int bufferCount);
+    virtual status_t dequeueBuffer(int* slot, sp<Fence>* fence,
+            uint32_t w, uint32_t h, uint32_t format, uint32_t usage);
+    virtual status_t queueBuffer(int slot,
+            const QueueBufferInput& input, QueueBufferOutput* output);
+    virtual void cancelBuffer(int slot, const sp<Fence>& fence);
+    virtual int query(int what, int* value);
+    virtual status_t setSynchronousMode(bool enabled);
+    virtual status_t connect(int api, QueueBufferOutput* output);
+    virtual status_t disconnect(int api);
+
+    //
+    // Interposer interface
+    //
+
+    enum {
+        NO_BUFFER_AVAILABLE = 2,    // matches BufferQueue
+        BUFFER_NOT_ACQUIRED,
+        BUFFER_ALREADY_ACQUIRED,
+    };
+
+    // Acquire the oldest queued buffer. If no buffers are pending, returns
+    // NO_BUFFER_AVAILABLE. If a buffer is currently acquired, returns
+    // BUFFER_ALREADY_ACQUIRED.
+    status_t acquireBuffer(sp<GraphicBuffer>* buf, sp<Fence>* fence);
+
+    // Release the currently acquired buffer, queueing it to the sink. If the
+    // current buffer hasn't been acquired, returns BUFFER_NOT_ACQUIRED.
+    status_t releaseBuffer(const sp<Fence>& fence);
+
+    // pullEmptyBuffer dequeues a buffer from the sink, then immediately
+    // queues it to the interposer. This makes a buffer available for the
+    // client to acquire even if the source hasn't queued one.
+    status_t pullEmptyBuffer();
+
+private:
+    struct QueuedBuffer {
+        QueuedBuffer(): slot(-1) {}
+        QueuedBuffer(int slot, const QueueBufferInput& qbi): slot(slot) {
+            qbi.deflate(&timestamp, &crop, &scalingMode, &transform, &fence);
+        }
+        int slot;
+        int64_t timestamp;
+        Rect crop;
+        int scalingMode;
+        uint32_t transform;
+        sp<Fence> fence;
+    };
+
+    virtual ~BufferQueueInterposer();
+    status_t flushQueuedBuffersLocked();
+
+    const sp<IGraphicBufferProducer> mSink;
+    String8 mName;
+
+    Mutex mMutex;
+    Vector<sp<GraphicBuffer> > mBuffers;
+    Vector<QueuedBuffer> mQueue;
+    bool mAcquired;
+    QueueBufferOutput mQueueBufferOutput;
+};
+
+// ---------------------------------------------------------------------------
+} // namespace android
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_SF_BUFFERQUEUEINTERPOSER_H
diff --git a/services/surfaceflinger/DisplayHardware/DisplaySurface.h b/services/surfaceflinger/DisplayHardware/DisplaySurface.h
new file mode 100644
index 0000000..2de6b4c
--- /dev/null
+++ b/services/surfaceflinger/DisplayHardware/DisplaySurface.h
@@ -0,0 +1,68 @@
+/*
+ * 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_SF_DISPLAY_SURFACE_H
+#define ANDROID_SF_DISPLAY_SURFACE_H
+
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+#include <utils/StrongPointer.h>
+
+// ---------------------------------------------------------------------------
+namespace android {
+// ---------------------------------------------------------------------------
+
+class IGraphicBufferProducer;
+class String8;
+
+class DisplaySurface : public virtual RefBase {
+public:
+    virtual sp<IGraphicBufferProducer> getIGraphicBufferProducer() const = 0;
+
+    // Should be called when composition rendering is complete for a frame (but
+    // eglSwapBuffers hasn't necessarily been called). Required by certain
+    // older drivers for synchronization.
+    // TODO: Remove this when we drop support for HWC 1.0.
+    virtual status_t compositionComplete() = 0;
+
+    // Inform the surface that GLES composition is complete for this frame, and
+    // the surface should make sure that HWComposer has the correct buffer for
+    // this frame. Some implementations may only push a new buffer to
+    // HWComposer if GLES composition took place, others need to push a new
+    // buffer on every frame.
+    virtual status_t advanceFrame() = 0;
+
+    // setReleaseFenceFd stores a fence file descriptor that will signal when
+    // the current buffer is no longer being read. This fence will be returned
+    // to the producer when the current buffer is released by updateTexImage().
+    // Multiple fences can be set for a given buffer; they will be merged into
+    // a single union fence. The GLConsumer will close the file descriptor
+    // when finished with it.
+    virtual status_t setReleaseFenceFd(int fenceFd) = 0;
+
+    virtual void dump(String8& result) const = 0;
+
+protected:
+    DisplaySurface() {}
+    virtual ~DisplaySurface() {}
+};
+
+// ---------------------------------------------------------------------------
+} // namespace android
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_SF_DISPLAY_SURFACE_H
+
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index 7557e3f..b5abaac 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -68,6 +68,17 @@
     mBufferQueue->setDefaultMaxBufferCount(NUM_FRAMEBUFFER_SURFACE_BUFFERS);
 }
 
+sp<IGraphicBufferProducer> FramebufferSurface::getIGraphicBufferProducer() const {
+    return getBufferQueue();
+}
+
+status_t FramebufferSurface::advanceFrame() {
+    // Once we remove FB HAL support, we can call nextBuffer() from here
+    // instead of using onFrameAvailable(). No real benefit, except it'll be
+    // more like VirtualDisplaySurface.
+    return NO_ERROR;
+}
+
 status_t FramebufferSurface::nextBuffer(sp<GraphicBuffer>& outBuffer, sp<Fence>& outFence) {
     Mutex::Autolock lock(mMutex);
 
@@ -134,7 +145,7 @@
     if (fenceFd >= 0) {
         sp<Fence> fence(new Fence(fenceFd));
         if (mCurrentBufferSlot != BufferQueue::INVALID_BUFFER_SLOT) {
-            status_t err = addReleaseFence(mCurrentBufferSlot, fence);
+            err = addReleaseFence(mCurrentBufferSlot, fence);
             ALOGE_IF(err, "setReleaseFenceFd: failed to add the fence: %s (%d)",
                     strerror(-err), err);
         }
@@ -142,21 +153,38 @@
     return err;
 }
 
-status_t FramebufferSurface::setUpdateRectangle(const Rect& r)
-{
-    return INVALID_OPERATION;
-}
-
 status_t FramebufferSurface::compositionComplete()
 {
     return mHwc.fbCompositionComplete();
 }
 
-void FramebufferSurface::dump(String8& result) {
-    mHwc.fbDump(result);
+// Since DisplaySurface and ConsumerBase both have a method with this
+// signature, results will vary based on the static pointer type the caller is
+// using:
+//   void dump(FrameBufferSurface* fbs, String8& s) {
+//       // calls FramebufferSurface::dump()
+//       fbs->dump(s);
+//
+//       // calls ConsumerBase::dump() since it is non-virtual
+//       static_cast<ConsumerBase*>(fbs)->dump(s);
+//
+//       // calls FramebufferSurface::dump() since it is virtual
+//       static_cast<DisplaySurface*>(fbs)->dump(s);
+//   }
+// To make sure that all of these end up doing the same thing, we just redirect
+// to ConsumerBase::dump() here. It will take the internal lock, and then call
+// virtual dumpLocked(), which is where the real work happens.
+void FramebufferSurface::dump(String8& result) const {
     ConsumerBase::dump(result);
 }
 
+void FramebufferSurface::dumpLocked(String8& result, const char* prefix,
+            char* buffer, size_t SIZE) const
+{
+    mHwc.fbDump(result);
+    ConsumerBase::dumpLocked(result, prefix, buffer, SIZE);
+}
+
 // ----------------------------------------------------------------------------
 }; // namespace android
 // ----------------------------------------------------------------------------
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
index b61b7f5..0aab742 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
@@ -22,6 +22,8 @@
 
 #include <gui/ConsumerBase.h>
 
+#include "DisplaySurface.h"
+
 // ---------------------------------------------------------------------------
 namespace android {
 // ---------------------------------------------------------------------------
@@ -32,23 +34,20 @@
 
 // ---------------------------------------------------------------------------
 
-class FramebufferSurface : public ConsumerBase {
+class FramebufferSurface : public ConsumerBase,
+                           public DisplaySurface {
 public:
     FramebufferSurface(HWComposer& hwc, int disp);
 
-    bool isUpdateOnDemand() const { return false; }
-    status_t setUpdateRectangle(const Rect& updateRect);
-    status_t compositionComplete();
+    virtual sp<IGraphicBufferProducer> getIGraphicBufferProducer() const;
 
-    virtual void dump(String8& result);
+    virtual status_t compositionComplete();
+    virtual status_t advanceFrame();
+    virtual status_t setReleaseFenceFd(int fenceFd);
 
-    // setReleaseFenceFd stores a fence file descriptor that will signal when the
-    // current buffer is no longer being read. This fence will be returned to
-    // the producer when the current buffer is released by updateTexImage().
-    // Multiple fences can be set for a given buffer; they will be merged into
-    // a single union fence. The GLConsumer will close the file descriptor
-    // when finished with it.
-    status_t setReleaseFenceFd(int fenceFd);
+    // Implementation of DisplaySurface::dump(). Note that ConsumerBase also
+    // has a non-virtual dump() with the same signature.
+    virtual void dump(String8& result) const;
 
 private:
     virtual ~FramebufferSurface() { }; // this class cannot be overloaded
@@ -56,6 +55,9 @@
     virtual void onFrameAvailable();
     virtual void freeBufferLocked(int slotIndex);
 
+    virtual void dumpLocked(String8& result, const char* prefix,
+            char* buffer, size_t SIZE) const;
+
     // nextBuffer waits for and then latches the next buffer from the
     // BufferQueue and releases the previously latched buffer to the
     // BufferQueue.  The new buffer is returned in the 'buffer' argument.
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 11f65f6..96cfc14 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -41,7 +41,6 @@
 #include <cutils/properties.h>
 
 #include "Layer.h"           // needed only for debugging
-#include "LayerBase.h"
 #include "HWComposer.h"
 #include "SurfaceFlinger.h"
 #include <utils/CallStack.h>
@@ -100,7 +99,7 @@
     bool needVSyncThread = true;
 
     // Note: some devices may insist that the FB HAL be opened before HWC.
-    loadFbHalModule();
+    int fberr = loadFbHalModule();
     loadHwcModule();
 
     if (mFbDev && mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
@@ -114,7 +113,8 @@
     // If we have no HWC, or a pre-1.1 HWC, an FB dev is mandatory.
     if ((!mHwc || !hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))
             && !mFbDev) {
-        ALOGE("ERROR: failed to open framebuffer, aborting");
+        ALOGE("ERROR: failed to open framebuffer (%s), aborting",
+                strerror(-fberr));
         abort();
     }
 
@@ -235,20 +235,17 @@
 }
 
 // Load and prepare the FB HAL, which uses the gralloc module.  Sets mFbDev.
-void HWComposer::loadFbHalModule()
+int HWComposer::loadFbHalModule()
 {
     hw_module_t const* module;
 
-    if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) != 0) {
+    int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
+    if (err != 0) {
         ALOGE("%s module not found", GRALLOC_HARDWARE_MODULE_ID);
-        return;
+        return err;
     }
 
-    int err = framebuffer_open(module, &mFbDev);
-    if (err) {
-        ALOGE("framebuffer_open failed (%s)", strerror(-err));
-        return;
-    }
+    return framebuffer_open(module, &mFbDev);
 }
 
 status_t HWComposer::initCheck() const {
@@ -381,6 +378,7 @@
     }
     int32_t id = mAllocatedDisplayIDs.firstUnmarkedBit();
     mAllocatedDisplayIDs.markBit(id);
+    mDisplayData[id].connected = true;
     return id;
 }
 
@@ -393,6 +391,7 @@
         return BAD_INDEX;
     }
     mAllocatedDisplayIDs.clearBit(id);
+    mDisplayData[id].connected = false;
     return NO_ERROR;
 }
 
@@ -616,14 +615,14 @@
 }
 
 bool HWComposer::hasHwcComposition(int32_t id) const {
-    if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
+    if (!mHwc || uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
         return false;
     return mDisplayData[id].hasOvComp;
 }
 
 bool HWComposer::hasGlesComposition(int32_t id) const {
-    if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
-        return false;
+    if (!mHwc || uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
+        return true;
     return mDisplayData[id].hasFbComp;
 }
 
@@ -654,6 +653,18 @@
             mLists[0]->sur = eglGetCurrentSurface(EGL_DRAW);
         }
 
+        // For virtual displays, the framebufferTarget buffer also serves as
+        // the HWC output buffer, so we need to copy the buffer handle and
+        // dup() the acquire fence.
+        for (size_t i=HWC_NUM_DISPLAY_TYPES; i<mNumDisplays; i++) {
+            DisplayData& disp(mDisplayData[i]);
+            if (disp.framebufferTarget) {
+                mLists[i]->outbuf = disp.framebufferTarget->handle;
+                mLists[i]->outbufAcquireFenceFd =
+                        dup(disp.framebufferTarget->acquireFenceFd);
+            }
+        }
+
         err = mHwc->set(mHwc, mNumDisplays, mLists);
 
         for (size_t i=0 ; i<mNumDisplays ; i++) {
@@ -925,7 +936,7 @@
         for (size_t i=0 ; i<mNumDisplays ; i++) {
             const DisplayData& disp(mDisplayData[i]);
 
-            const Vector< sp<LayerBase> >& visibleLayersSortedByZ =
+            const Vector< sp<Layer> >& visibleLayersSortedByZ =
                     mFlinger->getLayerSortedByZForHwcDisplay(i);
 
             if (disp.connected) {
@@ -949,13 +960,11 @@
                     String8 name("unknown");
 
                     if (i < visibleLayersSortedByZ.size()) {
-                        const sp<LayerBase>& layer(visibleLayersSortedByZ[i]);
-                        if (layer->getLayer() != NULL) {
-                            const sp<GraphicBuffer>& buffer(
-                                layer->getLayer()->getActiveBuffer());
-                            if (buffer != NULL) {
-                                format = buffer->getPixelFormat();
-                            }
+                        const sp<Layer>& layer(visibleLayersSortedByZ[i]);
+                        const sp<GraphicBuffer>& buffer(
+                                layer->getActiveBuffer());
+                        if (buffer != NULL) {
+                            format = buffer->getPixelFormat();
                         }
                         name = layer->getName();
                     }
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index f7ed1aa..fdbd2d9 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -47,7 +47,6 @@
 
 class GraphicBuffer;
 class Fence;
-class LayerBase;
 class Region;
 class String8;
 class SurfaceFlinger;
@@ -113,7 +112,7 @@
     // does this display have layers handled by GLES
     bool hasGlesComposition(int32_t id) const;
 
-    // get the releaseFence file descriptor for the given display
+    // get the releaseFence file descriptor for a display's framebuffer layer.
     // the release fence is only valid after commit()
     int getAndResetReleaseFenceFd(int32_t id);
 
@@ -266,7 +265,7 @@
 
 private:
     void loadHwcModule();
-    void loadFbHalModule();
+    int loadFbHalModule();
 
     LayerListIterator getLayerIterator(int32_t id, size_t index);
 
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
new file mode 100644
index 0000000..433e1eb
--- /dev/null
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -0,0 +1,103 @@
+/*
+ * 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.
+ */
+
+#include "VirtualDisplaySurface.h"
+#include "HWComposer.h"
+
+// ---------------------------------------------------------------------------
+namespace android {
+// ---------------------------------------------------------------------------
+
+VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, int disp,
+        const sp<IGraphicBufferProducer>& sink, const String8& name)
+:   mHwc(hwc),
+    mDisplayId(disp),
+    mSource(new BufferQueueInterposer(sink, name)),
+    mName(name),
+    mReleaseFence(Fence::NO_FENCE)
+{}
+
+VirtualDisplaySurface::~VirtualDisplaySurface() {
+    if (mAcquiredBuffer != NULL) {
+        status_t result = mSource->releaseBuffer(mReleaseFence);
+        ALOGE_IF(result != NO_ERROR, "VirtualDisplaySurface \"%s\": "
+                "failed to release previous buffer: %d",
+                mName.string(), result);
+    }
+}
+
+sp<IGraphicBufferProducer> VirtualDisplaySurface::getIGraphicBufferProducer() const {
+    return mSource;
+}
+
+status_t VirtualDisplaySurface::compositionComplete() {
+    return NO_ERROR;
+}
+
+status_t VirtualDisplaySurface::advanceFrame() {
+    Mutex::Autolock lock(mMutex);
+    status_t result = NO_ERROR;
+
+    if (mAcquiredBuffer != NULL) {
+        result = mSource->releaseBuffer(mReleaseFence);
+        ALOGE_IF(result != NO_ERROR, "VirtualDisplaySurface \"%s\": "
+                "failed to release previous buffer: %d",
+                mName.string(), result);
+        mAcquiredBuffer.clear();
+        mReleaseFence = Fence::NO_FENCE;
+    }
+
+    sp<Fence> fence;
+    result = mSource->acquireBuffer(&mAcquiredBuffer, &fence);
+    if (result == BufferQueueInterposer::NO_BUFFER_AVAILABLE) {
+        result = mSource->pullEmptyBuffer();
+        if (result != NO_ERROR)
+            return result;
+        result = mSource->acquireBuffer(&mAcquiredBuffer, &fence);
+    }
+    if (result != NO_ERROR)
+        return result;
+
+    return mHwc.fbPost(mDisplayId, fence, mAcquiredBuffer);
+}
+
+status_t VirtualDisplaySurface::setReleaseFenceFd(int fenceFd) {
+    if (fenceFd >= 0) {
+        sp<Fence> fence(new Fence(fenceFd));
+        Mutex::Autolock lock(mMutex);
+        sp<Fence> mergedFence = Fence::merge(
+                String8::format("VirtualDisplaySurface \"%s\"",
+                        mName.string()),
+                mReleaseFence, fence);
+        if (!mergedFence->isValid()) {
+            ALOGE("VirtualDisplaySurface \"%s\": failed to merge release fence",
+                    mName.string());
+            // synchronization is broken, the best we can do is hope fences
+            // signal in order so the new fence will act like a union
+            mReleaseFence = fence;
+            return BAD_VALUE;
+        }
+        mReleaseFence = mergedFence;
+    }
+    return NO_ERROR;
+}
+
+void VirtualDisplaySurface::dump(String8& result) const {
+}
+
+// ---------------------------------------------------------------------------
+} // namespace android
+// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
new file mode 100644
index 0000000..66f8580
--- /dev/null
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
@@ -0,0 +1,84 @@
+/*
+ * 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_SF_VIRTUAL_DISPLAY_SURFACE_H
+#define ANDROID_SF_VIRTUAL_DISPLAY_SURFACE_H
+
+#include "BufferQueueInterposer.h"
+#include "DisplaySurface.h"
+
+// ---------------------------------------------------------------------------
+namespace android {
+// ---------------------------------------------------------------------------
+
+class HWComposer;
+
+/* This DisplaySurface implementation uses a BufferQueueInterposer to pass
+ * partially- or fully-composited buffers from the OpenGL ES driver to
+ * HWComposer to use as the output buffer for virtual displays. Allowing HWC
+ * to compose into the same buffer that contains GLES results saves bandwidth
+ * compared to having two separate BufferQueues for frames with at least some
+ * GLES composition.
+ *
+ * The alternative would be to have two complete BufferQueues, one from GLES
+ * to HWC and one from HWC to the virtual display sink (e.g. video encoder).
+ * For GLES-only frames, the same bandwidth saving could be achieved if buffers
+ * could be acquired from the GLES->HWC queue and inserted into the HWC->sink
+ * queue. That would be complicated and doesn't help the mixed GLES+HWC case.
+ *
+ * On frames with no GLES composition, the VirtualDisplaySurface dequeues a
+ * buffer directly from the sink IGraphicBufferProducer and passes it to HWC,
+ * bypassing the GLES driver. This is only guaranteed to work if
+ * eglSwapBuffers doesn't immediately dequeue a buffer for the next frame,
+ * since we can't rely on being able to dequeue more than one buffer at a time.
+ *
+ * TODO(jessehall): Add a libgui test that ensures that EGL/GLES do lazy
+ * dequeBuffers; we've wanted to require that for other reasons anyway.
+ */
+class VirtualDisplaySurface : public DisplaySurface {
+public:
+    VirtualDisplaySurface(HWComposer& hwc, int disp,
+            const sp<IGraphicBufferProducer>& sink,
+            const String8& name);
+
+    virtual sp<IGraphicBufferProducer> getIGraphicBufferProducer() const;
+
+    virtual status_t compositionComplete();
+    virtual status_t advanceFrame();
+    virtual status_t setReleaseFenceFd(int fenceFd);
+    virtual void dump(String8& result) const;
+
+private:
+    virtual ~VirtualDisplaySurface();
+
+    // immutable after construction
+    HWComposer& mHwc;
+    int mDisplayId;
+    sp<BufferQueueInterposer> mSource;
+    String8 mName;
+
+    // mutable, must be synchronized with mMutex
+    Mutex mMutex;
+    sp<GraphicBuffer> mAcquiredBuffer;
+    sp<Fence> mReleaseFence;
+};
+
+// ---------------------------------------------------------------------------
+} // namespace android
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_SF_VIRTUAL_DISPLAY_SURFACE_H
+
diff --git a/services/surfaceflinger/EventThread.cpp b/services/surfaceflinger/EventThread.cpp
index edb9fa5..4d0fc79 100644
--- a/services/surfaceflinger/EventThread.cpp
+++ b/services/surfaceflinger/EventThread.cpp
@@ -41,7 +41,7 @@
       mUseSoftwareVSync(false),
       mDebugVsyncEnabled(false) {
 
-    for (int32_t i=0 ; i<HWC_DISPLAY_TYPES_SUPPORTED ; i++) {
+    for (int32_t i=0 ; i<HWC_NUM_DISPLAY_TYPES ; i++) {
         mVSyncEvent[i].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
         mVSyncEvent[i].header.id = 0;
         mVSyncEvent[i].header.timestamp = 0;
@@ -112,11 +112,11 @@
 
 
 void EventThread::onVSyncReceived(int type, nsecs_t timestamp) {
-    ALOGE_IF(type >= HWC_DISPLAY_TYPES_SUPPORTED,
-            "received event for an invalid display (id=%d)", type);
+    ALOGE_IF(type >= HWC_NUM_DISPLAY_TYPES,
+            "received vsync event for an invalid display (id=%d)", type);
 
     Mutex::Autolock _l(mLock);
-    if (type < HWC_DISPLAY_TYPES_SUPPORTED) {
+    if (type < HWC_NUM_DISPLAY_TYPES) {
         mVSyncEvent[type].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
         mVSyncEvent[type].header.id = type;
         mVSyncEvent[type].header.timestamp = timestamp;
@@ -126,11 +126,11 @@
 }
 
 void EventThread::onHotplugReceived(int type, bool connected) {
-    ALOGE_IF(type >= HWC_DISPLAY_TYPES_SUPPORTED,
-            "received event for an invalid display (id=%d)", type);
+    ALOGE_IF(type >= HWC_NUM_DISPLAY_TYPES,
+            "received hotplug event for an invalid display (id=%d)", type);
 
     Mutex::Autolock _l(mLock);
-    if (type < HWC_DISPLAY_TYPES_SUPPORTED) {
+    if (type < HWC_NUM_DISPLAY_TYPES) {
         DisplayEventReceiver::Event event;
         event.header.type = DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG;
         event.header.id = type;
@@ -184,7 +184,7 @@
 
         size_t vsyncCount = 0;
         nsecs_t timestamp = 0;
-        for (int32_t i=0 ; i<HWC_DISPLAY_TYPES_SUPPORTED ; i++) {
+        for (int32_t i=0 ; i<HWC_NUM_DISPLAY_TYPES ; i++) {
             timestamp = mVSyncEvent[i].header.timestamp;
             if (timestamp) {
                 // we have a vsync event to dispatch
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 439acb5..1677c76 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -50,45 +50,72 @@
 
 // ---------------------------------------------------------------------------
 
-Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client)
-    :   LayerBaseClient(flinger, client),
+int32_t Layer::sSequence = 1;
+
+Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client,
+        const String8& name, uint32_t w, uint32_t h, uint32_t flags)
+    :   contentDirty(false),
+        sequence(uint32_t(android_atomic_inc(&sSequence))),
+        mFlinger(flinger),
         mTextureName(-1U),
+        mPremultipliedAlpha(true),
+        mName("unnamed"),
+        mDebug(false),
+        mFormat(PIXEL_FORMAT_NONE),
+        mGLExtensions(GLExtensions::getInstance()),
+        mOpaqueLayer(true),
+        mTransactionFlags(0),
         mQueuedFrames(0),
         mCurrentTransform(0),
         mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
         mCurrentOpacity(true),
         mRefreshPending(false),
         mFrameLatencyNeeded(false),
-        mFormat(PIXEL_FORMAT_NONE),
-        mGLExtensions(GLExtensions::getInstance()),
-        mOpaqueLayer(true),
+        mFiltering(false),
+        mNeedsFiltering(false),
         mSecure(false),
-        mProtectedByApp(false)
+        mProtectedByApp(false),
+        mHasSurface(false),
+        mClientRef(client)
 {
     mCurrentCrop.makeInvalid();
     glGenTextures(1, &mTextureName);
-}
 
-void Layer::onLayerDisplayed(const sp<const DisplayDevice>& hw,
-        HWComposer::HWCLayerInterface* layer) {
-    LayerBaseClient::onLayerDisplayed(hw, layer);
-    if (layer) {
-        mSurfaceFlingerConsumer->setReleaseFence(layer->getAndResetReleaseFenceFd());
-    }
+    uint32_t layerFlags = 0;
+    if (flags & ISurfaceComposerClient::eHidden)
+        layerFlags = layer_state_t::eLayerHidden;
+
+    if (flags & ISurfaceComposerClient::eNonPremultiplied)
+        mPremultipliedAlpha = false;
+
+    mName = name;
+
+    mCurrentState.active.w = w;
+    mCurrentState.active.h = h;
+    mCurrentState.active.crop.makeInvalid();
+    mCurrentState.z = 0;
+    mCurrentState.alpha = 0xFF;
+    mCurrentState.layerStack = 0;
+    mCurrentState.flags = layerFlags;
+    mCurrentState.sequence = 0;
+    mCurrentState.transform.set(0, 0);
+    mCurrentState.requested = mCurrentState.active;
+
+    // drawing state & current state are identical
+    mDrawingState = mCurrentState;
 }
 
 void Layer::onFirstRef()
 {
-    LayerBaseClient::onFirstRef();
-
     // Creates a custom BufferQueue for SurfaceFlingerConsumer to use
-    sp<BufferQueue> bq = new SurfaceTextureLayer();
+    sp<BufferQueue> bq = new SurfaceTextureLayer(mFlinger);
     mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(mTextureName, true,
             GL_TEXTURE_EXTERNAL_OES, false, bq);
 
     mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0));
     mSurfaceFlingerConsumer->setFrameAvailableListener(this);
     mSurfaceFlingerConsumer->setSynchronousMode(true);
+    mSurfaceFlingerConsumer->setName(mName);
 
 #ifdef TARGET_DISABLE_TRIPLE_BUFFERING
 #warning "disabling triple buffering"
@@ -101,68 +128,44 @@
     updateTransformHint(hw);
 }
 
-Layer::~Layer()
-{
+Layer::~Layer() {
+    sp<Client> c(mClientRef.promote());
+    if (c != 0) {
+        c->detachLayer(this);
+    }
     mFlinger->deleteTextureAsync(mTextureName);
 }
 
+// ---------------------------------------------------------------------------
+// callbacks
+// ---------------------------------------------------------------------------
+
+void Layer::onLayerDisplayed(const sp<const DisplayDevice>& hw,
+        HWComposer::HWCLayerInterface* layer) {
+    if (layer) {
+        layer->onDisplayed();
+        mSurfaceFlingerConsumer->setReleaseFence(layer->getAndResetReleaseFenceFd());
+    }
+}
+
 void Layer::onFrameAvailable() {
     android_atomic_inc(&mQueuedFrames);
     mFlinger->signalLayerUpdate();
 }
 
-// called with SurfaceFlinger::mStateLock as soon as the layer is entered
-// in the purgatory list
-void Layer::onRemoved()
-{
+// called with SurfaceFlinger::mStateLock from the drawing thread after
+// the layer has been remove from the current state list (and just before
+// it's removed from the drawing state list)
+void Layer::onRemoved() {
     mSurfaceFlingerConsumer->abandon();
 }
 
-void Layer::setName(const String8& name) {
-    LayerBase::setName(name);
-    mSurfaceFlingerConsumer->setName(name);
-}
+// ---------------------------------------------------------------------------
+// set-up
+// ---------------------------------------------------------------------------
 
-sp<ISurface> Layer::createSurface()
-{
-    /*
-     * This class provides an implementation of BnSurface (the "native" or
-     * "remote" side of the Binder IPC interface ISurface), and mixes in
-     * LayerCleaner to ensure that mFlinger->onLayerDestroyed() is called for
-     * this layer when the BSurface is destroyed.
-     *
-     * The idea is to provide a handle to the Layer through ISurface that
-     * is cleaned up automatically when the last reference to the ISurface
-     * goes away.  (The references will be held on the "proxy" side, while
-     * the Layer exists on the "native" side.)
-     *
-     * The Layer has a reference to an instance of SurfaceFlinger's variant
-     * of GLConsumer, which holds a reference to the BufferQueue.  The
-     * getSurfaceTexture() call returns a Binder interface reference for
-     * the producer interface of the buffer queue associated with the Layer.
-     */
-    class BSurface : public BnSurface, public LayerCleaner {
-        wp<const Layer> mOwner;
-        virtual sp<IGraphicBufferProducer> getSurfaceTexture() const {
-            sp<IGraphicBufferProducer> res;
-            sp<const Layer> that( mOwner.promote() );
-            if (that != NULL) {
-                res = that->mSurfaceFlingerConsumer->getBufferQueue();
-            }
-            return res;
-        }
-    public:
-        BSurface(const sp<SurfaceFlinger>& flinger,
-                const sp<Layer>& layer)
-            : LayerCleaner(flinger, layer), mOwner(layer) { }
-    };
-    sp<ISurface> sur(new BSurface(mFlinger, this));
-    return sur;
-}
-
-wp<IBinder> Layer::getSurfaceTextureBinder() const
-{
-    return mSurfaceFlingerConsumer->getBufferQueue()->asBinder();
+String8 Layer::getName() const {
+    return mName;
 }
 
 status_t Layer::setBuffers( uint32_t w, uint32_t h,
@@ -200,26 +203,117 @@
     return NO_ERROR;
 }
 
-Rect Layer::computeBufferCrop() const {
-    // Start with the SurfaceFlingerConsumer's buffer crop...
+sp<IBinder> Layer::getHandle() {
+    Mutex::Autolock _l(mLock);
+
+    LOG_ALWAYS_FATAL_IF(mHasSurface,
+            "Layer::getHandle() has already been called");
+
+    mHasSurface = true;
+
+    /*
+     * The layer handle is just a BBinder object passed to the client
+     * (remote process) -- we don't keep any reference on our side such that
+     * the dtor is called when the remote side let go of its reference.
+     *
+     * LayerCleaner ensures that mFlinger->onLayerDestroyed() is called for
+     * this layer when the handle is destroyed.
+     */
+
+    class Handle : public BBinder, public LayerCleaner {
+        wp<const Layer> mOwner;
+    public:
+        Handle(const sp<SurfaceFlinger>& flinger, const sp<Layer>& layer)
+            : LayerCleaner(flinger, layer), mOwner(layer) {
+        }
+    };
+
+    return new Handle(mFlinger, this);
+}
+
+sp<BufferQueue> Layer::getBufferQueue() const {
+    return mSurfaceFlingerConsumer->getBufferQueue();
+}
+
+//virtual sp<IGraphicBufferProducer> getSurfaceTexture() const {
+//    sp<IGraphicBufferProducer> res;
+//    sp<const Layer> that( mOwner.promote() );
+//    if (that != NULL) {
+//        res = that->mSurfaceFlingerConsumer->getBufferQueue();
+//    }
+//    return res;
+//}
+
+// ---------------------------------------------------------------------------
+// h/w composer set-up
+// ---------------------------------------------------------------------------
+
+Rect Layer::getContentCrop() const {
+    // this is the crop rectangle that applies to the buffer
+    // itself (as opposed to the window)
     Rect crop;
     if (!mCurrentCrop.isEmpty()) {
+        // if the buffer crop is defined, we use that
         crop = mCurrentCrop;
-    } else  if (mActiveBuffer != NULL){
-        crop = Rect(mActiveBuffer->getWidth(), mActiveBuffer->getHeight());
+    } else if (mActiveBuffer != NULL) {
+        // otherwise we use the whole buffer
+        crop = mActiveBuffer->getBounds();
     } else {
+        // if we don't have a buffer yet, we use an empty/invalid crop
         crop.makeInvalid();
-        return crop;
     }
+    return crop;
+}
 
-    // ... then reduce that in the same proportions as the window crop reduces
-    // the window size.
-    const State& s(drawingState());
+uint32_t Layer::getContentTransform() const {
+    return mCurrentTransform;
+}
+
+Rect Layer::computeBounds() const {
+    const Layer::State& s(drawingState());
+    Rect win(s.active.w, s.active.h);
     if (!s.active.crop.isEmpty()) {
+        win.intersect(s.active.crop, &win);
+    }
+    return win;
+}
+
+Rect Layer::computeCrop(const sp<const DisplayDevice>& hw) const {
+    /*
+     * The way we compute the crop (aka. texture coordinates when we have a
+     * Layer) produces a different output from the GL code in
+     * drawWithOpenGL() due to HWC being limited to integers. The difference
+     * can be large if getContentTransform() contains a large scale factor.
+     * See comments in drawWithOpenGL() for more details.
+     */
+
+    // the content crop is the area of the content that gets scaled to the
+    // layer's size.
+    Rect crop(getContentCrop());
+
+    // the active.crop is the area of the window that gets cropped, but not
+    // scaled in any ways.
+    const State& s(drawingState());
+
+    // apply the projection's clipping to the window crop in
+    // layerstack space, and convert-back to layer space.
+    // if there are no window scaling (or content scaling) involved,
+    // this operation will map to full pixels in the buffer.
+    // NOTE: should we revert to GL composition if a scaling is involved
+    // since it cannot be represented in the HWC API?
+    Rect activeCrop(s.transform.transform(s.active.crop));
+    activeCrop.intersect(hw->getViewport(), &activeCrop);
+    activeCrop = s.transform.inverse().transform(activeCrop);
+
+    // paranoia: make sure the window-crop is constrained in the
+    // window's bounds
+    activeCrop.intersect(Rect(s.active.w, s.active.h), &activeCrop);
+
+    if (!activeCrop.isEmpty()) {
         // Transform the window crop to match the buffer coordinate system,
         // which means using the inverse of the current transform set on the
         // SurfaceFlingerConsumer.
-        uint32_t invTransform = mCurrentTransform;
+        uint32_t invTransform = getContentTransform();
         int winWidth = s.active.w;
         int winHeight = s.active.h;
         if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
@@ -228,17 +322,24 @@
             winWidth = s.active.h;
             winHeight = s.active.w;
         }
-        Rect winCrop = s.active.crop.transform(invTransform,
-                s.active.w, s.active.h);
+        const Rect winCrop = activeCrop.transform(
+                invTransform, s.active.w, s.active.h);
 
+        // the code below essentially performs a scaled intersection
+        // of crop and winCrop
         float xScale = float(crop.width()) / float(winWidth);
         float yScale = float(crop.height()) / float(winHeight);
-        crop.left += int(ceilf(float(winCrop.left) * xScale));
-        crop.top += int(ceilf(float(winCrop.top) * yScale));
-        crop.right -= int(ceilf(float(winWidth - winCrop.right) * xScale));
-        crop.bottom -= int(ceilf(float(winHeight - winCrop.bottom) * yScale));
-    }
 
+        int insetL = int(ceilf( winCrop.left                * xScale));
+        int insetT = int(ceilf( winCrop.top                 * yScale));
+        int insetR = int(ceilf((winWidth  - winCrop.right ) * xScale));
+        int insetB = int(ceilf((winHeight - winCrop.bottom) * yScale));
+
+        crop.left   += insetL;
+        crop.top    += insetT;
+        crop.right  -= insetR;
+        crop.bottom -= insetB;
+    }
     return crop;
 }
 
@@ -246,7 +347,7 @@
     const sp<const DisplayDevice>& hw,
         HWComposer::HWCLayerInterface& layer)
 {
-    LayerBaseClient::setGeometry(hw, layer);
+    layer.setDefaultState();
 
     // enable this layer
     layer.setSkip(false);
@@ -255,7 +356,21 @@
         layer.setSkip(true);
     }
 
+    // this gives us only the "orientation" component of the transform
     const State& s(drawingState());
+    if (!isOpaque() || s.alpha != 0xFF) {
+        layer.setBlending(mPremultipliedAlpha ?
+                HWC_BLENDING_PREMULT :
+                HWC_BLENDING_COVERAGE);
+    }
+
+    // apply the layer's transform, followed by the display's global transform
+    // here we're guaranteed that the layer's transform preserves rects
+    Rect frame(s.transform.transform(computeBounds()));
+    frame.intersect(hw->getViewport(), &frame);
+    const Transform& tr(hw->getTransform());
+    layer.setFrame(tr.transform(frame));
+    layer.setCrop(computeCrop(hw));
     layer.setPlaneAlpha(s.alpha);
 
     /*
@@ -267,23 +382,29 @@
      */
 
     const Transform bufferOrientation(mCurrentTransform);
-    const Transform tr(hw->getTransform() * s.transform * bufferOrientation);
+    const Transform transform(tr * s.transform * bufferOrientation);
 
     // this gives us only the "orientation" component of the transform
-    const uint32_t finalTransform = tr.getOrientation();
-
-    // we can only handle simple transformation
-    if (finalTransform & Transform::ROT_INVALID) {
+    const uint32_t orientation = transform.getOrientation();
+    if (orientation & Transform::ROT_INVALID) {
+        // we can only handle simple transformation
         layer.setSkip(true);
     } else {
-        layer.setTransform(finalTransform);
+        layer.setTransform(orientation);
     }
-    layer.setCrop(computeBufferCrop());
 }
 
 void Layer::setPerFrameData(const sp<const DisplayDevice>& hw,
         HWComposer::HWCLayerInterface& layer) {
-    LayerBaseClient::setPerFrameData(hw, layer);
+    // we have to set the visible region on every frame because
+    // we currently free it during onLayerDisplayed(), which is called
+    // after HWComposer::commit() -- every frame.
+    // Apply this display's projection's viewport to the visible region
+    // before giving it to the HWC HAL.
+    const Transform& tr = hw->getTransform();
+    Region visible = tr.transform(visibleRegion.intersect(hw->getViewport()));
+    layer.setVisibleRegionScreen(visible);
+
     // NOTE: buffer can be NULL if the client never drew into this
     // layer yet, or if we ran out of memory
     layer.setBuffer(mActiveBuffer);
@@ -308,6 +429,18 @@
     layer.setAcquireFenceFd(fenceFd);
 }
 
+// ---------------------------------------------------------------------------
+// drawing...
+// ---------------------------------------------------------------------------
+
+void Layer::draw(const sp<const DisplayDevice>& hw, const Region& clip) const {
+    onDraw(hw, clip);
+}
+
+void Layer::draw(const sp<const DisplayDevice>& hw) {
+    onDraw( hw, Region(hw->bounds()) );
+}
+
 void Layer::onDraw(const sp<const DisplayDevice>& hw, const Region& clip) const
 {
     ATRACE_CALL();
@@ -327,8 +460,8 @@
                 mFlinger->mDrawingState.layersSortedByZ);
         const size_t count = drawingLayers.size();
         for (size_t i=0 ; i<count ; ++i) {
-            const sp<LayerBase>& layer(drawingLayers[i]);
-            if (layer.get() == static_cast<LayerBase const*>(this))
+            const sp<Layer>& layer(drawingLayers[i]);
+            if (layer.get() == static_cast<Layer const*>(this))
                 break;
             under.orSelf( hw->getTransform().transform(layer->visibleRegion) );
         }
@@ -388,6 +521,119 @@
     glDisable(GL_TEXTURE_2D);
 }
 
+
+void Layer::clearWithOpenGL(const sp<const DisplayDevice>& hw, const Region& clip,
+        GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) const
+{
+    const uint32_t fbHeight = hw->getHeight();
+    glColor4f(red,green,blue,alpha);
+
+    glDisable(GL_TEXTURE_EXTERNAL_OES);
+    glDisable(GL_TEXTURE_2D);
+    glDisable(GL_BLEND);
+
+    LayerMesh mesh;
+    computeGeometry(hw, &mesh);
+
+    glVertexPointer(2, GL_FLOAT, 0, mesh.getVertices());
+    glDrawArrays(GL_TRIANGLE_FAN, 0, mesh.getVertexCount());
+}
+
+void Layer::clearWithOpenGL(
+        const sp<const DisplayDevice>& hw, const Region& clip) const {
+    clearWithOpenGL(hw, clip, 0,0,0,0);
+}
+
+void Layer::drawWithOpenGL(
+        const sp<const DisplayDevice>& hw, const Region& clip) const {
+    const uint32_t fbHeight = hw->getHeight();
+    const State& s(drawingState());
+
+    GLenum src = mPremultipliedAlpha ? GL_ONE : GL_SRC_ALPHA;
+    if (CC_UNLIKELY(s.alpha < 0xFF)) {
+        const GLfloat alpha = s.alpha * (1.0f/255.0f);
+        if (mPremultipliedAlpha) {
+            glColor4f(alpha, alpha, alpha, alpha);
+        } else {
+            glColor4f(1, 1, 1, alpha);
+        }
+        glEnable(GL_BLEND);
+        glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA);
+        glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+    } else {
+        glColor4f(1, 1, 1, 1);
+        glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+        if (!isOpaque()) {
+            glEnable(GL_BLEND);
+            glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA);
+        } else {
+            glDisable(GL_BLEND);
+        }
+    }
+
+    LayerMesh mesh;
+    computeGeometry(hw, &mesh);
+
+    // TODO: we probably want to generate the texture coords with the mesh
+    // here we assume that we only have 4 vertices
+
+    struct TexCoords {
+        GLfloat u;
+        GLfloat v;
+    };
+
+
+    /*
+     * NOTE: the way we compute the texture coordinates here produces
+     * different results than when we take the HWC path -- in the later case
+     * the "source crop" is rounded to texel boundaries.
+     * This can produce significantly different results when the texture
+     * is scaled by a large amount.
+     *
+     * The GL code below is more logical (imho), and the difference with
+     * HWC is due to a limitation of the HWC API to integers -- a question
+     * is suspend is wether we should ignore this problem or revert to
+     * GL composition when a buffer scaling is applied (maybe with some
+     * minimal value)? Or, we could make GL behave like HWC -- but this feel
+     * like more of a hack.
+     */
+    const Rect win(computeBounds());
+
+    GLfloat left   = GLfloat(win.left)   / GLfloat(s.active.w);
+    GLfloat top    = GLfloat(win.top)    / GLfloat(s.active.h);
+    GLfloat right  = GLfloat(win.right)  / GLfloat(s.active.w);
+    GLfloat bottom = GLfloat(win.bottom) / GLfloat(s.active.h);
+
+    TexCoords texCoords[4];
+    texCoords[0].u = left;
+    texCoords[0].v = top;
+    texCoords[1].u = left;
+    texCoords[1].v = bottom;
+    texCoords[2].u = right;
+    texCoords[2].v = bottom;
+    texCoords[3].u = right;
+    texCoords[3].v = top;
+    for (int i = 0; i < 4; i++) {
+        texCoords[i].v = 1.0f - texCoords[i].v;
+    }
+
+    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+    glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
+    glVertexPointer(2, GL_FLOAT, 0, mesh.getVertices());
+    glDrawArrays(GL_TRIANGLE_FAN, 0, mesh.getVertexCount());
+
+    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+    glDisable(GL_BLEND);
+}
+
+void Layer::setFiltering(bool filtering) {
+    mFiltering = filtering;
+}
+
+bool Layer::getFiltering() const {
+    return mFiltering;
+}
+
 // As documented in libhardware header, formats in the range
 // 0x100 - 0x1FF are specific to the HAL implementation, and
 // are known to have no alpha channel
@@ -406,6 +652,29 @@
     return (err || info.h_alpha <= info.l_alpha);
 }
 
+// ----------------------------------------------------------------------------
+// local state
+// ----------------------------------------------------------------------------
+
+void Layer::computeGeometry(const sp<const DisplayDevice>& hw, LayerMesh* mesh) const
+{
+    const Layer::State& s(drawingState());
+    const Transform tr(hw->getTransform() * s.transform);
+    const uint32_t hw_h = hw->getHeight();
+    Rect win(s.active.w, s.active.h);
+    if (!s.active.crop.isEmpty()) {
+        win.intersect(s.active.crop, &win);
+    }
+    if (mesh) {
+        tr.transform(mesh->mVertices[0], win.left,  win.top);
+        tr.transform(mesh->mVertices[1], win.left,  win.bottom);
+        tr.transform(mesh->mVertices[2], win.right, win.bottom);
+        tr.transform(mesh->mVertices[3], win.right, win.top);
+        for (size_t i=0 ; i<4 ; i++) {
+            mesh->mVertices[i][1] = hw_h - mesh->mVertices[i][1];
+        }
+    }
+}
 
 bool Layer::isOpaque() const
 {
@@ -427,8 +696,39 @@
             (activeBuffer->getUsage() & GRALLOC_USAGE_PROTECTED);
 }
 
-uint32_t Layer::doTransaction(uint32_t flags)
-{
+bool Layer::isFixedSize() const {
+    return mCurrentScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
+}
+
+bool Layer::isCropped() const {
+    return !mCurrentCrop.isEmpty();
+}
+
+bool Layer::needsFiltering(const sp<const DisplayDevice>& hw) const {
+    return mNeedsFiltering || hw->needsFiltering();
+}
+
+void Layer::setVisibleRegion(const Region& visibleRegion) {
+    // always called from main thread
+    this->visibleRegion = visibleRegion;
+}
+
+void Layer::setCoveredRegion(const Region& coveredRegion) {
+    // always called from main thread
+    this->coveredRegion = coveredRegion;
+}
+
+void Layer::setVisibleNonTransparentRegion(const Region&
+        setVisibleNonTransparentRegion) {
+    // always called from main thread
+    this->visibleNonTransparentRegion = setVisibleNonTransparentRegion;
+}
+
+// ----------------------------------------------------------------------------
+// transaction
+// ----------------------------------------------------------------------------
+
+uint32_t Layer::doTransaction(uint32_t flags) {
     ATRACE_CALL();
 
     const Layer::State& front(drawingState());
@@ -487,7 +787,7 @@
                                    (temp.requested.h != temp.active.h);
 
         if (resizePending) {
-            // don't let LayerBase::doTransaction update the drawing state
+            // don't let Layer::doTransaction update the drawing state
             // if we have a pending resize, unless we are in fixed-size mode.
             // the drawing state will be updated only once we receive a buffer
             // with the correct size.
@@ -500,15 +800,117 @@
         }
     }
 
-    return LayerBase::doTransaction(flags);
+    // always set active to requested, unless we're asked not to
+    // this is used by Layer, which special cases resizes.
+    if (flags & eDontUpdateGeometryState)  {
+    } else {
+        Layer::State& editTemp(currentState());
+        editTemp.active = temp.requested;
+    }
+
+    if (front.active != temp.active) {
+        // invalidate and recompute the visible regions if needed
+        flags |= Layer::eVisibleRegion;
+    }
+
+    if (temp.sequence != front.sequence) {
+        // invalidate and recompute the visible regions if needed
+        flags |= eVisibleRegion;
+        this->contentDirty = true;
+
+        // we may use linear filtering, if the matrix scales us
+        const uint8_t type = temp.transform.getType();
+        mNeedsFiltering = (!temp.transform.preserveRects() ||
+                (type >= Transform::SCALE));
+    }
+
+    // Commit the transaction
+    commitTransaction();
+    return flags;
 }
 
-bool Layer::isFixedSize() const {
-    return mCurrentScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
+void Layer::commitTransaction() {
+    mDrawingState = mCurrentState;
 }
 
-bool Layer::isCropped() const {
-    return !mCurrentCrop.isEmpty();
+uint32_t Layer::getTransactionFlags(uint32_t flags) {
+    return android_atomic_and(~flags, &mTransactionFlags) & flags;
+}
+
+uint32_t Layer::setTransactionFlags(uint32_t flags) {
+    return android_atomic_or(flags, &mTransactionFlags);
+}
+
+bool Layer::setPosition(float x, float y) {
+    if (mCurrentState.transform.tx() == x && mCurrentState.transform.ty() == y)
+        return false;
+    mCurrentState.sequence++;
+    mCurrentState.transform.set(x, y);
+    setTransactionFlags(eTransactionNeeded);
+    return true;
+}
+bool Layer::setLayer(uint32_t z) {
+    if (mCurrentState.z == z)
+        return false;
+    mCurrentState.sequence++;
+    mCurrentState.z = z;
+    setTransactionFlags(eTransactionNeeded);
+    return true;
+}
+bool Layer::setSize(uint32_t w, uint32_t h) {
+    if (mCurrentState.requested.w == w && mCurrentState.requested.h == h)
+        return false;
+    mCurrentState.requested.w = w;
+    mCurrentState.requested.h = h;
+    setTransactionFlags(eTransactionNeeded);
+    return true;
+}
+bool Layer::setAlpha(uint8_t alpha) {
+    if (mCurrentState.alpha == alpha)
+        return false;
+    mCurrentState.sequence++;
+    mCurrentState.alpha = alpha;
+    setTransactionFlags(eTransactionNeeded);
+    return true;
+}
+bool Layer::setMatrix(const layer_state_t::matrix22_t& matrix) {
+    mCurrentState.sequence++;
+    mCurrentState.transform.set(
+            matrix.dsdx, matrix.dsdy, matrix.dtdx, matrix.dtdy);
+    setTransactionFlags(eTransactionNeeded);
+    return true;
+}
+bool Layer::setTransparentRegionHint(const Region& transparent) {
+    mCurrentState.sequence++;
+    mCurrentState.transparentRegion = transparent;
+    setTransactionFlags(eTransactionNeeded);
+    return true;
+}
+bool Layer::setFlags(uint8_t flags, uint8_t mask) {
+    const uint32_t newFlags = (mCurrentState.flags & ~mask) | (flags & mask);
+    if (mCurrentState.flags == newFlags)
+        return false;
+    mCurrentState.sequence++;
+    mCurrentState.flags = newFlags;
+    setTransactionFlags(eTransactionNeeded);
+    return true;
+}
+bool Layer::setCrop(const Rect& crop) {
+    if (mCurrentState.requested.crop == crop)
+        return false;
+    mCurrentState.sequence++;
+    mCurrentState.requested.crop = crop;
+    setTransactionFlags(eTransactionNeeded);
+    return true;
+}
+
+bool Layer::setLayerStack(uint32_t layerStack) {
+    if (mCurrentState.layerStack == layerStack)
+        return false;
+    mCurrentState.sequence++;
+    mCurrentState.layerStack = layerStack;
+    setTransactionFlags(eTransactionNeeded);
+    return true;
 }
 
 // ----------------------------------------------------------------------------
@@ -551,7 +953,9 @@
 }
 
 bool Layer::isVisible() const {
-    return LayerBaseClient::isVisible() && (mActiveBuffer != NULL);
+    const Layer::State& s(mDrawingState);
+    return !(s.flags & layer_state_t::eLayerHidden) && s.alpha
+            && (mActiveBuffer != NULL);
 }
 
 Region Layer::latchBuffer(bool& recomputeVisibleRegions)
@@ -725,44 +1129,6 @@
     return outDirtyRegion;
 }
 
-void Layer::dump(String8& result, char* buffer, size_t SIZE) const
-{
-    LayerBaseClient::dump(result, buffer, SIZE);
-
-    sp<const GraphicBuffer> buf0(mActiveBuffer);
-    uint32_t w0=0, h0=0, s0=0, f0=0;
-    if (buf0 != 0) {
-        w0 = buf0->getWidth();
-        h0 = buf0->getHeight();
-        s0 = buf0->getStride();
-        f0 = buf0->format;
-    }
-    snprintf(buffer, SIZE,
-            "      "
-            "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);
-    }
-}
-
-void Layer::dumpStats(String8& result, char* buffer, size_t SIZE) const
-{
-    LayerBaseClient::dumpStats(result, buffer, SIZE);
-    mFrameTracker.dump(result);
-}
-
-void Layer::clearStats()
-{
-    LayerBaseClient::clearStats();
-    mFrameTracker.clear();
-}
-
 uint32_t Layer::getEffectiveUsage(uint32_t usage) const
 {
     // TODO: should we do something special if mSecure is set?
@@ -789,6 +1155,86 @@
     mSurfaceFlingerConsumer->setTransformHint(orientation);
 }
 
+// ----------------------------------------------------------------------------
+// debugging
+// ----------------------------------------------------------------------------
+
+void Layer::dump(String8& result, char* buffer, size_t SIZE) const
+{
+    const Layer::State& s(drawingState());
+
+    snprintf(buffer, SIZE,
+            "+ %s %p (%s)\n",
+            getTypeId(), this, getName().string());
+    result.append(buffer);
+
+    s.transparentRegion.dump(result, "transparentRegion");
+    visibleRegion.dump(result, "visibleRegion");
+    sp<Client> client(mClientRef.promote());
+
+    snprintf(buffer, SIZE,
+            "      "
+            "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"
+            "      client=%p\n",
+            s.layerStack, s.z, s.transform.tx(), s.transform.ty(), s.active.w, s.active.h,
+            s.active.crop.left, s.active.crop.top,
+            s.active.crop.right, s.active.crop.bottom,
+            isOpaque(), contentDirty,
+            s.alpha, s.flags,
+            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;
+    if (buf0 != 0) {
+        w0 = buf0->getWidth();
+        h0 = buf0->getHeight();
+        s0 = buf0->getStride();
+        f0 = buf0->format;
+    }
+    snprintf(buffer, SIZE,
+            "      "
+            "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);
+    }
+}
+
+
+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 {
+    mFrameTracker.dump(result);
+}
+
+void Layer::clearStats() {
+    mFrameTracker.clear();
+}
+
+// ---------------------------------------------------------------------------
+
+Layer::LayerCleaner::LayerCleaner(const sp<SurfaceFlinger>& flinger,
+        const sp<Layer>& layer)
+    : mFlinger(flinger), mLayer(layer) {
+}
+
+Layer::LayerCleaner::~LayerCleaner() {
+    // destroy client resources
+    mFlinger->onLayerDestroyed(mLayer);
+}
+
 // ---------------------------------------------------------------------------
 
 
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index a82767b..6bca941 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -20,112 +20,343 @@
 #include <stdint.h>
 #include <sys/types.h>
 
-#include <utils/Timers.h>
-
-#include <ui/GraphicBuffer.h>
-#include <ui/PixelFormat.h>
-
-#include <gui/ISurfaceComposerClient.h>
-
 #include <EGL/egl.h>
 #include <EGL/eglext.h>
 #include <GLES/gl.h>
 #include <GLES/glext.h>
 
-#include "SurfaceFlingerConsumer.h"
+#include <utils/RefBase.h>
+#include <utils/String8.h>
+#include <utils/Timers.h>
+
+#include <ui/GraphicBuffer.h>
+#include <ui/PixelFormat.h>
+#include <ui/Region.h>
+
+#include <gui/ISurfaceComposerClient.h>
+
+#include <private/gui/LayerState.h>
+
 #include "FrameTracker.h"
-#include "LayerBase.h"
+#include "Client.h"
+#include "SurfaceFlinger.h"
+#include "SurfaceFlingerConsumer.h"
 #include "SurfaceTextureLayer.h"
 #include "Transform.h"
 
+#include "DisplayHardware/HWComposer.h"
+
 namespace android {
 
 // ---------------------------------------------------------------------------
 
 class Client;
+class DisplayDevice;
+class GraphicBuffer;
+class SurfaceFlinger;
 class GLExtensions;
 
 // ---------------------------------------------------------------------------
 
 /*
- * The Layer class is essentially a LayerBase combined with a BufferQueue.
  * A new BufferQueue and a new SurfaceFlingerConsumer are created when the
  * Layer is first referenced.
  *
  * This also implements onFrameAvailable(), which notifies SurfaceFlinger
  * that new data has arrived.
  */
-class Layer : public LayerBaseClient,
-              public SurfaceFlingerConsumer::FrameAvailableListener
-{
+class Layer : public SurfaceFlingerConsumer::FrameAvailableListener {
+    static int32_t sSequence;
+
 public:
-    Layer(SurfaceFlinger* flinger, const sp<Client>& client);
+    mutable bool contentDirty;
+    // regions below are in window-manager space
+    Region visibleRegion;
+    Region coveredRegion;
+    Region visibleNonTransparentRegion;
+    int32_t sequence;
+
+    enum { // flags for doTransaction()
+        eDontUpdateGeometryState = 0x00000001,
+        eVisibleRegion = 0x00000002,
+    };
+
+    struct Geometry {
+        uint32_t w;
+        uint32_t h;
+        Rect crop;
+        inline bool operator ==(const Geometry& rhs) const {
+            return (w == rhs.w && h == rhs.h && crop == rhs.crop);
+        }
+        inline bool operator !=(const Geometry& rhs) const {
+            return !operator ==(rhs);
+        }
+    };
+
+    struct State {
+        Geometry active;
+        Geometry requested;
+        uint32_t z;
+        uint32_t layerStack;
+        uint8_t alpha;
+        uint8_t flags;
+        uint8_t reserved[2];
+        int32_t sequence; // changes when visible regions can change
+        Transform transform;
+        Region transparentRegion;
+    };
+
+    class LayerMesh {
+        friend class Layer;
+        GLfloat mVertices[4][2];
+        size_t mNumVertices;
+    public:
+        LayerMesh() :
+                mNumVertices(4) {
+        }
+        GLfloat const* getVertices() const {
+            return &mVertices[0][0];
+        }
+        size_t getVertexCount() const {
+            return mNumVertices;
+        }
+    };
+
+    // -----------------------------------------------------------------------
+
+    Layer(SurfaceFlinger* flinger, const sp<Client>& client,
+            const String8& name, uint32_t w, uint32_t h, uint32_t flags);
     virtual ~Layer();
 
+    // the this layer's size and format
+    status_t setBuffers(uint32_t w, uint32_t h, PixelFormat format, uint32_t flags);
+
+    // modify current state
+    bool setPosition(float x, float y);
+    bool setLayer(uint32_t z);
+    bool setSize(uint32_t w, uint32_t h);
+    bool setAlpha(uint8_t alpha);
+    bool setMatrix(const layer_state_t::matrix22_t& matrix);
+    bool setTransparentRegionHint(const Region& transparent);
+    bool setFlags(uint8_t flags, uint8_t mask);
+    bool setCrop(const Rect& crop);
+    bool setLayerStack(uint32_t layerStack);
+
+    void commitTransaction();
+
+    uint32_t getTransactionFlags(uint32_t flags);
+    uint32_t setTransactionFlags(uint32_t flags);
+
+    void computeGeometry(const sp<const DisplayDevice>& hw, LayerMesh* mesh) const;
+    Rect computeBounds() const;
+
+    sp<IBinder> getHandle();
+    sp<BufferQueue> getBufferQueue() const;
+    String8 getName() const;
+
+    // -----------------------------------------------------------------------
+
     virtual const char* getTypeId() const { return "Layer"; }
 
-    // the this layer's size and format
-    status_t setBuffers(uint32_t w, uint32_t h, 
-            PixelFormat format, uint32_t flags=0);
-
-    bool isFixedSize() const;
-
-    // LayerBase interface
     virtual void setGeometry(const sp<const DisplayDevice>& hw,
             HWComposer::HWCLayerInterface& layer);
     virtual void setPerFrameData(const sp<const DisplayDevice>& hw,
             HWComposer::HWCLayerInterface& layer);
     virtual void setAcquireFence(const sp<const DisplayDevice>& hw,
             HWComposer::HWCLayerInterface& layer);
+
+    /*
+     * called after page-flip
+     */
     virtual void onLayerDisplayed(const sp<const DisplayDevice>& hw,
             HWComposer::HWCLayerInterface* layer);
+
+    /*
+     * called before composition.
+     * returns true if the layer has pending updates.
+     */
     virtual bool onPreComposition();
+
+    /*
+     *  called after composition.
+     */
     virtual void onPostComposition();
 
+    /*
+     * draw - performs some global clipping optimizations
+     * and calls onDraw().
+     * Typically this method is not overridden, instead implement onDraw()
+     * to perform the actual drawing.
+     */
+    virtual void draw(const sp<const DisplayDevice>& hw, const Region& clip) const;
+    virtual void draw(const sp<const DisplayDevice>& hw);
+
+    /*
+     * onDraw - draws the surface.
+     */
     virtual void onDraw(const sp<const DisplayDevice>& hw, const Region& clip) const;
+
+    /*
+     * needsLinearFiltering - true if this surface's state requires filtering
+     */
+    virtual bool needsFiltering(const sp<const DisplayDevice>& hw) const;
+
+    /*
+     * doTransaction - process the transaction. This is a good place to figure
+     * out which attributes of the surface have changed.
+     */
     virtual uint32_t doTransaction(uint32_t transactionFlags);
+
+    /*
+     * setVisibleRegion - called to set the new visible region. This gives
+     * a chance to update the new visible region or record the fact it changed.
+     */
+    virtual void setVisibleRegion(const Region& visibleRegion);
+
+    /*
+     * setCoveredRegion - called when the covered region changes. The covered
+     * region corresponds to any area of the surface that is covered
+     * (transparently or not) by another surface.
+     */
+    virtual void setCoveredRegion(const Region& coveredRegion);
+
+    /*
+     * setVisibleNonTransparentRegion - called when the visible and
+     * non-transparent region changes.
+     */
+    virtual void setVisibleNonTransparentRegion(const Region&
+            visibleNonTransparentRegion);
+
+    /*
+     * latchBuffer - called each time the screen is redrawn and returns whether
+     * the visible regions need to be recomputed (this is a fairly heavy
+     * operation, so this should be set only if needed). Typically this is used
+     * to figure out if the content or size of a surface has changed.
+     */
     virtual Region latchBuffer(bool& recomputeVisibleRegions);
+
+    /*
+     * isOpaque - true if this surface is opaque
+     */
     virtual bool isOpaque() const;
+
+    /*
+     * isSecure - true if this surface is secure, that is if it prevents
+     * screenshots or VNC servers.
+     */
     virtual bool isSecure() const           { return mSecure; }
+
+    /*
+     * isProtected - true if the layer may contain protected content in the
+     * GRALLOC_USAGE_PROTECTED sense.
+     */
     virtual bool isProtected() const;
-    virtual void onRemoved();
-    virtual sp<Layer> getLayer() const { return const_cast<Layer*>(this); }
-    virtual void setName(const String8& name);
+
+    /*
+     * isVisible - true if this layer is visible, false otherwise
+     */
     virtual bool isVisible() const;
 
-    // LayerBaseClient interface
-    virtual wp<IBinder> getSurfaceTextureBinder() const;
+    /*
+     * isFixedSize - true if content has a fixed size
+     */
+    virtual bool isFixedSize() const;
 
-    // only for debugging
-    inline const sp<GraphicBuffer>& getActiveBuffer() const { return mActiveBuffer; }
+    /*
+     * called with the state lock when the surface is removed from the
+     * current list
+     */
+    virtual void onRemoved();
+
 
     // Updates the transform hint in our SurfaceFlingerConsumer to match
     // the current orientation of the display device.
     virtual void updateTransformHint(const sp<const DisplayDevice>& hw) const;
 
-protected:
-    virtual void onFirstRef();
+    /*
+     * returns the rectangle that crops the content of the layer and scales it
+     * to the layer's size.
+     */
+    virtual Rect getContentCrop() const;
+
+    /*
+     * returns the transform bits (90 rotation / h-flip / v-flip) of the
+     * layer's content
+     */
+    virtual uint32_t getContentTransform() const;
+
+    // -----------------------------------------------------------------------
+
+    void clearWithOpenGL(const sp<const DisplayDevice>& hw, const Region& clip) const;
+    void setFiltering(bool filtering);
+    bool getFiltering() const;
+
+    // only for debugging
+    inline const sp<GraphicBuffer>& getActiveBuffer() const { return mActiveBuffer; }
+
+    inline  const State&    drawingState() const    { return mDrawingState; }
+    inline  const State&    currentState() const    { return mCurrentState; }
+    inline  State&          currentState()          { return mCurrentState; }
+
+
+    /* 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 clearStats();
 
+protected:
+    // constant
+    sp<SurfaceFlinger> mFlinger;
+
+    virtual void onFirstRef();
+
+    /*
+     * Trivial class, used to ensure that mFlinger->onLayerDestroyed(mLayer)
+     * is called.
+     */
+    class LayerCleaner {
+        sp<SurfaceFlinger> mFlinger;
+        wp<Layer> mLayer;
+    protected:
+        ~LayerCleaner();
+    public:
+        LayerCleaner(const sp<SurfaceFlinger>& flinger, const sp<Layer>& layer);
+    };
+
+
 private:
-    // Creates an instance of ISurface for this Layer.
-    virtual sp<ISurface> createSurface();
-
-    uint32_t getEffectiveUsage(uint32_t usage) const;
-    bool isCropped() const;
-    Rect computeBufferCrop() const;
-    static bool getOpacityForFormat(uint32_t format);
-
     // Interface implementation for SurfaceFlingerConsumer::FrameAvailableListener
     virtual void onFrameAvailable();
 
+
+    uint32_t getEffectiveUsage(uint32_t usage) const;
+    Rect computeCrop(const sp<const DisplayDevice>& hw) const;
+    bool isCropped() const;
+    static bool getOpacityForFormat(uint32_t format);
+
+    // drawing
+    void clearWithOpenGL(const sp<const DisplayDevice>& hw, const Region& clip,
+            GLclampf r, GLclampf g, GLclampf b, GLclampf alpha) const;
+    void drawWithOpenGL(const sp<const DisplayDevice>& hw, const Region& clip) const;
+
+
     // -----------------------------------------------------------------------
 
     // constants
     sp<SurfaceFlingerConsumer> mSurfaceFlingerConsumer;
     GLuint mTextureName;
+    bool mPremultipliedAlpha;
+    String8 mName;
+    mutable bool mDebug;
+    PixelFormat mFormat;
+    const GLExtensions& mGLExtensions;
+    bool mOpaqueLayer;
+
+    // these are protected by an external lock
+    State mCurrentState;
+    State mDrawingState;
+    volatile int32_t mTransactionFlags;
 
     // thread-safe
     volatile int32_t mQueuedFrames;
@@ -139,15 +370,20 @@
     bool mCurrentOpacity;
     bool mRefreshPending;
     bool mFrameLatencyNeeded;
-
-    // constants
-    PixelFormat mFormat;
-    const GLExtensions& mGLExtensions;
-    bool mOpaqueLayer;
+    // Whether filtering is forced on or not
+    bool mFiltering;
+    // Whether filtering is needed b/c of the drawingstate
+    bool mNeedsFiltering;
 
     // page-flip thread (currently main thread)
-    bool mSecure;         // no screenshots
+    bool mSecure; // no screenshots
     bool mProtectedByApp; // application requires protected path to external sink
+
+    // protected by mLock
+    mutable Mutex mLock;
+    // Set to true once we've returned this surface's handle
+    mutable bool mHasSurface;
+    const wp<Client> mClientRef;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp
deleted file mode 100644
index dfdbf30..0000000
--- a/services/surfaceflinger/LayerBase.cpp
+++ /dev/null
@@ -1,565 +0,0 @@
-/*
- * Copyright (C) 2007 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.
- */
-
-#include <stdlib.h>
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <utils/Errors.h>
-#include <utils/Log.h>
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
-
-#include <GLES/gl.h>
-#include <GLES/glext.h>
-
-#include <hardware/hardware.h>
-
-#include "clz.h"
-#include "Client.h"
-#include "LayerBase.h"
-#include "Layer.h"
-#include "SurfaceFlinger.h"
-#include "DisplayDevice.h"
-
-namespace android {
-
-// ---------------------------------------------------------------------------
-
-int32_t LayerBase::sSequence = 1;
-
-LayerBase::LayerBase(SurfaceFlinger* flinger)
-    : contentDirty(false),
-      sequence(uint32_t(android_atomic_inc(&sSequence))),
-      mFlinger(flinger), mFiltering(false),
-      mNeedsFiltering(false),
-      mTransactionFlags(0),
-      mPremultipliedAlpha(true), mName("unnamed"), mDebug(false)
-{
-}
-
-LayerBase::~LayerBase()
-{
-}
-
-void LayerBase::setName(const String8& name) {
-    mName = name;
-}
-
-String8 LayerBase::getName() const {
-    return mName;
-}
-
-void LayerBase::initStates(uint32_t w, uint32_t h, uint32_t flags)
-{
-    uint32_t layerFlags = 0;
-    if (flags & ISurfaceComposerClient::eHidden)
-        layerFlags = layer_state_t::eLayerHidden;
-
-    if (flags & ISurfaceComposerClient::eNonPremultiplied)
-        mPremultipliedAlpha = false;
-
-    mCurrentState.active.w = w;
-    mCurrentState.active.h = h;
-    mCurrentState.active.crop.makeInvalid();
-    mCurrentState.z = 0;
-    mCurrentState.alpha = 0xFF;
-    mCurrentState.layerStack = 0;
-    mCurrentState.flags = layerFlags;
-    mCurrentState.sequence = 0;
-    mCurrentState.transform.set(0, 0);
-    mCurrentState.requested = mCurrentState.active;
-
-    // drawing state & current state are identical
-    mDrawingState = mCurrentState;
-}
-
-bool LayerBase::needsFiltering(const sp<const DisplayDevice>& hw) const {
-    return mNeedsFiltering || hw->needsFiltering();
-}
-
-void LayerBase::commitTransaction() {
-    mDrawingState = mCurrentState;
-}
-void LayerBase::forceVisibilityTransaction() {
-    // this can be called without SurfaceFlinger.mStateLock, but if we
-    // can atomically increment the sequence number, it doesn't matter.
-    android_atomic_inc(&mCurrentState.sequence);
-    requestTransaction();
-}
-bool LayerBase::requestTransaction() {
-    int32_t old = setTransactionFlags(eTransactionNeeded);
-    return ((old & eTransactionNeeded) == 0);
-}
-uint32_t LayerBase::getTransactionFlags(uint32_t flags) {
-    return android_atomic_and(~flags, &mTransactionFlags) & flags;
-}
-uint32_t LayerBase::setTransactionFlags(uint32_t flags) {
-    return android_atomic_or(flags, &mTransactionFlags);
-}
-
-bool LayerBase::setPosition(float x, float y) {
-    if (mCurrentState.transform.tx() == x && mCurrentState.transform.ty() == y)
-        return false;
-    mCurrentState.sequence++;
-    mCurrentState.transform.set(x, y);
-    requestTransaction();
-    return true;
-}
-bool LayerBase::setLayer(uint32_t z) {
-    if (mCurrentState.z == z)
-        return false;
-    mCurrentState.sequence++;
-    mCurrentState.z = z;
-    requestTransaction();
-    return true;
-}
-bool LayerBase::setSize(uint32_t w, uint32_t h) {
-    if (mCurrentState.requested.w == w && mCurrentState.requested.h == h)
-        return false;
-    mCurrentState.requested.w = w;
-    mCurrentState.requested.h = h;
-    requestTransaction();
-    return true;
-}
-bool LayerBase::setAlpha(uint8_t alpha) {
-    if (mCurrentState.alpha == alpha)
-        return false;
-    mCurrentState.sequence++;
-    mCurrentState.alpha = alpha;
-    requestTransaction();
-    return true;
-}
-bool LayerBase::setMatrix(const layer_state_t::matrix22_t& matrix) {
-    mCurrentState.sequence++;
-    mCurrentState.transform.set(
-            matrix.dsdx, matrix.dsdy, matrix.dtdx, matrix.dtdy);
-    requestTransaction();
-    return true;
-}
-bool LayerBase::setTransparentRegionHint(const Region& transparent) {
-    mCurrentState.sequence++;
-    mCurrentState.transparentRegion = transparent;
-    requestTransaction();
-    return true;
-}
-bool LayerBase::setFlags(uint8_t flags, uint8_t mask) {
-    const uint32_t newFlags = (mCurrentState.flags & ~mask) | (flags & mask);
-    if (mCurrentState.flags == newFlags)
-        return false;
-    mCurrentState.sequence++;
-    mCurrentState.flags = newFlags;
-    requestTransaction();
-    return true;
-}
-bool LayerBase::setCrop(const Rect& crop) {
-    if (mCurrentState.requested.crop == crop)
-        return false;
-    mCurrentState.sequence++;
-    mCurrentState.requested.crop = crop;
-    requestTransaction();
-    return true;
-}
-
-bool LayerBase::setLayerStack(uint32_t layerStack) {
-    if (mCurrentState.layerStack == layerStack)
-        return false;
-    mCurrentState.sequence++;
-    mCurrentState.layerStack = layerStack;
-    requestTransaction();
-    return true;
-}
-
-void LayerBase::setVisibleRegion(const Region& visibleRegion) {
-    // always called from main thread
-    this->visibleRegion = visibleRegion;
-}
-
-void LayerBase::setCoveredRegion(const Region& coveredRegion) {
-    // always called from main thread
-    this->coveredRegion = coveredRegion;
-}
-
-void LayerBase::setVisibleNonTransparentRegion(const Region&
-        setVisibleNonTransparentRegion) {
-    // always called from main thread
-    this->visibleNonTransparentRegion = setVisibleNonTransparentRegion;
-}
-
-uint32_t LayerBase::doTransaction(uint32_t flags)
-{
-    const Layer::State& front(drawingState());
-    const Layer::State& temp(currentState());
-
-    // always set active to requested, unless we're asked not to
-    // this is used by Layer, which special cases resizes.
-    if (flags & eDontUpdateGeometryState)  {
-    } else {
-        Layer::State& editTemp(currentState());
-        editTemp.active = temp.requested;
-    }
-
-    if (front.active != temp.active) {
-        // invalidate and recompute the visible regions if needed
-        flags |= Layer::eVisibleRegion;
-    }
-
-    if (temp.sequence != front.sequence) {
-        // invalidate and recompute the visible regions if needed
-        flags |= eVisibleRegion;
-        this->contentDirty = true;
-
-        // we may use linear filtering, if the matrix scales us
-        const uint8_t type = temp.transform.getType();
-        mNeedsFiltering = (!temp.transform.preserveRects() ||
-                (type >= Transform::SCALE));
-    }
-
-    // Commit the transaction
-    commitTransaction();
-    return flags;
-}
-
-void LayerBase::computeGeometry(const sp<const DisplayDevice>& hw, LayerMesh* mesh) const
-{
-    const Layer::State& s(drawingState());
-    const Transform tr(hw->getTransform() * s.transform);
-    const uint32_t hw_h = hw->getHeight();
-    Rect win(s.active.w, s.active.h);
-    if (!s.active.crop.isEmpty()) {
-        win.intersect(s.active.crop, &win);
-    }
-    if (mesh) {
-        tr.transform(mesh->mVertices[0], win.left,  win.top);
-        tr.transform(mesh->mVertices[1], win.left,  win.bottom);
-        tr.transform(mesh->mVertices[2], win.right, win.bottom);
-        tr.transform(mesh->mVertices[3], win.right, win.top);
-        for (size_t i=0 ; i<4 ; i++) {
-            mesh->mVertices[i][1] = hw_h - mesh->mVertices[i][1];
-        }
-    }
-}
-
-Rect LayerBase::computeBounds() const {
-    const Layer::State& s(drawingState());
-    Rect win(s.active.w, s.active.h);
-    if (!s.active.crop.isEmpty()) {
-        win.intersect(s.active.crop, &win);
-    }
-    return s.transform.transform(win);
-}
-
-Region LayerBase::latchBuffer(bool& recomputeVisibleRegions) {
-    Region result;
-    return result;
-}
-
-void LayerBase::setGeometry(
-    const sp<const DisplayDevice>& hw,
-        HWComposer::HWCLayerInterface& layer)
-{
-    layer.setDefaultState();
-
-    // this gives us only the "orientation" component of the transform
-    const State& s(drawingState());
-    const uint32_t finalTransform = s.transform.getOrientation();
-    // we can only handle simple transformation
-    if (finalTransform & Transform::ROT_INVALID) {
-        layer.setTransform(0);
-    } else {
-        layer.setTransform(finalTransform);
-    }
-
-    if (!isOpaque() || s.alpha != 0xFF) {
-        layer.setBlending(mPremultipliedAlpha ?
-                HWC_BLENDING_PREMULT :
-                HWC_BLENDING_COVERAGE);
-    }
-
-    const Transform& tr = hw->getTransform();
-    Rect transformedBounds(computeBounds());
-    transformedBounds = tr.transform(transformedBounds);
-
-    // scaling is already applied in transformedBounds
-    layer.setFrame(transformedBounds);
-    layer.setCrop(transformedBounds.getBounds());
-}
-
-void LayerBase::setPerFrameData(const sp<const DisplayDevice>& hw,
-        HWComposer::HWCLayerInterface& layer) {
-    // we have to set the visible region on every frame because
-    // we currently free it during onLayerDisplayed(), which is called
-    // after HWComposer::commit() -- every frame.
-    const Transform& tr = hw->getTransform();
-    layer.setVisibleRegionScreen(tr.transform(visibleRegion));
-}
-
-void LayerBase::setAcquireFence(const sp<const DisplayDevice>& hw,
-        HWComposer::HWCLayerInterface& layer) {
-    layer.setAcquireFenceFd(-1);
-}
-
-void LayerBase::onLayerDisplayed(const sp<const DisplayDevice>& hw,
-        HWComposer::HWCLayerInterface* layer) {
-    if (layer) {
-        layer->onDisplayed();
-    }
-}
-
-void LayerBase::setFiltering(bool filtering)
-{
-    mFiltering = filtering;
-}
-
-bool LayerBase::getFiltering() const
-{
-    return mFiltering;
-}
-
-bool LayerBase::isVisible() const {
-    const Layer::State& s(mDrawingState);
-    return !(s.flags & layer_state_t::eLayerHidden) && s.alpha;
-}
-
-void LayerBase::draw(const sp<const DisplayDevice>& hw, const Region& clip) const
-{
-    onDraw(hw, clip);
-}
-
-void LayerBase::draw(const sp<const DisplayDevice>& hw)
-{
-    onDraw( hw, Region(hw->bounds()) );
-}
-
-void LayerBase::clearWithOpenGL(const sp<const DisplayDevice>& hw, const Region& clip,
-        GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) const
-{
-    const uint32_t fbHeight = hw->getHeight();
-    glColor4f(red,green,blue,alpha);
-
-    glDisable(GL_TEXTURE_EXTERNAL_OES);
-    glDisable(GL_TEXTURE_2D);
-    glDisable(GL_BLEND);
-
-    LayerMesh mesh;
-    computeGeometry(hw, &mesh);
-
-    glVertexPointer(2, GL_FLOAT, 0, mesh.getVertices());
-    glDrawArrays(GL_TRIANGLE_FAN, 0, mesh.getVertexCount());
-}
-
-void LayerBase::clearWithOpenGL(const sp<const DisplayDevice>& hw, const Region& clip) const
-{
-    clearWithOpenGL(hw, clip, 0,0,0,0);
-}
-
-void LayerBase::drawWithOpenGL(const sp<const DisplayDevice>& hw, const Region& clip) const
-{
-    const uint32_t fbHeight = hw->getHeight();
-    const State& s(drawingState());
-
-    GLenum src = mPremultipliedAlpha ? GL_ONE : GL_SRC_ALPHA;
-    if (CC_UNLIKELY(s.alpha < 0xFF)) {
-        const GLfloat alpha = s.alpha * (1.0f/255.0f);
-        if (mPremultipliedAlpha) {
-            glColor4f(alpha, alpha, alpha, alpha);
-        } else {
-            glColor4f(1, 1, 1, alpha);
-        }
-        glEnable(GL_BLEND);
-        glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA);
-        glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-    } else {
-        glColor4f(1, 1, 1, 1);
-        glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
-        if (!isOpaque()) {
-            glEnable(GL_BLEND);
-            glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA);
-        } else {
-            glDisable(GL_BLEND);
-        }
-    }
-
-    LayerMesh mesh;
-    computeGeometry(hw, &mesh);
-
-    // TODO: we probably want to generate the texture coords with the mesh
-    // here we assume that we only have 4 vertices
-
-    struct TexCoords {
-        GLfloat u;
-        GLfloat v;
-    };
-
-    Rect win(s.active.w, s.active.h);
-    if (!s.active.crop.isEmpty()) {
-        win.intersect(s.active.crop, &win);
-    }
-
-    GLfloat left   = GLfloat(win.left)   / GLfloat(s.active.w);
-    GLfloat top    = GLfloat(win.top)    / GLfloat(s.active.h);
-    GLfloat right  = GLfloat(win.right)  / GLfloat(s.active.w);
-    GLfloat bottom = GLfloat(win.bottom) / GLfloat(s.active.h);
-
-    TexCoords texCoords[4];
-    texCoords[0].u = left;
-    texCoords[0].v = top;
-    texCoords[1].u = left;
-    texCoords[1].v = bottom;
-    texCoords[2].u = right;
-    texCoords[2].v = bottom;
-    texCoords[3].u = right;
-    texCoords[3].v = top;
-    for (int i = 0; i < 4; i++) {
-        texCoords[i].v = 1.0f - texCoords[i].v;
-    }
-
-    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-    glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
-    glVertexPointer(2, GL_FLOAT, 0, mesh.getVertices());
-    glDrawArrays(GL_TRIANGLE_FAN, 0, mesh.getVertexCount());
-
-    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-    glDisable(GL_BLEND);
-}
-
-void LayerBase::dump(String8& result, char* buffer, size_t SIZE) const
-{
-    const Layer::State& s(drawingState());
-
-    snprintf(buffer, SIZE,
-            "+ %s %p (%s)\n",
-            getTypeId(), this, getName().string());
-    result.append(buffer);
-
-    s.transparentRegion.dump(result, "transparentRegion");
-    visibleRegion.dump(result, "visibleRegion");
-
-    snprintf(buffer, SIZE,
-            "      "
-            "layerStack=%4d, z=%9d, pos=(%g,%g), size=(%4d,%4d), crop=(%4d,%4d,%4d,%4d), "
-            "isOpaque=%1d, needsDithering=%1d, invalidate=%1d, "
-            "alpha=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n",
-            s.layerStack, s.z, s.transform.tx(), s.transform.ty(), s.active.w, s.active.h,
-            s.active.crop.left, s.active.crop.top,
-            s.active.crop.right, s.active.crop.bottom,
-            isOpaque(), needsDithering(), contentDirty,
-            s.alpha, s.flags,
-            s.transform[0][0], s.transform[0][1],
-            s.transform[1][0], s.transform[1][1]);
-    result.append(buffer);
-}
-
-void LayerBase::shortDump(String8& result, char* scratch, size_t size) const {
-    LayerBase::dump(result, scratch, size);
-}
-
-void LayerBase::dumpStats(String8& result, char* scratch, size_t SIZE) const {
-}
-
-void LayerBase::clearStats() {
-}
-
-sp<LayerBaseClient> LayerBase::getLayerBaseClient() const {
-    return 0;
-}
-
-sp<Layer> LayerBase::getLayer() const {
-    return 0;
-}
-
-// ---------------------------------------------------------------------------
-
-LayerBaseClient::LayerBaseClient(SurfaceFlinger* flinger,
-        const sp<Client>& client)
-    : LayerBase(flinger),
-      mHasSurface(false),
-      mClientRef(client)
-{
-}
-
-LayerBaseClient::~LayerBaseClient()
-{
-    sp<Client> c(mClientRef.promote());
-    if (c != 0) {
-        c->detachLayer(this);
-    }
-}
-
-sp<ISurface> LayerBaseClient::createSurface()
-{
-    class BSurface : public BnSurface, public LayerCleaner {
-        virtual sp<IGraphicBufferProducer> getSurfaceTexture() const { return 0; }
-    public:
-        BSurface(const sp<SurfaceFlinger>& flinger,
-                const sp<LayerBaseClient>& layer)
-            : LayerCleaner(flinger, layer) { }
-    };
-    sp<ISurface> sur(new BSurface(mFlinger, this));
-    return sur;
-}
-
-sp<ISurface> LayerBaseClient::getSurface()
-{
-    sp<ISurface> s;
-    Mutex::Autolock _l(mLock);
-
-    LOG_ALWAYS_FATAL_IF(mHasSurface,
-            "LayerBaseClient::getSurface() has already been called");
-
-    mHasSurface = true;
-    s = createSurface();
-    mClientSurfaceBinder = s->asBinder();
-    return s;
-}
-
-wp<IBinder> LayerBaseClient::getSurfaceBinder() const {
-    return mClientSurfaceBinder;
-}
-
-wp<IBinder> LayerBaseClient::getSurfaceTextureBinder() const {
-    return 0;
-}
-
-void LayerBaseClient::dump(String8& result, char* buffer, size_t SIZE) const
-{
-    LayerBase::dump(result, buffer, SIZE);
-    sp<Client> client(mClientRef.promote());
-    snprintf(buffer, SIZE, "      client=%p\n", client.get());
-    result.append(buffer);
-}
-
-
-void LayerBaseClient::shortDump(String8& result, char* scratch, size_t size) const
-{
-    LayerBaseClient::dump(result, scratch, size);
-}
-
-// ---------------------------------------------------------------------------
-
-LayerBaseClient::LayerCleaner::LayerCleaner(const sp<SurfaceFlinger>& flinger,
-        const sp<LayerBaseClient>& layer)
-    : mFlinger(flinger), mLayer(layer) {
-}
-
-LayerBaseClient::LayerCleaner::~LayerCleaner() {
-    // destroy client resources
-    mFlinger->onLayerDestroyed(mLayer);
-}
-
-// ---------------------------------------------------------------------------
-
-}; // namespace android
diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h
deleted file mode 100644
index c2624df..0000000
--- a/services/surfaceflinger/LayerBase.h
+++ /dev/null
@@ -1,386 +0,0 @@
-/*
- * Copyright (C) 2007 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_LAYER_BASE_H
-#define ANDROID_LAYER_BASE_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-#include <GLES/gl.h>
-
-#include <utils/RefBase.h>
-#include <utils/String8.h>
-
-#include <ui/Region.h>
-
-#include <gui/ISurfaceComposerClient.h>
-
-#include <private/gui/LayerState.h>
-
-#include "Transform.h"
-#include "DisplayHardware/HWComposer.h"
-
-namespace android {
-
-// ---------------------------------------------------------------------------
-
-class Client;
-class DisplayDevice;
-class GraphicBuffer;
-class Layer;
-class LayerBaseClient;
-class SurfaceFlinger;
-
-// ---------------------------------------------------------------------------
-
-/*
- * Layers are rectangular graphic entities, internal to SurfaceFlinger.
- * They have properties including width, height, Z-depth, and 2D
- * transformations (chiefly translation and 90-degree rotations).
- *
- * Layers are organized into "layer stacks".  Each layer is a member of
- * exactly one layer stack, identified by an integer in Layer::State.  A
- * given layer stack may appear on more than one display.
- *
- * Notable subclasses (below LayerBaseClient) include Layer, LayerDim, and
- * LayerScreenshot.
- */
-class LayerBase : virtual public RefBase
-{
-    static int32_t sSequence;
-
-public:
-            LayerBase(SurfaceFlinger* flinger);
-
-    mutable bool        contentDirty;
-            // regions below are in window-manager space
-            Region      visibleRegion;
-            Region      coveredRegion;
-            Region      visibleNonTransparentRegion;
-            int32_t     sequence;
-            
-            struct Geometry {
-                uint32_t w;
-                uint32_t h;
-                Rect crop;
-                inline bool operator == (const Geometry& rhs) const {
-                    return (w==rhs.w && h==rhs.h && crop==rhs.crop);
-                }
-                inline bool operator != (const Geometry& rhs) const {
-                    return !operator == (rhs);
-                }
-            };
-
-            struct State {
-                Geometry        active;
-                Geometry        requested;
-                uint32_t        z;
-                uint32_t        layerStack;
-                uint8_t         alpha;
-                uint8_t         flags;
-                uint8_t         reserved[2];
-                int32_t         sequence;   // changes when visible regions can change
-                Transform       transform;
-                Region          transparentRegion;
-            };
-
-            class LayerMesh {
-                friend class LayerBase;
-                GLfloat mVertices[4][2];
-                size_t mNumVertices;
-            public:
-                LayerMesh() : mNumVertices(4) { }
-                GLfloat const* getVertices() const {
-                    return &mVertices[0][0];
-                }
-                size_t getVertexCount() const {
-                    return mNumVertices;
-                }
-            };
-
-    virtual void setName(const String8& name);
-            String8 getName() const;
-
-            // modify current state
-            bool setPosition(float x, float y);
-            bool setLayer(uint32_t z);
-            bool setSize(uint32_t w, uint32_t h);
-            bool setAlpha(uint8_t alpha);
-            bool setMatrix(const layer_state_t::matrix22_t& matrix);
-            bool setTransparentRegionHint(const Region& transparent);
-            bool setFlags(uint8_t flags, uint8_t mask);
-            bool setCrop(const Rect& crop);
-            bool setLayerStack(uint32_t layerStack);
-
-            void commitTransaction();
-            bool requestTransaction();
-            void forceVisibilityTransaction();
-            
-            uint32_t getTransactionFlags(uint32_t flags);
-            uint32_t setTransactionFlags(uint32_t flags);
-
-            void computeGeometry(const sp<const DisplayDevice>& hw, LayerMesh* mesh) const;
-            Rect computeBounds() const;
-
-
-    virtual sp<LayerBaseClient> getLayerBaseClient() const;
-    virtual sp<Layer> getLayer() const;
-
-    virtual const char* getTypeId() const { return "LayerBase"; }
-
-    virtual void setGeometry(const sp<const DisplayDevice>& hw,
-            HWComposer::HWCLayerInterface& layer);
-    virtual void setPerFrameData(const sp<const DisplayDevice>& hw,
-            HWComposer::HWCLayerInterface& layer);
-    virtual void setAcquireFence(const sp<const DisplayDevice>& hw,
-            HWComposer::HWCLayerInterface& layer);
-
-    /**
-     * draw - performs some global clipping optimizations
-     * and calls onDraw().
-     * Typically this method is not overridden, instead implement onDraw()
-     * to perform the actual drawing.  
-     */
-    virtual void draw(const sp<const DisplayDevice>& hw, const Region& clip) const;
-    virtual void draw(const sp<const DisplayDevice>& hw);
-    
-    /**
-     * onDraw - draws the surface.
-     */
-    virtual void onDraw(const sp<const DisplayDevice>& hw, const Region& clip) const = 0;
-    
-    /**
-     * initStates - called just after construction
-     */
-    virtual void initStates(uint32_t w, uint32_t h, uint32_t flags);
-    
-    /**
-     * doTransaction - process the transaction. This is a good place to figure
-     * out which attributes of the surface have changed.
-     */
-    virtual uint32_t doTransaction(uint32_t transactionFlags);
-    
-    /**
-     * setVisibleRegion - called to set the new visible region. This gives
-     * a chance to update the new visible region or record the fact it changed.
-     */
-    virtual void setVisibleRegion(const Region& visibleRegion);
-    
-    /**
-     * setCoveredRegion - called when the covered region changes. The covered
-     * region corresponds to any area of the surface that is covered
-     * (transparently or not) by another surface.
-     */
-    virtual void setCoveredRegion(const Region& coveredRegion);
-
-    /**
-     * setVisibleNonTransparentRegion - called when the visible and
-     * non-transparent region changes.
-     */
-    virtual void setVisibleNonTransparentRegion(const Region&
-            visibleNonTransparentRegion);
-
-    /**
-     * latchBuffer - called each time the screen is redrawn and returns whether
-     * the visible regions need to be recomputed (this is a fairly heavy
-     * operation, so this should be set only if needed). Typically this is used
-     * to figure out if the content or size of a surface has changed.
-     */
-    virtual Region latchBuffer(bool& recomputeVisibleRegions);
-
-    /**
-     * isOpaque - true if this surface is opaque
-     */
-    virtual bool isOpaque() const  { return true; }
-
-    /**
-     * needsDithering - true if this surface needs dithering
-     */
-    virtual bool needsDithering() const { return false; }
-
-    /**
-     * needsLinearFiltering - true if this surface's state requires filtering
-     */
-    virtual bool needsFiltering(const sp<const DisplayDevice>& hw) const;
-
-    /**
-     * isSecure - true if this surface is secure, that is if it prevents
-     * screenshots or VNC servers.
-     */
-    virtual bool isSecure() const       { return false; }
-
-    /**
-     * isProtected - true if the layer may contain protected content in the
-     * GRALLOC_USAGE_PROTECTED sense.
-     */
-    virtual bool isProtected() const   { return false; }
-
-    /*
-     * isVisible - true if this layer is visibile, false otherwise
-     */
-    virtual bool isVisible() const;
-
-    /** called with the state lock when the surface is removed from the
-     *  current list */
-    virtual void onRemoved() { }
-
-    /** called after page-flip
-     */
-    virtual void onLayerDisplayed(const sp<const DisplayDevice>& hw,
-            HWComposer::HWCLayerInterface* layer);
-
-    /** called before composition.
-     * returns true if the layer has pending updates.
-     */
-    virtual bool onPreComposition() { return false; }
-
-    /** called before composition.
-     */
-    virtual void onPostComposition() { }
-
-    /**
-     * Updates the GLConsumer's transform hint, for layers that have
-     * a GLConsumer.
-     */
-    virtual void updateTransformHint(const sp<const DisplayDevice>& hw) const { }
-
-    /** 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 clearStats();
-
-
-    enum { // flags for doTransaction()
-        eDontUpdateGeometryState = 0x00000001,
-        eVisibleRegion           = 0x00000002,
-    };
-
-
-    inline  const State&    drawingState() const    { return mDrawingState; }
-    inline  const State&    currentState() const    { return mCurrentState; }
-    inline  State&          currentState()          { return mCurrentState; }
-
-    void clearWithOpenGL(const sp<const DisplayDevice>& hw, const Region& clip) const;
-
-    void setFiltering(bool filtering);
-    bool getFiltering() const;
-
-protected:
-          void clearWithOpenGL(const sp<const DisplayDevice>& hw, const Region& clip,
-                  GLclampf r, GLclampf g, GLclampf b, GLclampf alpha) const;
-          void drawWithOpenGL(const sp<const DisplayDevice>& hw, const Region& clip) const;
-
-                sp<SurfaceFlinger> mFlinger;
-
-private:
-                // accessed only in the main thread
-                // Whether filtering is forced on or not
-                bool            mFiltering;
-
-                // Whether filtering is needed b/c of the drawingstate
-                bool            mNeedsFiltering;
-
-protected:
-                // these are protected by an external lock
-                State           mCurrentState;
-                State           mDrawingState;
-    volatile    int32_t         mTransactionFlags;
-
-                // don't change, don't need a lock
-                bool            mPremultipliedAlpha;
-                String8         mName;
-    mutable     bool            mDebug;
-
-
-public:
-    // called from class SurfaceFlinger
-    virtual ~LayerBase();
-
-private:
-    LayerBase(const LayerBase& rhs);
-};
-
-
-// ---------------------------------------------------------------------------
-
-/*
- * This adds some additional fields and methods to support some Binder IPC
- * interactions.  In particular, the LayerBaseClient's lifetime can be
- * managed by references to an ISurface object in another process.
- */
-class LayerBaseClient : public LayerBase
-{
-public:
-    LayerBaseClient(SurfaceFlinger* flinger, const sp<Client>& client);
-
-    virtual ~LayerBaseClient();
-
-    // Creates an ISurface associated with this object.  This may only be
-    // called once (see also getSurfaceBinder()).
-    sp<ISurface> getSurface();
-
-    // Returns the Binder object for the ISurface associated with
-    // this object.
-    wp<IBinder> getSurfaceBinder() const;
-
-    virtual wp<IBinder> getSurfaceTextureBinder() const;
-
-    virtual sp<LayerBaseClient> getLayerBaseClient() const {
-        return const_cast<LayerBaseClient*>(this); }
-
-    virtual const char* getTypeId() const { return "LayerBaseClient"; }
-
-protected:
-    virtual void dump(String8& result, char* scratch, size_t size) const;
-    virtual void shortDump(String8& result, char* scratch, size_t size) const;
-
-    /*
-     * Trivial class, used to ensure that mFlinger->onLayerDestroyed(mLayer)
-     * is called.
-     */
-    class LayerCleaner {
-        sp<SurfaceFlinger> mFlinger;
-        wp<LayerBaseClient> mLayer;
-    protected:
-        ~LayerCleaner();
-    public:
-        LayerCleaner(const sp<SurfaceFlinger>& flinger,
-                const sp<LayerBaseClient>& layer);
-    };
-
-private:
-    virtual sp<ISurface> createSurface();
-
-    mutable Mutex mLock;
-
-    // Set to true if an ISurface has been associated with this object.
-    mutable bool mHasSurface;
-
-    // The ISurface's Binder object, set by getSurface().
-    wp<IBinder> mClientSurfaceBinder;
-
-    const wp<Client> mClientRef;
-};
-
-// ---------------------------------------------------------------------------
-
-}; // namespace android
-
-#endif // ANDROID_LAYER_BASE_H
diff --git a/services/surfaceflinger/LayerDim.cpp b/services/surfaceflinger/LayerDim.cpp
index 25caa0a..36bafdb 100644
--- a/services/surfaceflinger/LayerDim.cpp
+++ b/services/surfaceflinger/LayerDim.cpp
@@ -33,13 +33,12 @@
 namespace android {
 // ---------------------------------------------------------------------------
 
-LayerDim::LayerDim(SurfaceFlinger* flinger, const sp<Client>& client)
-    : LayerBaseClient(flinger, client)
-{
+LayerDim::LayerDim(SurfaceFlinger* flinger, const sp<Client>& client,
+        const String8& name, uint32_t w, uint32_t h, uint32_t flags)
+    : Layer(flinger, client, name, w, h, flags) {
 }
 
-LayerDim::~LayerDim()
-{
+LayerDim::~LayerDim() {
 }
 
 void LayerDim::onDraw(const sp<const DisplayDevice>& hw, const Region& clip) const
@@ -71,6 +70,12 @@
     }
 }
 
+bool LayerDim::isVisible() const {
+    const Layer::State& s(drawingState());
+    return !(s.flags & layer_state_t::eLayerHidden) && s.alpha;
+}
+
+
 // ---------------------------------------------------------------------------
 
 }; // namespace android
diff --git a/services/surfaceflinger/LayerDim.h b/services/surfaceflinger/LayerDim.h
index 06f312d..e19bf52 100644
--- a/services/surfaceflinger/LayerDim.h
+++ b/services/surfaceflinger/LayerDim.h
@@ -23,16 +23,17 @@
 #include <EGL/egl.h>
 #include <EGL/eglext.h>
 
-#include "LayerBase.h"
+#include "Layer.h"
 
 // ---------------------------------------------------------------------------
 
 namespace android {
 
-class LayerDim : public LayerBaseClient
+class LayerDim : public Layer
 {
 public:    
-                LayerDim(SurfaceFlinger* flinger, const sp<Client>& client);
+                LayerDim(SurfaceFlinger* flinger, const sp<Client>& client,
+                        const String8& name, uint32_t w, uint32_t h, uint32_t flags);
         virtual ~LayerDim();
 
     virtual void onDraw(const sp<const DisplayDevice>& hw, const Region& clip) const;
@@ -41,6 +42,9 @@
     virtual bool isProtectedByApp() const { return false; }
     virtual bool isProtectedByDRM() const { return false; }
     virtual const char* getTypeId() const { return "LayerDim"; }
+
+    virtual bool isFixedSize() const      { return true; }
+    virtual bool isVisible() const;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/LayerScreenshot.cpp b/services/surfaceflinger/LayerScreenshot.cpp
deleted file mode 100644
index f8009b3..0000000
--- a/services/surfaceflinger/LayerScreenshot.cpp
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdlib.h>
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <GLES/gl.h>
-#include <GLES/glext.h>
-
-#include <utils/Errors.h>
-#include <utils/Log.h>
-
-#include <ui/GraphicBuffer.h>
-
-#include "LayerScreenshot.h"
-#include "SurfaceFlinger.h"
-#include "DisplayDevice.h"
-
-
-namespace android {
-// ---------------------------------------------------------------------------
-
-LayerScreenshot::LayerScreenshot(SurfaceFlinger* flinger,
-        const sp<Client>& client)
-    : LayerBaseClient(flinger, client),
-      mTextureName(0), mFlinger(flinger), mIsSecure(false)
-{
-}
-
-LayerScreenshot::~LayerScreenshot()
-{
-    if (mTextureName) {
-        mFlinger->deleteTextureAsync(mTextureName);
-    }
-}
-
-status_t LayerScreenshot::captureLocked(int32_t layerStack) {
-    GLfloat u, v;
-    status_t result = mFlinger->renderScreenToTextureLocked(layerStack,
-            &mTextureName, &u, &v);
-    if (result != NO_ERROR) {
-        return result;
-    }
-    initTexture(u, v);
-
-    // Currently screenshot always comes from the default display
-    mIsSecure = mFlinger->getDefaultDisplayDevice()->getSecureLayerVisible();
-
-    return NO_ERROR;
-}
-
-status_t LayerScreenshot::capture() {
-    GLfloat u, v;
-    status_t result = mFlinger->renderScreenToTexture(0, &mTextureName, &u, &v);
-    if (result != NO_ERROR) {
-        return result;
-    }
-    initTexture(u, v);
-
-    // Currently screenshot always comes from the default display
-    mIsSecure = mFlinger->getDefaultDisplayDevice()->getSecureLayerVisible();
-    
-    return NO_ERROR;
-}
-
-void LayerScreenshot::initTexture(GLfloat u, GLfloat v) {
-    glBindTexture(GL_TEXTURE_2D, mTextureName);
-    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-    mTexCoords[0] = 0;         mTexCoords[1] = v;
-    mTexCoords[2] = 0;         mTexCoords[3] = 0;
-    mTexCoords[4] = u;         mTexCoords[5] = 0;
-    mTexCoords[6] = u;         mTexCoords[7] = v;
-}
-
-void LayerScreenshot::initStates(uint32_t w, uint32_t h, uint32_t flags) {
-    LayerBaseClient::initStates(w, h, flags);
-    if (!(flags & ISurfaceComposerClient::eHidden)) {
-        capture();
-    }
-    if (flags & ISurfaceComposerClient::eSecure) {
-        ALOGW("ignoring surface flag eSecure - LayerScreenshot is considered "
-                "secure iff it captures the contents of a secure surface.");
-    }
-}
-
-uint32_t LayerScreenshot::doTransaction(uint32_t flags)
-{
-    const LayerBase::State& draw(drawingState());
-    const LayerBase::State& curr(currentState());
-
-    if (draw.flags & layer_state_t::eLayerHidden) {
-        if (!(curr.flags & layer_state_t::eLayerHidden)) {
-            // we're going from hidden to visible
-            status_t err = captureLocked(curr.layerStack);
-            if (err != NO_ERROR) {
-                ALOGW("createScreenshotSurface failed (%s)", strerror(-err));
-            }
-        }
-    } else if (curr.flags & layer_state_t::eLayerHidden) {
-        // we're going from visible to hidden
-        if (mTextureName) {
-            glDeleteTextures(1, &mTextureName);
-            mTextureName = 0;
-        }
-    }
-    return LayerBaseClient::doTransaction(flags);
-}
-
-void LayerScreenshot::onDraw(const sp<const DisplayDevice>& hw, const Region& clip) const
-{
-    const State& s(drawingState());
-    if (s.alpha>0) {
-        const GLfloat alpha = s.alpha/255.0f;
-        const uint32_t fbHeight = hw->getHeight();
-
-        if (s.alpha == 0xFF) {
-            glDisable(GL_BLEND);
-            glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
-        } else {
-            glEnable(GL_BLEND);
-            glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
-            glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-        }
-
-        GLuint texName = mTextureName;
-        if (isSecure() && !hw->isSecure()) {
-            texName = mFlinger->getProtectedTexName();
-        }
-
-        LayerMesh mesh;
-        computeGeometry(hw, &mesh);
-
-        glColor4f(alpha, alpha, alpha, alpha);
-
-        glDisable(GL_TEXTURE_EXTERNAL_OES);
-        glEnable(GL_TEXTURE_2D);
-
-        glBindTexture(GL_TEXTURE_2D, texName);
-        glMatrixMode(GL_TEXTURE);
-        glLoadIdentity();
-        glMatrixMode(GL_MODELVIEW);
-
-        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-        glTexCoordPointer(2, GL_FLOAT, 0, mTexCoords);
-        glVertexPointer(2, GL_FLOAT, 0, mesh.getVertices());
-        glDrawArrays(GL_TRIANGLE_FAN, 0, mesh.getVertexCount());
-
-        glDisable(GL_BLEND);
-        glDisable(GL_TEXTURE_2D);
-        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-    }
-}
-
-// ---------------------------------------------------------------------------
-
-}; // namespace android
diff --git a/services/surfaceflinger/LayerScreenshot.h b/services/surfaceflinger/LayerScreenshot.h
deleted file mode 100644
index 38cbd88..0000000
--- a/services/surfaceflinger/LayerScreenshot.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_LAYER_SCREENSHOT_H
-#define ANDROID_LAYER_SCREENSHOT_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-
-#include "LayerBase.h"
-
-// ---------------------------------------------------------------------------
-
-namespace android {
-
-class LayerScreenshot : public LayerBaseClient
-{
-    GLuint mTextureName;
-    GLfloat mTexCoords[8];
-    sp<SurfaceFlinger> mFlinger;
-    bool mIsSecure;
-public:    
-            LayerScreenshot(SurfaceFlinger* flinger, const sp<Client>& client);
-        virtual ~LayerScreenshot();
-
-        status_t capture();
-
-    virtual void initStates(uint32_t w, uint32_t h, uint32_t flags);
-    virtual uint32_t doTransaction(uint32_t flags);
-    virtual void onDraw(const sp<const DisplayDevice>& hw, const Region& clip) const;
-    virtual bool isOpaque() const         { return false; }
-    virtual bool isSecure() const         { return mIsSecure; }
-    virtual bool isProtectedByApp() const { return false; }
-    virtual bool isProtectedByDRM() const { return false; }
-    virtual const char* getTypeId() const { return "LayerScreenshot"; }
-
-private:
-    status_t captureLocked(int32_t layerStack);
-    void initTexture(GLfloat u, GLfloat v);
-};
-
-// ---------------------------------------------------------------------------
-
-}; // namespace android
-
-#endif // ANDROID_LAYER_SCREENSHOT_H
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index ee3e93b..8546920 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -62,11 +62,11 @@
 #include "GLExtensions.h"
 #include "Layer.h"
 #include "LayerDim.h"
-#include "LayerScreenshot.h"
 #include "SurfaceFlinger.h"
 
 #include "DisplayHardware/FramebufferSurface.h"
 #include "DisplayHardware/HWComposer.h"
+#include "DisplayHardware/VirtualDisplaySurface.h"
 
 
 #define EGL_VERSION_HW_ANDROID  0x3143
@@ -502,11 +502,9 @@
             createBuiltinDisplayLocked(type);
             wp<IBinder> token = mBuiltinDisplays[i];
 
-            sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i);
-            sp<Surface> stc = new Surface(
-                        static_cast< sp<IGraphicBufferProducer> >(fbs->getBufferQueue()));
             sp<DisplayDevice> hw = new DisplayDevice(this,
-                    type, isSecure, token, stc, fbs, mEGLConfig);
+                    type, isSecure, token, new FramebufferSurface(*mHwc, i),
+                    mEGLConfig);
             if (i > DisplayDevice::DISPLAY_PRIMARY) {
                 // FIXME: currently we don't get blank/unblank requests
                 // for displays other than the main display, so we always
@@ -575,46 +573,7 @@
         const sp<IGraphicBufferProducer>& bufferProducer) const {
     Mutex::Autolock _l(mStateLock);
     sp<IBinder> surfaceTextureBinder(bufferProducer->asBinder());
-
-    // We want to determine whether the IGraphicBufferProducer was created by
-    // SurfaceFlinger.  Check to see if we can find it in the layer list.
-    const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
-    size_t count = currentLayers.size();
-    for (size_t i=0 ; i<count ; i++) {
-        const sp<LayerBase>& layer(currentLayers[i]);
-        sp<LayerBaseClient> lbc(layer->getLayerBaseClient());
-        if (lbc != NULL) {
-            // If this is an instance of Layer (as opposed to, say, LayerDim),
-            // we will get the consumer interface of SurfaceFlingerConsumer's
-            // BufferQueue.  If it's the same Binder object as the graphic
-            // buffer producer interface, return success.
-            wp<IBinder> lbcBinder = lbc->getSurfaceTextureBinder();
-            if (lbcBinder == surfaceTextureBinder) {
-                return true;
-            }
-        }
-    }
-
-    // Check the layers in the purgatory.  This check is here so that if a
-    // GLConsumer gets destroyed before all the clients are done using it,
-    // the error will not be reported as "surface XYZ is not authenticated", but
-    // will instead fail later on when the client tries to use the surface,
-    // which should be reported as "surface XYZ returned an -ENODEV".  The
-    // purgatorized layers are no less authentic than the visible ones, so this
-    // should not cause any harm.
-    size_t purgatorySize =  mLayerPurgatory.size();
-    for (size_t i=0 ; i<purgatorySize ; i++) {
-        const sp<LayerBase>& layer(mLayerPurgatory.itemAt(i));
-        sp<LayerBaseClient> lbc(layer->getLayerBaseClient());
-        if (lbc != NULL) {
-            wp<IBinder> lbcBinder = lbc->getSurfaceTextureBinder();
-            if (lbcBinder == surfaceTextureBinder) {
-                return true;
-            }
-        }
-    }
-
-    return false;
+    return mGraphicBufferProducerList.indexOf(surfaceTextureBinder) >= 0;
 }
 
 status_t SurfaceFlinger::getDisplayInfo(const sp<IBinder>& display, DisplayInfo* info) {
@@ -915,7 +874,7 @@
         for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
             Region opaqueRegion;
             Region dirtyRegion;
-            Vector< sp<LayerBase> > layersSortedByZ;
+            Vector< sp<Layer> > layersSortedByZ;
             const sp<DisplayDevice>& hw(mDisplays[dpy]);
             const Transform& tr(hw->getTransform());
             const Rect bounds(hw->getBounds());
@@ -925,7 +884,7 @@
 
                 const size_t count = currentLayers.size();
                 for (size_t i=0 ; i<count ; i++) {
-                    const sp<LayerBase>& layer(currentLayers[i]);
+                    const sp<Layer>& layer(currentLayers[i]);
                     const Layer::State& s(layer->drawingState());
                     if (s.layerStack == hw->getLayerStack()) {
                         Region drawRegion(tr.transform(
@@ -955,14 +914,14 @@
                 sp<const DisplayDevice> hw(mDisplays[dpy]);
                 const int32_t id = hw->getHwcDisplayId();
                 if (id >= 0) {
-                    const Vector< sp<LayerBase> >& currentLayers(
+                    const Vector< sp<Layer> >& currentLayers(
                         hw->getVisibleLayersSortedByZ());
                     const size_t count = currentLayers.size();
                     if (hwc.createWorkList(id, count) == NO_ERROR) {
                         HWComposer::LayerListIterator cur = hwc.begin(id);
                         const HWComposer::LayerListIterator end = hwc.end(id);
                         for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) {
-                            const sp<LayerBase>& layer(currentLayers[i]);
+                            const sp<Layer>& layer(currentLayers[i]);
                             layer->setGeometry(hw, *cur);
                             if (mDebugDisableHWC || mDebugRegion) {
                                 cur->setSkip(true);
@@ -978,7 +937,7 @@
             sp<const DisplayDevice> hw(mDisplays[dpy]);
             const int32_t id = hw->getHwcDisplayId();
             if (id >= 0) {
-                const Vector< sp<LayerBase> >& currentLayers(
+                const Vector< sp<Layer> >& currentLayers(
                     hw->getVisibleLayersSortedByZ());
                 const size_t count = currentLayers.size();
                 HWComposer::LayerListIterator cur = hwc.begin(id);
@@ -988,7 +947,7 @@
                      * update the per-frame h/w composer data for each layer
                      * and build the transparent region of the FB
                      */
-                    const sp<LayerBase>& layer(currentLayers[i]);
+                    const sp<Layer>& layer(currentLayers[i]);
                     layer->setPerFrameData(hw, *cur);
                 }
             }
@@ -1042,7 +1001,7 @@
 
     for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
         sp<const DisplayDevice> hw(mDisplays[dpy]);
-        const Vector< sp<LayerBase> >& currentLayers(hw->getVisibleLayersSortedByZ());
+        const Vector< sp<Layer> >& currentLayers(hw->getVisibleLayersSortedByZ());
         hw->onSwapBuffersCompleted(hwc);
         const size_t count = currentLayers.size();
         int32_t id = hw->getHwcDisplayId();
@@ -1098,7 +1057,7 @@
 
     if (transactionFlags & eTraversalNeeded) {
         for (size_t i=0 ; i<count ; i++) {
-            const sp<LayerBase>& layer(currentLayers[i]);
+            const sp<Layer>& layer(currentLayers[i]);
             uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded);
             if (!trFlags) continue;
 
@@ -1139,7 +1098,8 @@
                         DisplayDevice::makeCurrent(mEGLDisplay, hw, mEGLContext);
                         mDisplays.removeItem(draw.keyAt(i));
                         getHwComposer().disconnectDisplay(draw[i].type);
-                        mEventThread->onHotplugReceived(draw[i].type, false);
+                        if (draw[i].type < DisplayDevice::NUM_DISPLAY_TYPES)
+                            mEventThread->onHotplugReceived(draw[i].type, false);
                     } else {
                         ALOGW("trying to remove the main display");
                     }
@@ -1181,10 +1141,14 @@
                 if (draw.indexOfKey(curr.keyAt(i)) < 0) {
                     const DisplayDeviceState& state(curr[i]);
 
-                    sp<FramebufferSurface> fbs;
-                    sp<Surface> stc;
-                    if (!state.isVirtualDisplay()) {
-
+                    sp<DisplaySurface> dispSurface;
+                    if (state.isVirtualDisplay()) {
+                        if (state.surface != NULL) {
+                            dispSurface = new VirtualDisplaySurface(
+                                    *mHwc, state.type, state.surface,
+                                    state.displayName);
+                        }
+                    } else {
                         ALOGE_IF(state.surface!=NULL,
                                 "adding a supported display, but rendering "
                                 "surface is provided (%p), ignoring it",
@@ -1192,27 +1156,21 @@
 
                         // for supported (by hwc) displays we provide our
                         // own rendering surface
-                        fbs = new FramebufferSurface(*mHwc, state.type);
-                        stc = new Surface(
-                                static_cast< sp<IGraphicBufferProducer> >(
-                                        fbs->getBufferQueue()));
-                    } else {
-                        if (state.surface != NULL) {
-                            stc = new Surface(state.surface);
-                        }
+                        dispSurface = new FramebufferSurface(*mHwc, state.type);
                     }
 
                     const wp<IBinder>& display(curr.keyAt(i));
-                    if (stc != NULL) {
+                    if (dispSurface != NULL) {
                         sp<DisplayDevice> hw = new DisplayDevice(this,
-                                state.type, state.isSecure, display, stc, fbs,
-                                mEGLConfig);
+                                state.type, state.isSecure, display,
+                                dispSurface, mEGLConfig);
                         hw->setLayerStack(state.layerStack);
                         hw->setProjection(state.orientation,
                                 state.viewport, state.frame);
                         hw->setDisplayName(state.displayName);
                         mDisplays.add(display, hw);
-                        mEventThread->onHotplugReceived(state.type, true);
+                        if (state.type < DisplayDevice::NUM_DISPLAY_TYPES)
+                            mEventThread->onHotplugReceived(state.type, true);
                     }
                 }
             }
@@ -1245,8 +1203,8 @@
             // NOTE: we rely on the fact that layers are sorted by
             // layerStack first (so we don't have to traverse the list
             // of displays for every layer).
-            const sp<LayerBase>& layerBase(currentLayers[i]);
-            uint32_t layerStack = layerBase->drawingState().layerStack;
+            const sp<Layer>& layer(currentLayers[i]);
+            uint32_t layerStack = layer->drawingState().layerStack;
             if (i==0 || currentlayerStack != layerStack) {
                 currentlayerStack = layerStack;
                 // figure out if this layerstack is mirrored
@@ -1268,7 +1226,7 @@
             if (disp != NULL) {
                 // presumably this means this layer is using a layerStack
                 // that is not visible on any display
-                layerBase->updateTransformHint(disp);
+                layer->updateTransformHint(disp);
             }
         }
     }
@@ -1291,7 +1249,7 @@
         mVisibleRegionsDirty = true;
         const size_t count = previousLayers.size();
         for (size_t i=0 ; i<count ; i++) {
-            const sp<LayerBase>& layer(previousLayers[i]);
+            const sp<Layer>& layer(previousLayers[i]);
             if (currentLayers.indexOf(layer) < 0) {
                 // this layer is not visible anymore
                 // TODO: we could traverse the tree from front to back and
@@ -1342,12 +1300,12 @@
 
     size_t i = currentLayers.size();
     while (i--) {
-        const sp<LayerBase>& layer = currentLayers[i];
+        const sp<Layer>& layer = currentLayers[i];
 
         // start with the whole surface at its current location
         const Layer::State& s(layer->drawingState());
 
-        // only consider the layers on the given later stack
+        // only consider the layers on the given layer stack
         if (s.layerStack != layerStack)
             continue;
 
@@ -1384,7 +1342,7 @@
         // handle hidden surfaces by setting the visible region to empty
         if (CC_LIKELY(layer->isVisible())) {
             const bool translucent = !layer->isOpaque();
-            Rect bounds(layer->computeBounds());
+            Rect bounds(s.transform.transform(layer->computeBounds()));
             visibleRegion.set(bounds);
             if (!visibleRegion.isEmpty()) {
                 // Remove the transparent area from the visible region
@@ -1485,7 +1443,7 @@
     const LayerVector& currentLayers(mDrawingState.layersSortedByZ);
     const size_t count = currentLayers.size();
     for (size_t i=0 ; i<count ; i++) {
-        const sp<LayerBase>& layer(currentLayers[i]);
+        const sp<Layer>& layer(currentLayers[i]);
         const Region dirty(layer->latchBuffer(visibleRegions));
         const Layer::State& s(layer->drawingState());
         invalidateLayerStack(s.layerStack, dirty);
@@ -1607,13 +1565,13 @@
      * and then, render the layers targeted at the framebuffer
      */
 
-    const Vector< sp<LayerBase> >& layers(hw->getVisibleLayersSortedByZ());
+    const Vector< sp<Layer> >& layers(hw->getVisibleLayersSortedByZ());
     const size_t count = layers.size();
     const Transform& tr = hw->getTransform();
     if (cur != end) {
         // we're using h/w composer
         for (size_t i=0 ; i<count && cur!=end ; ++i, ++cur) {
-            const sp<LayerBase>& layer(layers[i]);
+            const sp<Layer>& layer(layers[i]);
             const Region clip(dirty.intersect(tr.transform(layer->visibleRegion)));
             if (!clip.isEmpty()) {
                 switch (cur->getCompositionType()) {
@@ -1645,7 +1603,7 @@
     } else {
         // we're not using h/w composer
         for (size_t i=0 ; i<count ; ++i) {
-            const sp<LayerBase>& layer(layers[i]);
+            const sp<Layer>& layer(layers[i]);
             const Region clip(dirty.intersect(
                     tr.transform(layer->visibleRegion)));
             if (!clip.isEmpty()) {
@@ -1684,7 +1642,8 @@
 
 void SurfaceFlinger::addClientLayer(const sp<Client>& client,
         const sp<IBinder>& handle,
-        const sp<LayerBaseClient>& lbc)
+        const sp<IGraphicBufferProducer>& gbc,
+        const sp<Layer>& lbc)
 {
     // attach this layer to the client
     client->attachLayer(handle, lbc);
@@ -1692,45 +1651,22 @@
     // add this layer to the current state list
     Mutex::Autolock _l(mStateLock);
     mCurrentState.layersSortedByZ.add(lbc);
+    mGraphicBufferProducerList.add(gbc->asBinder());
 }
 
-status_t SurfaceFlinger::removeLayer(const sp<LayerBase>& layer)
+status_t SurfaceFlinger::removeLayer(const sp<Layer>& layer)
 {
     Mutex::Autolock _l(mStateLock);
-    status_t err = purgatorizeLayer_l(layer);
-    if (err == NO_ERROR)
-        setTransactionFlags(eTransactionNeeded);
-    return err;
-}
-
-status_t SurfaceFlinger::removeLayer_l(const sp<LayerBase>& layerBase)
-{
-    ssize_t index = mCurrentState.layersSortedByZ.remove(layerBase);
+    ssize_t index = mCurrentState.layersSortedByZ.remove(layer);
     if (index >= 0) {
+        mLayersPendingRemoval.push(layer);
         mLayersRemoved = true;
+        setTransactionFlags(eTransactionNeeded);
         return NO_ERROR;
     }
     return status_t(index);
 }
 
-status_t SurfaceFlinger::purgatorizeLayer_l(const sp<LayerBase>& layerBase)
-{
-    // First add the layer to the purgatory list, which makes sure it won't
-    // go away, then remove it from the main list (through a transaction).
-    ssize_t err = removeLayer_l(layerBase);
-    if (err >= 0) {
-        mLayerPurgatory.add(layerBase);
-    }
-
-    mLayersPendingRemoval.push(layerBase);
-
-    // it's possible that we don't find a layer, because it might
-    // have been destroyed already -- this is not technically an error
-    // from the user because there is a race between Client::destroySurface(),
-    // ~Client() and ~ISurface().
-    return (err == NAME_NOT_FOUND) ? status_t(NO_ERROR) : err;
-}
-
 uint32_t SurfaceFlinger::peekTransactionFlags(uint32_t flags)
 {
     return android_atomic_release_load(&mTransactionFlags);
@@ -1873,7 +1809,7 @@
         const layer_state_t& s)
 {
     uint32_t flags = 0;
-    sp<LayerBaseClient> layer(client->getLayerUser(s.surface));
+    sp<Layer> layer(client->getLayerUser(s.surface));
     if (layer != 0) {
         const uint32_t what = s.what;
         if (what & layer_state_t::ePositionChanged) {
@@ -1931,52 +1867,49 @@
     return flags;
 }
 
-sp<ISurface> SurfaceFlinger::createLayer(
+status_t SurfaceFlinger::createLayer(
         const String8& name,
         const sp<Client>& client,
-        uint32_t w, uint32_t h, PixelFormat format,
-        uint32_t flags)
+        uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
+        sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp)
 {
-    sp<LayerBaseClient> layer;
-    sp<ISurface> surfaceHandle;
-
+    //ALOGD("createLayer for (%d x %d), name=%s", w, h, name.string());
     if (int32_t(w|h) < 0) {
         ALOGE("createLayer() failed, w or h is negative (w=%d, h=%d)",
                 int(w), int(h));
-        return surfaceHandle;
+        return BAD_VALUE;
     }
 
-    //ALOGD("createLayer for (%d x %d), name=%s", w, h, name.string());
+    status_t result = NO_ERROR;
+
+    sp<Layer> layer;
+
     switch (flags & ISurfaceComposerClient::eFXSurfaceMask) {
         case ISurfaceComposerClient::eFXSurfaceNormal:
-            layer = createNormalLayer(client, w, h, flags, format);
+            result = createNormalLayer(client,
+                    name, w, h, flags, format,
+                    handle, gbp, &layer);
             break;
-        case ISurfaceComposerClient::eFXSurfaceBlur:
         case ISurfaceComposerClient::eFXSurfaceDim:
-            layer = createDimLayer(client, w, h, flags);
+            result = createDimLayer(client,
+                    name, w, h, flags,
+                    handle, gbp, &layer);
             break;
-        case ISurfaceComposerClient::eFXSurfaceScreenshot:
-            layer = createScreenshotLayer(client, w, h, flags);
+        default:
+            result = BAD_VALUE;
             break;
     }
 
-    if (layer != 0) {
-        layer->initStates(w, h, flags);
-        layer->setName(name);
-        surfaceHandle = layer->getSurface();
-        if (surfaceHandle != 0) {
-            addClientLayer(client, surfaceHandle->asBinder(), layer);
-        }
+    if (result == NO_ERROR) {
+        addClientLayer(client, *handle, *gbp, layer);
         setTransactionFlags(eTransactionNeeded);
     }
-
-    return surfaceHandle;
+    return result;
 }
 
-sp<Layer> SurfaceFlinger::createNormalLayer(
-        const sp<Client>& client,
-        uint32_t w, uint32_t h, uint32_t flags,
-        PixelFormat& format)
+status_t SurfaceFlinger::createNormalLayer(const sp<Client>& client,
+        const String8& name, uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format,
+        sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, sp<Layer>* outLayer)
 {
     // initialize the surfaces
     switch (format) {
@@ -1998,71 +1931,48 @@
         format = PIXEL_FORMAT_RGBA_8888;
 #endif
 
-    sp<Layer> layer = new Layer(this, client);
-    status_t err = layer->setBuffers(w, h, format, flags);
-    if (CC_LIKELY(err != NO_ERROR)) {
-        ALOGE("createNormalLayer() failed (%s)", strerror(-err));
-        layer.clear();
+    *outLayer = new Layer(this, client, name, w, h, flags);
+    status_t err = (*outLayer)->setBuffers(w, h, format, flags);
+    if (err == NO_ERROR) {
+        *handle = (*outLayer)->getHandle();
+        *gbp = (*outLayer)->getBufferQueue();
     }
-    return layer;
+
+    ALOGE_IF(err, "createNormalLayer() failed (%s)", strerror(-err));
+    return err;
 }
 
-sp<LayerDim> SurfaceFlinger::createDimLayer(
-        const sp<Client>& client,
-        uint32_t w, uint32_t h, uint32_t flags)
+status_t SurfaceFlinger::createDimLayer(const sp<Client>& client,
+        const String8& name, uint32_t w, uint32_t h, uint32_t flags,
+        sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, sp<Layer>* outLayer)
 {
-    sp<LayerDim> layer = new LayerDim(this, client);
-    return layer;
-}
-
-sp<LayerScreenshot> SurfaceFlinger::createScreenshotLayer(
-        const sp<Client>& client,
-        uint32_t w, uint32_t h, uint32_t flags)
-{
-    sp<LayerScreenshot> layer = new LayerScreenshot(this, client);
-    return layer;
+    *outLayer = new LayerDim(this, client, name, w, h, flags);
+    *handle = (*outLayer)->getHandle();
+    *gbp = (*outLayer)->getBufferQueue();
+    return NO_ERROR;
 }
 
 status_t SurfaceFlinger::onLayerRemoved(const sp<Client>& client, const sp<IBinder>& handle)
 {
-    /*
-     * called by the window manager, when a surface should be marked for
-     * destruction.
-     *
-     * The surface is removed from the current and drawing lists, but placed
-     * in the purgatory queue, so it's not destroyed right-away (we need
-     * to wait for all client's references to go away first).
-     */
-
-    status_t err = NAME_NOT_FOUND;
-    Mutex::Autolock _l(mStateLock);
-    sp<LayerBaseClient> layer = client->getLayerUser(handle);
-
-    if (layer != 0) {
-        err = purgatorizeLayer_l(layer);
-        if (err == NO_ERROR) {
-            setTransactionFlags(eTransactionNeeded);
-        }
+    // called by the window manager when it wants to remove a Layer
+    status_t err = NO_ERROR;
+    sp<Layer> l(client->getLayerUser(handle));
+    if (l != NULL) {
+        err = removeLayer(l);
+        ALOGE_IF(err<0 && err != NAME_NOT_FOUND,
+                "error removing layer=%p (%s)", l.get(), strerror(-err));
     }
     return err;
 }
 
-status_t SurfaceFlinger::onLayerDestroyed(const wp<LayerBaseClient>& layer)
+status_t SurfaceFlinger::onLayerDestroyed(const wp<Layer>& layer)
 {
-    // called by ~ISurface() when all references are gone
+    // called by ~LayerCleaner() when all references to the IBinder (handle)
+    // are gone
     status_t err = NO_ERROR;
-    sp<LayerBaseClient> l(layer.promote());
+    sp<Layer> l(layer.promote());
     if (l != NULL) {
-        Mutex::Autolock _l(mStateLock);
-        err = removeLayer_l(l);
-        if (err == NAME_NOT_FOUND) {
-            // The surface wasn't in the current list, which means it was
-            // removed already, which means it is in the purgatory,
-            // and need to be removed from there.
-            ssize_t idx = mLayerPurgatory.remove(l);
-            ALOGE_IF(idx < 0,
-                    "layer=%p is not in the purgatory list", l.get());
-        }
+        err = removeLayer(l);
         ALOGE_IF(err<0 && err != NAME_NOT_FOUND,
                 "error removing layer=%p (%s)", l.get(), strerror(-err));
     }
@@ -2072,12 +1982,14 @@
 // ---------------------------------------------------------------------------
 
 void SurfaceFlinger::onInitializeDisplays() {
-    // reset screen orientation
+    // reset screen orientation and use primary layer stack
     Vector<ComposerState> state;
     Vector<DisplayState> displays;
     DisplayState d;
-    d.what = DisplayState::eDisplayProjectionChanged;
+    d.what = DisplayState::eDisplayProjectionChanged |
+             DisplayState::eLayerStackChanged;
     d.token = mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY];
+    d.layerStack = 0;
     d.orientation = DisplayState::eOrientationDefault;
     d.frame.makeInvalid();
     d.viewport.makeInvalid();
@@ -2266,7 +2178,7 @@
     const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
     const size_t count = currentLayers.size();
     for (size_t i=0 ; i<count ; i++) {
-        const sp<LayerBase>& layer(currentLayers[i]);
+        const sp<Layer>& layer(currentLayers[i]);
         snprintf(buffer, SIZE, "%s\n", layer->getName().string());
         result.append(buffer);
     }
@@ -2291,7 +2203,7 @@
         const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
         const size_t count = currentLayers.size();
         for (size_t i=0 ; i<count ; i++) {
-            const sp<LayerBase>& layer(currentLayers[i]);
+            const sp<Layer>& layer(currentLayers[i]);
             if (name == layer->getName()) {
                 layer->dumpStats(result, buffer, SIZE);
             }
@@ -2311,7 +2223,7 @@
     const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
     const size_t count = currentLayers.size();
     for (size_t i=0 ; i<count ; i++) {
-        const sp<LayerBase>& layer(currentLayers[i]);
+        const sp<Layer>& layer(currentLayers[i]);
         if (name.isEmpty() || (name == layer->getName())) {
             layer->clearStats();
         }
@@ -2367,23 +2279,11 @@
     snprintf(buffer, SIZE, "Visible layers (count = %d)\n", count);
     result.append(buffer);
     for (size_t i=0 ; i<count ; i++) {
-        const sp<LayerBase>& layer(currentLayers[i]);
+        const sp<Layer>& layer(currentLayers[i]);
         layer->dump(result, buffer, SIZE);
     }
 
     /*
-     * Dump the layers in the purgatory
-     */
-
-    const size_t purgatorySize = mLayerPurgatory.size();
-    snprintf(buffer, SIZE, "Purgatory state (%d entries)\n", purgatorySize);
-    result.append(buffer);
-    for (size_t i=0 ; i<purgatorySize ; i++) {
-        const sp<LayerBase>& layer(mLayerPurgatory.itemAt(i));
-        layer->shortDump(result, buffer, SIZE);
-    }
-
-    /*
      * Dump Display state
      */
 
@@ -2468,7 +2368,7 @@
     alloc.dump(result);
 }
 
-const Vector< sp<LayerBase> >&
+const Vector< sp<Layer> >&
 SurfaceFlinger::getLayerSortedByZForHwcDisplay(int disp) {
     // Note: mStateLock is held here
     return getDisplayDevice( getBuiltInDisplay(disp) )->getVisibleLayersSortedByZ();
@@ -2497,6 +2397,7 @@
 {
     switch (code) {
         case CREATE_CONNECTION:
+        case CREATE_DISPLAY:
         case SET_TRANSACTION_STATE:
         case BOOT_FINISHED:
         case BLANK:
@@ -2603,101 +2504,82 @@
 }
 
 // ---------------------------------------------------------------------------
-
-status_t SurfaceFlinger::renderScreenToTexture(uint32_t layerStack,
-        GLuint* textureName, GLfloat* uOut, GLfloat* vOut)
-{
-    Mutex::Autolock _l(mStateLock);
-    return renderScreenToTextureLocked(layerStack, textureName, uOut, vOut);
-}
-
-status_t SurfaceFlinger::renderScreenToTextureLocked(uint32_t layerStack,
-        GLuint* textureName, GLfloat* uOut, GLfloat* vOut)
-{
-    ATRACE_CALL();
-
-    if (!GLExtensions::getInstance().haveFramebufferObject())
-        return INVALID_OPERATION;
-
-    // get screen geometry
-    // FIXME: figure out what it means to have a screenshot texture w/ multi-display
-    sp<const DisplayDevice> hw(getDefaultDisplayDevice());
-    const uint32_t hw_w = hw->getWidth();
-    const uint32_t hw_h = hw->getHeight();
-    GLfloat u = 1;
-    GLfloat v = 1;
-
-    // make sure to clear all GL error flags
-    while ( glGetError() != GL_NO_ERROR ) ;
-
-    // create a FBO
-    GLuint name, tname;
-    glGenTextures(1, &tname);
-    glBindTexture(GL_TEXTURE_2D, tname);
-    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
-            hw_w, hw_h, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
-    if (glGetError() != GL_NO_ERROR) {
-        while ( glGetError() != GL_NO_ERROR ) ;
-        GLint tw = (2 << (31 - clz(hw_w)));
-        GLint th = (2 << (31 - clz(hw_h)));
-        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
-                tw, th, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
-        u = GLfloat(hw_w) / tw;
-        v = GLfloat(hw_h) / th;
-    }
-    glGenFramebuffersOES(1, &name);
-    glBindFramebufferOES(GL_FRAMEBUFFER_OES, name);
-    glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES,
-            GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, tname, 0);
-
-    DisplayDevice::setViewportAndProjection(hw);
-
-    // redraw the screen entirely...
-    glDisable(GL_TEXTURE_EXTERNAL_OES);
-    glDisable(GL_TEXTURE_2D);
-    glClearColor(0,0,0,1);
-    glClear(GL_COLOR_BUFFER_BIT);
-    glMatrixMode(GL_MODELVIEW);
-    glLoadIdentity();
-    const Vector< sp<LayerBase> >& layers(hw->getVisibleLayersSortedByZ());
-    const size_t count = layers.size();
-    for (size_t i=0 ; i<count ; ++i) {
-        const sp<LayerBase>& layer(layers[i]);
-        layer->draw(hw);
-    }
-
-    hw->compositionComplete();
-
-    // back to main framebuffer
-    glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
-    glDeleteFramebuffersOES(1, &name);
-
-    *textureName = tname;
-    *uOut = u;
-    *vOut = v;
-    return NO_ERROR;
-}
-
+// Capture screen into an IGraphiBufferProducer
 // ---------------------------------------------------------------------------
 
-status_t SurfaceFlinger::captureScreenImplLocked(const sp<IBinder>& display,
-        sp<IMemoryHeap>* heap,
-        uint32_t* w, uint32_t* h, PixelFormat* f,
-        uint32_t sw, uint32_t sh,
+status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display,
+        const sp<IGraphicBufferProducer>& producer,
+        uint32_t reqWidth, uint32_t reqHeight,
+        uint32_t minLayerZ, uint32_t maxLayerZ,
+        bool isCpuConsumer) {
+
+    if (CC_UNLIKELY(display == 0))
+        return BAD_VALUE;
+
+    if (CC_UNLIKELY(producer == 0))
+        return BAD_VALUE;
+
+    class MessageCaptureScreen : public MessageBase {
+        SurfaceFlinger* flinger;
+        sp<IBinder> display;
+        sp<IGraphicBufferProducer> producer;
+        uint32_t reqWidth, reqHeight;
+        uint32_t minLayerZ,maxLayerZ;
+        bool isCpuConsumer;
+        status_t result;
+    public:
+        MessageCaptureScreen(SurfaceFlinger* flinger,
+                const sp<IBinder>& display,
+                const sp<IGraphicBufferProducer>& producer,
+                uint32_t reqWidth, uint32_t reqHeight,
+                uint32_t minLayerZ, uint32_t maxLayerZ, bool isCpuConsumer)
+            : flinger(flinger), display(display), producer(producer),
+              reqWidth(reqWidth), reqHeight(reqHeight),
+              minLayerZ(minLayerZ), maxLayerZ(maxLayerZ),
+              isCpuConsumer(isCpuConsumer),
+              result(PERMISSION_DENIED)
+        {
+        }
+        status_t getResult() const {
+            return result;
+        }
+        virtual bool handler() {
+            Mutex::Autolock _l(flinger->mStateLock);
+            sp<const DisplayDevice> hw(flinger->getDisplayDevice(display));
+            // TODO: if we know the GL->CPU path works, we can call
+            // captureScreenImplLocked() directly, instead of using the
+            // "CpuConsumer" version, which is much less efficient -- it is
+            // however needed by some older drivers.
+            if (isCpuConsumer) {
+                result = flinger->captureScreenImplCpuConsumerLocked(hw,
+                        producer, reqWidth, reqHeight, minLayerZ, maxLayerZ);
+            } else {
+                result = flinger->captureScreenImplLocked(hw,
+                        producer, reqWidth, reqHeight, minLayerZ, maxLayerZ);
+            }
+            return true;
+        }
+    };
+
+    sp<MessageBase> msg = new MessageCaptureScreen(this,
+            display, producer, reqWidth, reqHeight, minLayerZ, maxLayerZ,
+            isCpuConsumer);
+    status_t res = postMessageSync(msg);
+    if (res == NO_ERROR) {
+        res = static_cast<MessageCaptureScreen*>( msg.get() )->getResult();
+    }
+    return res;
+}
+
+status_t SurfaceFlinger::captureScreenImplLocked(
+        const sp<const DisplayDevice>& hw,
+        const sp<IGraphicBufferProducer>& producer,
+        uint32_t reqWidth, uint32_t reqHeight,
         uint32_t minLayerZ, uint32_t maxLayerZ)
 {
     ATRACE_CALL();
 
-    status_t result = PERMISSION_DENIED;
-
-    if (!GLExtensions::getInstance().haveFramebufferObject()) {
-        return INVALID_OPERATION;
-    }
-
     // get screen geometry
-    sp<const DisplayDevice> hw(getDisplayDevice(display));
     const uint32_t hw_w = hw->getWidth();
     const uint32_t hw_h = hw->getHeight();
 
@@ -2707,162 +2589,199 @@
         return PERMISSION_DENIED;
     }
 
-    if ((sw > hw_w) || (sh > hw_h)) {
-        ALOGE("size mismatch (%d, %d) > (%d, %d)", sw, sh, hw_w, hw_h);
+    if ((reqWidth > hw_w) || (reqHeight > hw_h)) {
+        ALOGE("size mismatch (%d, %d) > (%d, %d)",
+                reqWidth, reqHeight, hw_w, hw_h);
         return BAD_VALUE;
     }
 
-    sw = (!sw) ? hw_w : sw;
-    sh = (!sh) ? hw_h : sh;
-    const size_t size = sw * sh * 4;
-    const bool filtering = sw != hw_w || sh != hw_h;
+    reqWidth = (!reqWidth) ? hw_w : reqWidth;
+    reqHeight = (!reqHeight) ? hw_h : reqHeight;
+    const bool filtering = reqWidth != hw_w || reqWidth != hw_h;
 
-//    ALOGD("screenshot: sw=%d, sh=%d, minZ=%d, maxZ=%d",
-//            sw, sh, minLayerZ, maxLayerZ);
+    // 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;
+    }
 
     // make sure to clear all GL error flags
     while ( glGetError() != GL_NO_ERROR ) ;
 
-    // create a FBO
-    GLuint name, tname;
-    glGenRenderbuffersOES(1, &tname);
-    glBindRenderbufferOES(GL_RENDERBUFFER_OES, tname);
-    glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_RGBA8_OES, sw, sh);
+    // set-up our viewport
+    glViewport(0, 0, reqWidth, reqHeight);
+    glMatrixMode(GL_PROJECTION);
+    glLoadIdentity();
+    glOrthof(0, hw_w, 0, hw_h, 0, 1);
+    glMatrixMode(GL_MODELVIEW);
+    glLoadIdentity();
 
-    glGenFramebuffersOES(1, &name);
-    glBindFramebufferOES(GL_FRAMEBUFFER_OES, name);
-    glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES,
-            GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, tname);
+    // redraw the screen entirely...
+    glDisable(GL_TEXTURE_EXTERNAL_OES);
+    glDisable(GL_TEXTURE_2D);
+    glClearColor(0,0,0,1);
+    glClear(GL_COLOR_BUFFER_BIT);
 
-    GLenum status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES);
-
-    if (status == GL_FRAMEBUFFER_COMPLETE_OES) {
-
-        // invert everything, b/c glReadPixel() below will invert the FB
-        GLint  viewport[4];
-        glGetIntegerv(GL_VIEWPORT, viewport);
-        glViewport(0, 0, sw, sh);
-        glMatrixMode(GL_PROJECTION);
-        glPushMatrix();
-        glLoadIdentity();
-        glOrthof(0, hw_w, hw_h, 0, 0, 1);
-        glMatrixMode(GL_MODELVIEW);
-
-        // redraw the screen entirely...
-        glClearColor(0,0,0,1);
-        glClear(GL_COLOR_BUFFER_BIT);
-
-        const Vector< sp<LayerBase> >& layers(hw->getVisibleLayersSortedByZ());
-        const size_t count = layers.size();
-        for (size_t i=0 ; i<count ; ++i) {
-            const sp<LayerBase>& layer(layers[i]);
-            const uint32_t z = layer->drawingState().z;
-            if (z >= minLayerZ && z <= maxLayerZ) {
-                if (filtering) layer->setFiltering(true);
-                layer->draw(hw);
-                if (filtering) layer->setFiltering(false);
-            }
-        }
-
-        // check for errors and return screen capture
-        if (glGetError() != GL_NO_ERROR) {
-            // error while rendering
-            result = INVALID_OPERATION;
-        } else {
-            // allocate shared memory large enough to hold the
-            // screen capture
-            sp<MemoryHeapBase> base(
-                    new MemoryHeapBase(size, 0, "screen-capture") );
-            void* const ptr = base->getBase();
-            if (ptr != MAP_FAILED) {
-                // capture the screen with glReadPixels()
-                ScopedTrace _t(ATRACE_TAG, "glReadPixels");
-                glReadPixels(0, 0, sw, sh, GL_RGBA, GL_UNSIGNED_BYTE, ptr);
-                if (glGetError() == GL_NO_ERROR) {
-                    *heap = base;
-                    *w = sw;
-                    *h = sh;
-                    *f = PIXEL_FORMAT_RGBA_8888;
-                    result = NO_ERROR;
+    const LayerVector& layers( mDrawingState.layersSortedByZ );
+    const size_t count = layers.size();
+    for (size_t i=0 ; i<count ; ++i) {
+        const sp<Layer>& layer(layers[i]);
+        const Layer::State& state(layer->drawingState());
+        if (state.layerStack == hw->getLayerStack()) {
+            if (state.z >= minLayerZ && state.z <= maxLayerZ) {
+                if (layer->isVisible()) {
+                    if (filtering) layer->setFiltering(true);
+                    layer->draw(hw);
+                    if (filtering) layer->setFiltering(false);
                 }
-            } else {
-                result = NO_MEMORY;
             }
         }
-        glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
-        glMatrixMode(GL_PROJECTION);
-        glPopMatrix();
-        glMatrixMode(GL_MODELVIEW);
-    } else {
-        result = BAD_VALUE;
     }
 
-    // release FBO resources
-    glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
-    glDeleteRenderbuffersOES(1, &tname);
-    glDeleteFramebuffersOES(1, &name);
-
+    // compositionComplete is needed for older driver
     hw->compositionComplete();
 
-//    ALOGD("screenshot: result = %s", result<0 ? strerror(result) : "OK");
+    // and finishing things up...
+    if (eglSwapBuffers(mEGLDisplay, eglSurface) != EGL_TRUE) {
+        ALOGE("captureScreenImplLocked: eglSwapBuffers() failed 0x%4x",
+                eglGetError());
+        eglDestroySurface(mEGLDisplay, eglSurface);
+        return BAD_VALUE;
+    }
 
-    return result;
+    eglDestroySurface(mEGLDisplay, eglSurface);
+
+    return NO_ERROR;
 }
 
 
-status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display,
-        sp<IMemoryHeap>* heap,
-        uint32_t* width, uint32_t* height, PixelFormat* format,
-        uint32_t sw, uint32_t sh,
+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)
 {
-    if (CC_UNLIKELY(display == 0))
-        return BAD_VALUE;
+    ATRACE_CALL();
 
-    if (!GLExtensions::getInstance().haveFramebufferObject())
+    if (!GLExtensions::getInstance().haveFramebufferObject()) {
         return INVALID_OPERATION;
-
-    class MessageCaptureScreen : public MessageBase {
-        SurfaceFlinger* flinger;
-        sp<IBinder> display;
-        sp<IMemoryHeap>* heap;
-        uint32_t* w;
-        uint32_t* h;
-        PixelFormat* f;
-        uint32_t sw;
-        uint32_t sh;
-        uint32_t minLayerZ;
-        uint32_t maxLayerZ;
-        status_t result;
-    public:
-        MessageCaptureScreen(SurfaceFlinger* flinger, const sp<IBinder>& display,
-                sp<IMemoryHeap>* heap, uint32_t* w, uint32_t* h, PixelFormat* f,
-                uint32_t sw, uint32_t sh,
-                uint32_t minLayerZ, uint32_t maxLayerZ)
-            : flinger(flinger), display(display),
-              heap(heap), w(w), h(h), f(f), sw(sw), sh(sh),
-              minLayerZ(minLayerZ), maxLayerZ(maxLayerZ),
-              result(PERMISSION_DENIED)
-        {
-        }
-        status_t getResult() const {
-            return result;
-        }
-        virtual bool handler() {
-            Mutex::Autolock _l(flinger->mStateLock);
-            result = flinger->captureScreenImplLocked(display,
-                    heap, w, h, f, sw, sh, minLayerZ, maxLayerZ);
-            return true;
-        }
-    };
-
-    sp<MessageBase> msg = new MessageCaptureScreen(this,
-            display, heap, width, height, format, sw, sh, minLayerZ, maxLayerZ);
-    status_t res = postMessageSync(msg);
-    if (res == NO_ERROR) {
-        res = static_cast<MessageCaptureScreen*>( msg.get() )->getResult();
     }
-    return res;
+
+    // create the texture that will receive the screenshot, later we'll
+    // attach a FBO to it so we can call glReadPixels().
+    GLuint tname;
+    glGenTextures(1, &tname);
+    glBindTexture(GL_TEXTURE_2D, tname);
+    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+    // the GLConsumer will provide the BufferQueue
+    sp<GLConsumer> consumer = new GLConsumer(tname, true, GL_TEXTURE_2D);
+    consumer->getBufferQueue()->setDefaultBufferFormat(HAL_PIXEL_FORMAT_RGBA_8888);
+
+    // call the new screenshot taking code, passing a BufferQueue to it
+    status_t result = captureScreenImplLocked(hw,
+            consumer->getBufferQueue(), reqWidth, reqHeight, minLayerZ, maxLayerZ);
+
+    if (result == NO_ERROR) {
+        result = consumer->updateTexImage();
+        if (result == NO_ERROR) {
+            // create a FBO
+            GLuint name;
+            glGenFramebuffersOES(1, &name);
+            glBindFramebufferOES(GL_FRAMEBUFFER_OES, name);
+            glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES,
+                    GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, tname, 0);
+
+            reqWidth = consumer->getCurrentBuffer()->getWidth();
+            reqHeight = consumer->getCurrentBuffer()->getHeight();
+
+            {
+                // in this block we render the screenshot into the
+                // CpuConsumer using glReadPixels from our GLConsumer,
+                // Some older drivers don't support the GL->CPU path so
+                // 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();
+                ANativeWindowBuffer* buffer;
+                void* vaddr;
+
+                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) {
+                        if (native_window_dequeue_buffer_and_wait(window,
+                                &buffer) == NO_ERROR) {
+                            sp<GraphicBuffer> buf =
+                                    static_cast<GraphicBuffer*>(buffer);
+                            if (buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN,
+                                    &vaddr) == NO_ERROR) {
+                                if (buffer->stride != int(reqWidth)) {
+                                    // we're unlucky here, glReadPixels is
+                                    // not able to deal with a stride not
+                                    // equal to the width.
+                                    uint32_t* tmp = new uint32_t[reqWidth*reqHeight];
+                                    if (tmp != NULL) {
+                                        glReadPixels(0, 0, reqWidth, reqHeight,
+                                                GL_RGBA, GL_UNSIGNED_BYTE, tmp);
+                                        for (size_t y=0 ; y<reqHeight ; y++) {
+                                            memcpy((uint32_t*)vaddr + y*buffer->stride,
+                                                    tmp + y*reqWidth, reqWidth*4);
+                                        }
+                                        delete [] tmp;
+                                    }
+                                } else {
+                                    glReadPixels(0, 0, reqWidth, reqHeight,
+                                            GL_RGBA, GL_UNSIGNED_BYTE, vaddr);
+                                }
+                                buf->unlock();
+                            }
+                            window->queueBuffer(window, buffer, -1);
+                        }
+                    }
+                    native_window_api_disconnect(window, NATIVE_WINDOW_API_CPU);
+                }
+            }
+
+            // back to main framebuffer
+            glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
+            glDeleteFramebuffersOES(1, &name);
+        }
+    }
+
+    glDeleteTextures(1, &tname);
+
+    DisplayDevice::makeCurrent(mEGLDisplay,
+            getDefaultDisplayDevice(), mEGLContext);
+
+    return result;
 }
 
 // ---------------------------------------------------------------------------
@@ -2871,15 +2790,15 @@
 }
 
 SurfaceFlinger::LayerVector::LayerVector(const LayerVector& rhs)
-    : SortedVector<sp<LayerBase> >(rhs) {
+    : SortedVector<sp<Layer> >(rhs) {
 }
 
 int SurfaceFlinger::LayerVector::do_compare(const void* lhs,
     const void* rhs) const
 {
     // sort layers per layer-stack, then by z-order and finally by sequence
-    const sp<LayerBase>& l(*reinterpret_cast<const sp<LayerBase>*>(lhs));
-    const sp<LayerBase>& r(*reinterpret_cast<const sp<LayerBase>*>(rhs));
+    const sp<Layer>& l(*reinterpret_cast<const sp<Layer>*>(lhs));
+    const sp<Layer>& r(*reinterpret_cast<const sp<Layer>*>(rhs));
 
     uint32_t ls = l->currentState().layerStack;
     uint32_t rs = r->currentState().layerStack;
@@ -2901,7 +2820,7 @@
 }
 
 SurfaceFlinger::DisplayDeviceState::DisplayDeviceState(DisplayDevice::DisplayType type)
-    : type(type), layerStack(0), orientation(0) {
+    : type(type), layerStack(DisplayDevice::NO_LAYER_STACK), orientation(0) {
     viewport.makeInvalid();
     frame.makeInvalid();
 }
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index e67f3f1..2aacfe7 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -60,10 +60,7 @@
 class EventThread;
 class IGraphicBufferAlloc;
 class Layer;
-class LayerBase;
-class LayerBaseClient;
 class LayerDim;
-class LayerScreenshot;
 class Surface;
 
 // ---------------------------------------------------------------------------
@@ -103,14 +100,6 @@
     // force full composition on all displays
     void repaintEverything();
 
-    // renders content on given display to a texture. thread-safe version.
-    status_t renderScreenToTexture(uint32_t layerStack, GLuint* textureName,
-        GLfloat* uOut, GLfloat* vOut);
-
-    // renders content on given display to a texture, w/o acquiring main lock
-    status_t renderScreenToTextureLocked(uint32_t layerStack, GLuint* textureName,
-        GLfloat* uOut, GLfloat* vOut);
-
     // returns the default Display
     sp<const DisplayDevice> getDefaultDisplayDevice() const {
         return getDisplayDevice(mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY]);
@@ -133,15 +122,13 @@
 
     // for debugging only
     // TODO: this should be made accessible only to HWComposer
-    const Vector< sp<LayerBase> >& getLayerSortedByZForHwcDisplay(int disp);
+    const Vector< sp<Layer> >& getLayerSortedByZForHwcDisplay(int disp);
 
 private:
     friend class Client;
     friend class DisplayEventConnection;
-    friend class LayerBase;
-    friend class LayerBaseClient;
     friend class Layer;
-    friend class LayerScreenshot;
+    friend class SurfaceTextureLayer;
 
     // We're reference counted, never destroy SurfaceFlinger directly
     virtual ~SurfaceFlinger();
@@ -150,7 +137,7 @@
      * Internal data structures
      */
 
-    class LayerVector : public SortedVector<sp<LayerBase> > {
+    class LayerVector : public SortedVector< sp<Layer> > {
     public:
         LayerVector();
         LayerVector(const LayerVector& rhs);
@@ -198,10 +185,10 @@
     virtual bool authenticateSurfaceTexture(
         const sp<IGraphicBufferProducer>& bufferProducer) const;
     virtual sp<IDisplayEventConnection> createDisplayEventConnection();
-    virtual status_t captureScreen(const sp<IBinder>& display, sp<IMemoryHeap>* heap,
-        uint32_t* width, uint32_t* height, PixelFormat* format,
-        uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ,
-        uint32_t maxLayerZ);
+    virtual status_t captureScreen(const sp<IBinder>& display,
+            const sp<IGraphicBufferProducer>& producer,
+            uint32_t reqWidth, uint32_t reqHeight,
+            uint32_t minLayerZ, uint32_t maxLayerZ, bool isCpuConsumer);
     // called when screen needs to turn off
     virtual void blank(const sp<IBinder>& display);
     // called when screen is turning back on
@@ -267,38 +254,36 @@
     /* ------------------------------------------------------------------------
      * Layer management
      */
-    sp<ISurface> createLayer(const String8& name, const sp<Client>& client,
-            uint32_t w, uint32_t h, PixelFormat format, uint32_t flags);
+    status_t createLayer(const String8& name, const sp<Client>& client,
+            uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
+            sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp);
 
-    sp<Layer> createNormalLayer(const sp<Client>& client,
-            uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format);
+    status_t createNormalLayer(const sp<Client>& client, const String8& name,
+            uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format,
+            sp<IBinder>* outHandle, sp<IGraphicBufferProducer>* outGbp,
+            sp<Layer>* outLayer);
 
-    sp<LayerDim> createDimLayer(const sp<Client>& client,
-            uint32_t w, uint32_t h, uint32_t flags);
-
-    sp<LayerScreenshot> createScreenshotLayer(const sp<Client>& client,
-            uint32_t w, uint32_t h, uint32_t flags);
+    status_t createDimLayer(const sp<Client>& client, const String8& name,
+            uint32_t w, uint32_t h, uint32_t flags, sp<IBinder>* outHandle,
+            sp<IGraphicBufferProducer>* outGbp, sp<Layer>* outLayer);
 
     // called in response to the window-manager calling
     // ISurfaceComposerClient::destroySurface()
-    // The specified layer is first placed in a purgatory list
-    // until all references from the client are released.
     status_t onLayerRemoved(const sp<Client>& client, const sp<IBinder>& handle);
 
     // called when all clients have released all their references to
     // this layer meaning it is entirely safe to destroy all
     // resources associated to this layer.
-    status_t onLayerDestroyed(const wp<LayerBaseClient>& layer);
+    status_t onLayerDestroyed(const wp<Layer>& layer);
 
     // remove a layer from SurfaceFlinger immediately
-    status_t removeLayer(const sp<LayerBase>& layer);
+    status_t removeLayer(const sp<Layer>& layer);
 
     // add a layer to SurfaceFlinger
-    void addClientLayer(const sp<Client>& client, const sp<IBinder>& handle,
-        const sp<LayerBaseClient>& lbc);
-
-    status_t removeLayer_l(const sp<LayerBase>& layer);
-    status_t purgatorizeLayer_l(const sp<LayerBase>& layer);
+    void addClientLayer(const sp<Client>& client,
+            const sp<IBinder>& handle,
+            const sp<IGraphicBufferProducer>& gbc,
+            const sp<Layer>& lbc);
 
     /* ------------------------------------------------------------------------
      * Boot animation, on/off animations and screen capture
@@ -306,10 +291,18 @@
 
     void startBootAnim();
 
-    status_t captureScreenImplLocked(const sp<IBinder>& display, sp<IMemoryHeap>* heap,
-        uint32_t* width, uint32_t* height, PixelFormat* format,
-        uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ,
-        uint32_t maxLayerZ);
+    status_t captureScreenImplLocked(
+            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);
+
 
     /* ------------------------------------------------------------------------
      * EGL
@@ -404,10 +397,10 @@
     State mCurrentState;
     volatile int32_t mTransactionFlags;
     Condition mTransactionCV;
-    SortedVector<sp<LayerBase> > mLayerPurgatory;
     bool mTransactionPending;
     bool mAnimTransactionPending;
-    Vector<sp<LayerBase> > mLayersPendingRemoval;
+    Vector< sp<Layer> > mLayersPendingRemoval;
+    SortedVector< wp<IBinder> > mGraphicBufferProducerList;
 
     // protected by mStateLock (but we could use another lock)
     bool mLayersRemoved;
@@ -456,7 +449,7 @@
 
     // protected by mDestroyedLayerLock;
     mutable Mutex mDestroyedLayerLock;
-    Vector<LayerBase const *> mDestroyedLayers;
+    Vector<Layer const *> mDestroyedLayers;
 
     /* ------------------------------------------------------------------------
      * Feature prototyping
diff --git a/services/surfaceflinger/SurfaceTextureLayer.cpp b/services/surfaceflinger/SurfaceTextureLayer.cpp
index 395c8c8..d0f0dae 100644
--- a/services/surfaceflinger/SurfaceTextureLayer.cpp
+++ b/services/surfaceflinger/SurfaceTextureLayer.cpp
@@ -20,17 +20,35 @@
 
 #include <utils/Errors.h>
 
+#include "SurfaceFlinger.h"
 #include "SurfaceTextureLayer.h"
 
 namespace android {
 // ---------------------------------------------------------------------------
 
 
-SurfaceTextureLayer::SurfaceTextureLayer()
-    : BufferQueue(true) {
+SurfaceTextureLayer::SurfaceTextureLayer(const sp<SurfaceFlinger>& flinger)
+    : BufferQueue(true), flinger(flinger) {
 }
 
 SurfaceTextureLayer::~SurfaceTextureLayer() {
+    // remove ourselves from SurfaceFlinger's list. We do this asynchronously
+    // because we don't know where this dtor is called from, it could be
+    // called with the mStateLock held, leading to a dead-lock (it actually
+    // happens).
+    class MessageCleanUpList : public MessageBase {
+        sp<SurfaceFlinger> flinger;
+        wp<IBinder> gbp;
+    public:
+        MessageCleanUpList(const sp<SurfaceFlinger>& flinger, const wp<IBinder>& gbp)
+            : flinger(flinger), gbp(gbp) { }
+        virtual bool handler() {
+            Mutex::Autolock _l(flinger->mStateLock);
+            flinger->mGraphicBufferProducerList.remove(gbp);
+            return true;
+        }
+    };
+    flinger->postMessageAsync( new MessageCleanUpList(flinger, this) );
 }
 
 status_t SurfaceTextureLayer::connect(int api, QueueBufferOutput* output) {
diff --git a/services/surfaceflinger/SurfaceTextureLayer.h b/services/surfaceflinger/SurfaceTextureLayer.h
index a75ccf4..13cff2f 100644
--- a/services/surfaceflinger/SurfaceTextureLayer.h
+++ b/services/surfaceflinger/SurfaceTextureLayer.h
@@ -28,15 +28,16 @@
 // ---------------------------------------------------------------------------
 
 class Layer;
+class SurfaceFlinger;
 
 /*
  * This is a thin wrapper around BufferQueue, used by the Layer class.
  */
-class SurfaceTextureLayer : public BufferQueue
-{
+class SurfaceTextureLayer : public BufferQueue {
+    sp<SurfaceFlinger> flinger;
 public:
-    SurfaceTextureLayer();
-    ~SurfaceTextureLayer();
+    SurfaceTextureLayer(const sp<SurfaceFlinger>& flinger);
+    virtual ~SurfaceTextureLayer();
 
     // After calling the superclass connect(), set or clear synchronous
     // mode appropriately for the specified API.
diff --git a/services/surfaceflinger/Transform.cpp b/services/surfaceflinger/Transform.cpp
index aca90e0..315720e 100644
--- a/services/surfaceflinger/Transform.cpp
+++ b/services/surfaceflinger/Transform.cpp
@@ -298,6 +298,44 @@
     return mType;
 }
 
+Transform Transform::inverse() const {
+    // our 3x3 matrix is always of the form of a 2x2 transformation
+    // followed by a translation: T*M, therefore:
+    // (T*M)^-1 = M^-1 * T^-1
+    Transform result;
+    if (mType <= TRANSLATE) {
+        // 1 0 x
+        // 0 1 y
+        // 0 0 1
+        result = *this;
+        result.mMatrix[2][0] = -result.mMatrix[2][0];
+        result.mMatrix[2][1] = -result.mMatrix[2][1];
+    } else {
+        // a c x
+        // b d y
+        // 0 0 1
+        const mat33& M(mMatrix);
+        const float a = M[0][0];
+        const float b = M[1][0];
+        const float c = M[0][1];
+        const float d = M[1][1];
+        const float x = M[2][0];
+        const float y = M[2][1];
+
+        Transform R, T;
+        const float idet = 1.0 / (a*d - b*c);
+        R.mMatrix[0][0] =  d*idet;    R.mMatrix[0][1] = -c*idet;
+        R.mMatrix[1][0] = -b*idet;    R.mMatrix[1][1] =  a*idet;
+        R.mType = mType &= ~TRANSLATE;
+
+        T.mMatrix[2][0] = -x;
+        T.mMatrix[2][1] = -y;
+        T.mType = TRANSLATE;
+        result =  R * T;
+    }
+    return result;
+}
+
 uint32_t Transform::getType() const {
     return type() & 0xFF;
 }
diff --git a/services/surfaceflinger/Transform.h b/services/surfaceflinger/Transform.h
index 4fe261a..c4efade 100644
--- a/services/surfaceflinger/Transform.h
+++ b/services/surfaceflinger/Transform.h
@@ -80,6 +80,8 @@
             Rect    transform(const Rect& bounds) const;
             Transform operator * (const Transform& rhs) const;
 
+            Transform inverse() const;
+
             // for debugging
             void dump(const char* name) const;
 
diff --git a/services/surfaceflinger/tests/surface/Android.mk b/services/surfaceflinger/tests/surface/Android.mk
deleted file mode 100644
index c59060e..0000000
--- a/services/surfaceflinger/tests/surface/Android.mk
+++ /dev/null
@@ -1,18 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-	surface.cpp
-
-LOCAL_SHARED_LIBRARIES := \
-	libcutils \
-	libutils \
-	libbinder \
-    libui \
-    libgui
-
-LOCAL_MODULE:= test-surface
-
-LOCAL_MODULE_TAGS := tests
-
-include $(BUILD_EXECUTABLE)
diff --git a/services/surfaceflinger/tests/surface/surface.cpp b/services/surfaceflinger/tests/surface/surface.cpp
deleted file mode 100644
index 9c41cc3..0000000
--- a/services/surfaceflinger/tests/surface/surface.cpp
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2010 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.
- */
-
-#include <cutils/memory.h>
-
-#include <utils/Log.h>
-
-#include <binder/IPCThreadState.h>
-#include <binder/ProcessState.h>
-#include <binder/IServiceManager.h>
-
-#include <gui/Surface.h>
-#include <gui/SurfaceComposerClient.h>
-
-using namespace android;
-
-int main(int argc, char** argv)
-{
-    // set up the thread-pool
-    sp<ProcessState> proc(ProcessState::self());
-    ProcessState::self()->startThreadPool();
-
-    // create a client to surfaceflinger
-    sp<SurfaceComposerClient> client = new SurfaceComposerClient();
-    
-    sp<SurfaceControl> surfaceControl = client->createSurface(
-            String8("surface"), 160, 240, PIXEL_FORMAT_RGB_565, 0);
-    SurfaceComposerClient::openGlobalTransaction();
-    surfaceControl->setLayer(100000);
-    SurfaceComposerClient::closeGlobalTransaction();
-
-    // pretend it went cross-process
-    Parcel parcel;
-    SurfaceControl::writeSurfaceToParcel(surfaceControl, &parcel);
-    parcel.setDataPosition(0);
-    sp<Surface> surface = Surface::readFromParcel(parcel);
-    ANativeWindow* window = surface.get();
-
-    printf("window=%p\n", window);
-
-    int err = native_window_set_buffer_count(window, 8);
-    ANativeWindowBuffer* buffer;
-
-    for (int i=0 ; i<8 ; i++) {
-        window->dequeueBuffer(window, &buffer);
-        printf("buffer %d: %p\n", i, buffer);
-    }
-
-    printf("test complete. CTRL+C to finish.\n");
-
-    IPCThreadState::self()->joinThreadPool();
-    return 0;
-}