auto import from //depot/cupcake/@135843
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
new file mode 100644
index 0000000..f14d7e9
--- /dev/null
+++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
@@ -0,0 +1,353 @@
+/*
+ * 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 "SurfaceFlinger"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+
+#include <cutils/properties.h>
+
+#include <utils/Log.h>
+
+#include <ui/EGLDisplaySurface.h>
+
+#include <GLES/gl.h>
+#include <EGL/eglext.h>
+
+
+#include "DisplayHardware/DisplayHardware.h"
+
+#include <hardware/copybit.h>
+#include <hardware/overlay.h>
+
+using namespace android;
+
+static __attribute__((noinline))
+const char *egl_strerror(EGLint err)
+{
+    switch (err){
+        case EGL_SUCCESS:           return "EGL_SUCCESS";
+        case EGL_NOT_INITIALIZED:   return "EGL_NOT_INITIALIZED";
+        case EGL_BAD_ACCESS:        return "EGL_BAD_ACCESS";
+        case EGL_BAD_ALLOC:         return "EGL_BAD_ALLOC";
+        case EGL_BAD_ATTRIBUTE:     return "EGL_BAD_ATTRIBUTE";
+        case EGL_BAD_CONFIG:        return "EGL_BAD_CONFIG";
+        case EGL_BAD_CONTEXT:       return "EGL_BAD_CONTEXT";
+        case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE";
+        case EGL_BAD_DISPLAY:       return "EGL_BAD_DISPLAY";
+        case EGL_BAD_MATCH:         return "EGL_BAD_MATCH";
+        case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP";
+        case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW";
+        case EGL_BAD_PARAMETER:     return "EGL_BAD_PARAMETER";
+        case EGL_BAD_SURFACE:       return "EGL_BAD_SURFACE";
+        case EGL_CONTEXT_LOST:      return "EGL_CONTEXT_LOST";
+        default: return "UNKNOWN";
+    }
+}
+
+static __attribute__((noinline))
+void checkGLErrors()
+{
+    GLenum error = glGetError();
+    if (error != GL_NO_ERROR)
+        LOGE("GL error 0x%04x", int(error));
+}
+
+static __attribute__((noinline))
+void checkEGLErrors(const char* token)
+{
+    EGLint error = eglGetError();
+    // GLESonGL seems to be returning 0 when there is no errors?
+    if (error && error != EGL_SUCCESS)
+        LOGE("%s error 0x%04x (%s)",
+                token, int(error), egl_strerror(error));
+}
+
+
+/*
+ * Initialize the display to the specified values.
+ *
+ */
+
+DisplayHardware::DisplayHardware(
+        const sp<SurfaceFlinger>& flinger,
+        uint32_t dpy)
+    : DisplayHardwareBase(flinger, dpy)
+{
+    init(dpy);
+}
+
+DisplayHardware::~DisplayHardware()
+{
+    fini();
+}
+
+float DisplayHardware::getDpiX() const          { return mDpiX; }
+float DisplayHardware::getDpiY() const          { return mDpiY; }
+float DisplayHardware::getDensity() const       { return mDensity; }
+float DisplayHardware::getRefreshRate() const   { return mRefreshRate; }
+int DisplayHardware::getWidth() const           { return mWidth; }
+int DisplayHardware::getHeight() const          { return mHeight; }
+PixelFormat DisplayHardware::getFormat() const  { return mFormat; }
+
+void DisplayHardware::init(uint32_t dpy)
+{
+    // initialize EGL
+    const EGLint attribs[] = {
+            EGL_RED_SIZE,       5,
+            EGL_GREEN_SIZE,     6,
+            EGL_BLUE_SIZE,      5,
+            EGL_DEPTH_SIZE,     0,
+            EGL_NONE
+    };
+    EGLint w, h, dummy;
+    EGLint numConfigs, n;
+    EGLConfig config;
+    EGLSurface surface;
+    EGLContext context;
+    mFlags = 0;
+
+    // TODO: all the extensions below should be queried through
+    // eglGetProcAddress().
+
+    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+    eglInitialize(display, NULL, NULL);
+    eglGetConfigs(display, NULL, 0, &numConfigs);
+    eglChooseConfig(display, attribs, &config, 1, &n);
+
+    /*
+     * Gather EGL extensions
+     */
+
+    const char* const egl_extensions = eglQueryString(
+            display, EGL_EXTENSIONS);
+    
+    LOGI("EGL informations:");
+    LOGI("# of configs : %d", numConfigs);
+    LOGI("vendor    : %s", eglQueryString(display, EGL_VENDOR));
+    LOGI("version   : %s", eglQueryString(display, EGL_VERSION));
+    LOGI("extensions: %s", egl_extensions);
+    LOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS)?:"Not Supported");
+
+    // TODO: get this from the devfb driver (probably should be HAL module)
+    mFlags |= SWAP_RECTANGLE_EXTENSION;
+    
+    // TODO: get the real "update_on_demand" behavior (probably should be HAL module)
+    mFlags |= UPDATE_ON_DEMAND;
+
+    if (eglGetConfigAttrib(display, config, EGL_CONFIG_CAVEAT, &dummy) == EGL_TRUE) {
+        if (dummy == EGL_SLOW_CONFIG)
+            mFlags |= SLOW_CONFIG;
+    }
+
+    /*
+     * Create our main surface
+     */
+
+    mDisplaySurface = new EGLDisplaySurface();
+
+    surface = eglCreateWindowSurface(display, config, mDisplaySurface.get(), NULL);
+    //checkEGLErrors("eglCreateDisplaySurfaceANDROID");
+
+    if (eglQuerySurface(display, surface, EGL_SWAP_BEHAVIOR, &dummy) == EGL_TRUE) {
+        if (dummy == EGL_BUFFER_PRESERVED) {
+            mFlags |= BUFFER_PRESERVED;
+        }
+    }
+    
+    GLint value = EGL_UNKNOWN;
+    eglQuerySurface(display, surface, EGL_HORIZONTAL_RESOLUTION, &value);
+    if (value == EGL_UNKNOWN) {
+        mDpiX = 160.0f;
+    } else {
+        mDpiX = 25.4f * float(value)/EGL_DISPLAY_SCALING;
+    }
+    value = EGL_UNKNOWN;
+    eglQuerySurface(display, surface, EGL_VERTICAL_RESOLUTION, &value);
+    if (value == EGL_UNKNOWN) {
+        mDpiY = 160.0f;
+    } else {
+        mDpiY = 25.4f * float(value)/EGL_DISPLAY_SCALING;
+    }
+    mRefreshRate = 60.f;    // TODO: get the real refresh rate 
+    
+    
+    char property[PROPERTY_VALUE_MAX];
+    if (property_get("ro.sf.lcd_density", property, NULL) <= 0) {
+        LOGW("ro.sf.lcd_density not defined, using 160 dpi by default.");
+        strcpy(property, "160");
+    }
+    mDensity = atoi(property) * (1.0f/160.0f);
+
+
+    /*
+     * Create our OpenGL ES context
+     */
+    
+    context = eglCreateContext(display, config, NULL, NULL);
+    //checkEGLErrors("eglCreateContext");
+    
+    eglQuerySurface(display, surface, EGL_WIDTH, &mWidth);
+    eglQuerySurface(display, surface, EGL_HEIGHT, &mHeight);
+    
+    
+    /*
+     * Gather OpenGL ES extensions
+     */
+
+    eglMakeCurrent(display, surface, surface, context);
+    const char* const  gl_extensions = (const char*)glGetString(GL_EXTENSIONS);
+    LOGI("OpenGL informations:");
+    LOGI("vendor    : %s", glGetString(GL_VENDOR));
+    LOGI("renderer  : %s", glGetString(GL_RENDERER));
+    LOGI("version   : %s", glGetString(GL_VERSION));
+    LOGI("extensions: %s", gl_extensions);
+
+    if (strstr(gl_extensions, "GL_ARB_texture_non_power_of_two")) {
+        mFlags |= NPOT_EXTENSION;
+    }
+    if (strstr(gl_extensions, "GL_OES_draw_texture")) {
+        mFlags |= DRAW_TEXTURE_EXTENSION;
+    }
+    if (strstr(gl_extensions, "GL_ANDROID_direct_texture")) {
+        mFlags |= DIRECT_TEXTURE;
+    }
+
+    // Unbind the context from this thread
+    eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+
+    mDisplay = display;
+    mConfig  = config;
+    mSurface = surface;
+    mContext = context;
+    mFormat  = GGL_PIXEL_FORMAT_RGB_565;
+    
+    hw_module_t const* module;
+
+    mBlitEngine = NULL;
+    if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) {
+        copybit_open(module, &mBlitEngine);
+    }
+
+    mOverlayEngine = NULL;
+    if (hw_get_module(OVERLAY_HARDWARE_MODULE_ID, &module) == 0) {
+        overlay_control_open(module, &mOverlayEngine);
+    }
+}
+
+/*
+ * Clean up.  Throw out our local state.
+ *
+ * (It's entirely possible we'll never get here, since this is meant
+ * for real hardware, which doesn't restart.)
+ */
+
+void DisplayHardware::fini()
+{
+    eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+    eglTerminate(mDisplay);
+    copybit_close(mBlitEngine);
+    overlay_control_close(mOverlayEngine);
+}
+
+void DisplayHardware::releaseScreen() const
+{
+    DisplayHardwareBase::releaseScreen();
+}
+
+void DisplayHardware::acquireScreen() const
+{
+    DisplayHardwareBase::acquireScreen();
+}
+
+void DisplayHardware::getDisplaySurface(copybit_image_t* img) const
+{
+    img->w      = mDisplaySurface->stride;
+    img->h      = mDisplaySurface->height;
+    img->format = mDisplaySurface->format;
+    img->offset = mDisplaySurface->offset;
+    img->base   = (void*)mDisplaySurface->base;
+    img->fd     = mDisplaySurface->fd;
+}
+
+void DisplayHardware::getDisplaySurface(GGLSurface* fb) const
+{
+    fb->version= sizeof(GGLSurface);
+    fb->width  = mDisplaySurface->width;
+    fb->height = mDisplaySurface->height;
+    fb->stride = mDisplaySurface->stride;
+    fb->format = mDisplaySurface->format;
+    fb->data   = (GGLubyte*)mDisplaySurface->base + mDisplaySurface->offset;
+}
+
+uint32_t DisplayHardware::getPageFlipCount() const {
+    return mDisplaySurface->getPageFlipCount();
+}
+
+/*
+ * "Flip" the front and back buffers.
+ */
+
+void DisplayHardware::flip(const Region& dirty) const
+{
+    checkGLErrors();
+
+    EGLDisplay dpy = mDisplay;
+    EGLSurface surface = mSurface;
+
+    Region newDirty(dirty);
+    newDirty.andSelf(Rect(mWidth, mHeight));
+
+    if (mFlags & BUFFER_PRESERVED) {
+        const Region copyback(mDirty.subtract(newDirty));
+        mDirty = newDirty;
+        mDisplaySurface->copyFrontToBack(copyback);
+    } 
+
+    if (mFlags & SWAP_RECTANGLE_EXTENSION) {
+        const Rect& b(newDirty.bounds());
+        mDisplaySurface->setSwapRectangle(
+                b.left, b.top, b.width(), b.height());
+    }
+
+    eglSwapBuffers(dpy, surface);
+    checkEGLErrors("eglSwapBuffers");
+
+    // for debugging
+    //glClearColor(1,0,0,0);
+    //glClear(GL_COLOR_BUFFER_BIT);
+}
+
+uint32_t DisplayHardware::getFlags() const
+{
+    return mFlags;
+}
+
+void DisplayHardware::makeCurrent() const
+{
+    eglMakeCurrent(mDisplay, mSurface, mSurface, mContext);
+}
+
+void DisplayHardware::copyFrontToImage(const copybit_image_t& front) const {
+    mDisplaySurface->copyFrontToImage(front);
+}
+
+void DisplayHardware::copyBackToImage(const copybit_image_t& front) const {
+    mDisplaySurface->copyBackToImage(front);
+}
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.h b/libs/surfaceflinger/DisplayHardware/DisplayHardware.h
new file mode 100644
index 0000000..550a4d1
--- /dev/null
+++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.h
@@ -0,0 +1,113 @@
+/*
+ * 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_DISPLAY_HARDWARE_H
+#define ANDROID_DISPLAY_HARDWARE_H
+
+#include <stdlib.h>
+
+#include <ui/PixelFormat.h>
+#include <ui/Region.h>
+
+#include <EGL/egl.h>
+
+#include "DisplayHardware/DisplayHardwareBase.h"
+
+struct overlay_control_device_t;
+struct copybit_device_t;
+struct copybit_image_t;
+struct copybit_t;
+
+namespace android {
+
+class EGLDisplaySurface;
+
+class DisplayHardware : public DisplayHardwareBase
+{
+public:
+    enum {
+        DIRECT_TEXTURE          = 0x00000002,
+        SWAP_RECTANGLE_EXTENSION= 0x00000004,
+        COPY_BITS_EXTENSION     = 0x00000008,
+        NPOT_EXTENSION          = 0x00000100,
+        DRAW_TEXTURE_EXTENSION  = 0x00000200,
+        BUFFER_PRESERVED        = 0x00010000,
+        UPDATE_ON_DEMAND        = 0x00020000,   // video driver feature
+        SLOW_CONFIG             = 0x00040000,   // software
+    };
+
+    DisplayHardware(
+            const sp<SurfaceFlinger>& flinger,
+            uint32_t displayIndex);
+
+    ~DisplayHardware();
+
+    void releaseScreen() const;
+    void acquireScreen() const;
+
+    // Flip the front and back buffers if the back buffer is "dirty".  Might
+    // be instantaneous, might involve copying the frame buffer around.
+    void flip(const Region& dirty) const;
+
+    float       getDpiX() const;
+    float       getDpiY() const;
+    float       getRefreshRate() const;
+    float       getDensity() const;
+    int         getWidth() const;
+    int         getHeight() const;
+    PixelFormat getFormat() const;
+    uint32_t    getFlags() const;
+    void        makeCurrent() const;
+
+    uint32_t getPageFlipCount() const;
+    void getDisplaySurface(copybit_image_t* img) const;
+    void getDisplaySurface(GGLSurface* fb) const;
+    EGLDisplay getEGLDisplay() const { return mDisplay; }
+    copybit_device_t* getBlitEngine() const { return mBlitEngine; }
+    overlay_control_device_t* getOverlayEngine() const { return mOverlayEngine; }
+    
+    void copyFrontToImage(const copybit_image_t& front) const;
+    void copyBackToImage(const copybit_image_t& front) const;
+       
+    Rect bounds() const {
+        return Rect(mWidth, mHeight);
+    }
+
+private:
+    void init(uint32_t displayIndex) __attribute__((noinline));
+    void fini() __attribute__((noinline));
+
+    EGLDisplay      mDisplay;
+    EGLSurface      mSurface;
+    EGLContext      mContext;
+    EGLConfig       mConfig;
+    float           mDpiX;
+    float           mDpiY;
+    float           mRefreshRate;
+    float           mDensity;
+    int             mWidth;
+    int             mHeight;
+    PixelFormat     mFormat;
+    uint32_t        mFlags;
+    mutable Region  mDirty;
+    sp<EGLDisplaySurface> mDisplaySurface;
+    copybit_device_t*     mBlitEngine;
+    overlay_control_device_t* mOverlayEngine;
+};
+
+}; // namespace android
+
+#endif // ANDROID_DISPLAY_HARDWARE_H
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp
new file mode 100644
index 0000000..f75e5c2
--- /dev/null
+++ b/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp
@@ -0,0 +1,403 @@
+/*
+ * 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 "SurfaceFlinger"
+
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <termios.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/resource.h>
+
+#include <linux/unistd.h>
+
+#include <utils/Log.h>
+
+#include "DisplayHardware/DisplayHardwareBase.h"
+#include "SurfaceFlinger.h"
+
+// ----------------------------------------------------------------------------
+// the sim build doesn't have gettid
+
+#ifndef HAVE_GETTID
+# define gettid getpid
+#endif
+
+// ----------------------------------------------------------------------------
+namespace android {
+
+static char const * kSleepFileName = "/sys/power/wait_for_fb_sleep";
+static char const * kWakeFileName = "/sys/power/wait_for_fb_wake";
+static char const * const kOldSleepFileName = "/sys/android_power/wait_for_fb_sleep";
+static char const * const kOldWakeFileName = "/sys/android_power/wait_for_fb_wake";
+
+// This dir exists if the framebuffer console is present, either built into
+// the kernel or loaded as a module.
+static char const * const kFbconSysDir = "/sys/class/graphics/fbcon";
+
+// ----------------------------------------------------------------------------
+
+DisplayHardwareBase::DisplayEventThreadBase::DisplayEventThreadBase(
+        const sp<SurfaceFlinger>& flinger)
+    : Thread(false), mFlinger(flinger) {
+}
+
+DisplayHardwareBase::DisplayEventThreadBase::~DisplayEventThreadBase() {
+}
+
+// ----------------------------------------------------------------------------
+
+DisplayHardwareBase::DisplayEventThread::DisplayEventThread(
+        const sp<SurfaceFlinger>& flinger)
+    : DisplayEventThreadBase(flinger)
+{
+}
+
+DisplayHardwareBase::DisplayEventThread::~DisplayEventThread()
+{
+}
+
+bool DisplayHardwareBase::DisplayEventThread::threadLoop()
+{
+    int err = 0;
+    char buf;
+    int fd;
+
+    fd = open(kSleepFileName, O_RDONLY, 0);
+    do {
+      err = read(fd, &buf, 1);
+    } while (err < 0 && errno == EINTR);
+    close(fd);
+    LOGW_IF(err<0, "ANDROID_WAIT_FOR_FB_SLEEP failed (%s)", strerror(errno));
+    if (err >= 0) {
+        sp<SurfaceFlinger> flinger = mFlinger.promote();
+        LOGD("About to give-up screen, flinger = %p", flinger.get());
+        if (flinger != 0) {
+            mBarrier.close();
+            flinger->screenReleased(0);
+            mBarrier.wait();
+        }
+    }
+    fd = open(kWakeFileName, O_RDONLY, 0);
+    do {
+      err = read(fd, &buf, 1);
+    } while (err < 0 && errno == EINTR);
+    close(fd);
+    LOGW_IF(err<0, "ANDROID_WAIT_FOR_FB_WAKE failed (%s)", strerror(errno));
+    if (err >= 0) {
+        sp<SurfaceFlinger> flinger = mFlinger.promote();
+        LOGD("Screen about to return, flinger = %p", flinger.get());
+        if (flinger != 0)
+            flinger->screenAcquired(0);
+    }
+    return true;
+}
+
+status_t DisplayHardwareBase::DisplayEventThread::releaseScreen() const
+{
+    mBarrier.open();
+    return NO_ERROR;
+}
+
+status_t DisplayHardwareBase::DisplayEventThread::readyToRun()
+{
+    if (access(kSleepFileName, R_OK) || access(kWakeFileName, R_OK)) {
+        if (access(kOldSleepFileName, R_OK) || access(kOldWakeFileName, R_OK)) {
+            LOGE("Couldn't open %s or %s", kSleepFileName, kWakeFileName);
+            return NO_INIT;
+        }
+        kSleepFileName = kOldSleepFileName;
+        kWakeFileName = kOldWakeFileName;
+    }
+    return NO_ERROR;
+}
+
+status_t DisplayHardwareBase::DisplayEventThread::initCheck() const
+{
+    return (((access(kSleepFileName, R_OK) == 0 &&
+            access(kWakeFileName, R_OK) == 0) ||
+            (access(kOldSleepFileName, R_OK) == 0 &&
+            access(kOldWakeFileName, R_OK) == 0)) &&
+            access(kFbconSysDir, F_OK) != 0) ? NO_ERROR : NO_INIT;
+}
+
+// ----------------------------------------------------------------------------
+
+pid_t DisplayHardwareBase::ConsoleManagerThread::sSignalCatcherPid = 0;
+
+DisplayHardwareBase::ConsoleManagerThread::ConsoleManagerThread(
+        const sp<SurfaceFlinger>& flinger)
+    : DisplayEventThreadBase(flinger), consoleFd(-1)
+{   
+    sSignalCatcherPid = 0;
+
+    // create a new console
+    char const * const ttydev = "/dev/tty0";
+    int fd = open(ttydev, O_RDWR | O_SYNC);
+    if (fd<0) {
+        LOGE("Can't open %s", ttydev);
+        this->consoleFd = -errno;
+        return;
+    }
+
+    // to make sure that we are in text mode
+    int res = ioctl(fd, KDSETMODE, (void*) KD_TEXT);
+    if (res<0) {
+        LOGE("ioctl(%d, KDSETMODE, ...) failed, res %d (%s)",
+                fd, res, strerror(errno));
+    }
+    
+    // get the current console
+    struct vt_stat vs;
+    res = ioctl(fd, VT_GETSTATE, &vs);
+    if (res<0) {
+        LOGE("ioctl(%d, VT_GETSTATE, ...) failed, res %d (%s)",
+                fd, res, strerror(errno));
+        this->consoleFd = -errno;
+        return;
+    }
+
+    // switch to console 7 (which is what X normaly uses)
+    int vtnum = 7;
+    do {
+        res = ioctl(fd, VT_ACTIVATE, (void*)vtnum);
+    } while(res < 0 && errno == EINTR);
+    if (res<0) {
+        LOGE("ioctl(%d, VT_ACTIVATE, ...) failed, %d (%s) for %d",
+                fd, errno, strerror(errno), vtnum);
+        this->consoleFd = -errno;
+        return;
+    }
+
+    do {
+        res = ioctl(fd, VT_WAITACTIVE, (void*)vtnum);
+    } while(res < 0 && errno == EINTR);
+    if (res<0) {
+        LOGE("ioctl(%d, VT_WAITACTIVE, ...) failed, %d %d %s for %d",
+                fd, res, errno, strerror(errno), vtnum);
+        this->consoleFd = -errno;
+        return;
+    }
+
+    // open the new console
+    close(fd);
+    fd = open(ttydev, O_RDWR | O_SYNC);
+    if (fd<0) {
+        LOGE("Can't open new console %s", ttydev);
+        this->consoleFd = -errno;
+        return;
+    }
+
+    /* disable console line buffer, echo, ... */
+    struct termios ttyarg;
+    ioctl(fd, TCGETS , &ttyarg);
+    ttyarg.c_iflag = 0;
+    ttyarg.c_lflag = 0;
+    ioctl(fd, TCSETS , &ttyarg);
+
+    // set up signals so we're notified when the console changes
+    // we can't use SIGUSR1 because it's used by the java-vm
+    vm.mode = VT_PROCESS;
+    vm.waitv = 0;
+    vm.relsig = SIGUSR2;
+    vm.acqsig = SIGUNUSED;
+    vm.frsig = 0;
+
+    struct sigaction act;
+    sigemptyset(&act.sa_mask);
+    act.sa_handler = sigHandler;
+    act.sa_flags = 0;
+    sigaction(vm.relsig, &act, NULL);
+
+    sigemptyset(&act.sa_mask);
+    act.sa_handler = sigHandler;
+    act.sa_flags = 0;
+    sigaction(vm.acqsig, &act, NULL);
+
+    sigset_t mask;
+    sigemptyset(&mask);
+    sigaddset(&mask, vm.relsig);
+    sigaddset(&mask, vm.acqsig);
+    sigprocmask(SIG_BLOCK, &mask, NULL);
+
+    // switch to graphic mode
+    res = ioctl(fd, KDSETMODE, (void*)KD_GRAPHICS);
+    LOGW_IF(res<0,
+            "ioctl(%d, KDSETMODE, KD_GRAPHICS) failed, res %d", fd, res);
+
+    this->prev_vt_num = vs.v_active;
+    this->vt_num = vtnum;
+    this->consoleFd = fd;
+}
+
+DisplayHardwareBase::ConsoleManagerThread::~ConsoleManagerThread()
+{   
+    if (this->consoleFd >= 0) {
+        int fd = this->consoleFd;
+        int prev_vt_num = this->prev_vt_num;
+        int res;
+        ioctl(fd, KDSETMODE, (void*)KD_TEXT);
+        do {
+            res = ioctl(fd, VT_ACTIVATE, (void*)prev_vt_num);
+        } while(res < 0 && errno == EINTR);
+        do {
+            res = ioctl(fd, VT_WAITACTIVE, (void*)prev_vt_num);
+        } while(res < 0 && errno == EINTR);
+        close(fd);    
+        char const * const ttydev = "/dev/tty0";
+        fd = open(ttydev, O_RDWR | O_SYNC);
+        ioctl(fd, VT_DISALLOCATE, 0);
+        close(fd);
+    }
+}
+
+status_t DisplayHardwareBase::ConsoleManagerThread::readyToRun()
+{
+    if (this->consoleFd >= 0) {
+        sSignalCatcherPid = gettid();
+        
+        sigset_t mask;
+        sigemptyset(&mask);
+        sigaddset(&mask, vm.relsig);
+        sigaddset(&mask, vm.acqsig);
+        sigprocmask(SIG_BLOCK, &mask, NULL);
+
+        int res = ioctl(this->consoleFd, VT_SETMODE, &vm);
+        if (res<0) {
+            LOGE("ioctl(%d, VT_SETMODE, ...) failed, %d (%s)",
+                    this->consoleFd, errno, strerror(errno));
+        }
+        return NO_ERROR;
+    }
+    return this->consoleFd;
+}
+
+void DisplayHardwareBase::ConsoleManagerThread::requestExit()
+{
+    Thread::requestExit();
+    if (sSignalCatcherPid != 0) {
+        // wake the thread up
+        kill(sSignalCatcherPid, SIGINT);
+        // wait for it...
+    }
+}
+
+void DisplayHardwareBase::ConsoleManagerThread::sigHandler(int sig)
+{
+    // resend the signal to our signal catcher thread
+    LOGW("received signal %d in thread %d, resending to %d",
+            sig, gettid(), sSignalCatcherPid);
+
+    // we absolutely need the delays below because without them
+    // our main thread never gets a chance to handle the signal.
+    usleep(10000);
+    kill(sSignalCatcherPid, sig);
+    usleep(10000);
+}
+
+status_t DisplayHardwareBase::ConsoleManagerThread::releaseScreen() const
+{
+    int fd = this->consoleFd;
+    int err = ioctl(fd, VT_RELDISP, (void*)1);
+    LOGE_IF(err<0, "ioctl(%d, VT_RELDISP, 1) failed %d (%s)",
+        fd, errno, strerror(errno));
+    return (err<0) ? (-errno) : status_t(NO_ERROR);
+}
+
+bool DisplayHardwareBase::ConsoleManagerThread::threadLoop()
+{
+    sigset_t mask;
+    sigemptyset(&mask);
+    sigaddset(&mask, vm.relsig);
+    sigaddset(&mask, vm.acqsig);
+
+    int sig = 0;
+    sigwait(&mask, &sig);
+
+    if (sig == vm.relsig) {
+        sp<SurfaceFlinger> flinger = mFlinger.promote();
+        //LOGD("About to give-up screen, flinger = %p", flinger.get());
+        if (flinger != 0)
+            flinger->screenReleased(0);
+    } else if (sig == vm.acqsig) {
+        sp<SurfaceFlinger> flinger = mFlinger.promote();
+        //LOGD("Screen about to return, flinger = %p", flinger.get());
+        if (flinger != 0) 
+            flinger->screenAcquired(0);
+    }
+    
+    return true;
+}
+
+status_t DisplayHardwareBase::ConsoleManagerThread::initCheck() const
+{
+    return consoleFd >= 0 ? NO_ERROR : NO_INIT;
+}
+
+// ----------------------------------------------------------------------------
+
+DisplayHardwareBase::DisplayHardwareBase(const sp<SurfaceFlinger>& flinger,
+        uint32_t displayIndex) 
+    : mCanDraw(true)
+{
+    mDisplayEventThread = new DisplayEventThread(flinger);
+    if (mDisplayEventThread->initCheck() != NO_ERROR) {
+        // fall-back on the console
+        mDisplayEventThread = new ConsoleManagerThread(flinger);
+    }
+}
+
+DisplayHardwareBase::~DisplayHardwareBase()
+{
+    // request exit
+    mDisplayEventThread->requestExitAndWait();
+}
+
+
+bool DisplayHardwareBase::canDraw() const
+{
+    return mCanDraw;
+}
+
+void DisplayHardwareBase::releaseScreen() const
+{
+    status_t err = mDisplayEventThread->releaseScreen();
+    if (err >= 0) {
+        //LOGD("screen given-up");
+        mCanDraw = false;
+    }
+}
+
+void DisplayHardwareBase::acquireScreen() const
+{
+    status_t err = mDisplayEventThread->acquireScreen();
+    if (err >= 0) {
+        //LOGD("screen returned");
+        mCanDraw = true;
+    }
+}
+
+}; // namespace android
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.h b/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.h
new file mode 100644
index 0000000..8369bb8
--- /dev/null
+++ b/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.h
@@ -0,0 +1,96 @@
+/*
+ * 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_DISPLAY_HARDWARE_BASE_H
+#define ANDROID_DISPLAY_HARDWARE_BASE_H
+
+#include <stdint.h>
+#include <utils/RefBase.h>
+#include <utils/threads.h>
+#include <linux/kd.h>
+#include <linux/vt.h>
+#include "Barrier.h"
+
+namespace android {
+
+class SurfaceFlinger; 
+
+class DisplayHardwareBase
+{
+public:
+                DisplayHardwareBase(
+                        const sp<SurfaceFlinger>& flinger,
+                        uint32_t displayIndex);
+
+                ~DisplayHardwareBase();
+
+    // console managment
+    void releaseScreen() const;
+    void acquireScreen() const;
+    bool canDraw() const;
+
+private:
+    class DisplayEventThreadBase : public Thread {
+    protected:
+        wp<SurfaceFlinger> mFlinger;
+    public:
+        DisplayEventThreadBase(const sp<SurfaceFlinger>& flinger);
+        virtual ~DisplayEventThreadBase();
+        virtual void onFirstRef() {
+            run("DisplayEventThread", PRIORITY_URGENT_DISPLAY);
+        }
+        virtual status_t acquireScreen() const { return NO_ERROR; };
+        virtual status_t releaseScreen() const { return NO_ERROR; };
+        virtual status_t initCheck() const = 0;
+    };
+
+    class DisplayEventThread : public DisplayEventThreadBase 
+    {
+        mutable Barrier mBarrier;
+    public:
+                DisplayEventThread(const sp<SurfaceFlinger>& flinger);
+        virtual ~DisplayEventThread();
+        virtual bool threadLoop();
+        virtual status_t readyToRun();
+        virtual status_t releaseScreen() const;
+        virtual status_t initCheck() const;
+    };
+
+    class ConsoleManagerThread : public DisplayEventThreadBase 
+    {
+        int consoleFd;
+        int vt_num;
+        int prev_vt_num;
+        vt_mode vm;
+        static void sigHandler(int sig);
+        static pid_t sSignalCatcherPid;
+    public:
+                ConsoleManagerThread(const sp<SurfaceFlinger>& flinger);
+        virtual ~ConsoleManagerThread();
+        virtual bool threadLoop();
+        virtual status_t readyToRun();
+        virtual void requestExit();
+        virtual status_t releaseScreen() const;
+        virtual status_t initCheck() const;
+    };
+
+    sp<DisplayEventThreadBase>  mDisplayEventThread;
+    mutable int                 mCanDraw;
+};
+
+}; // namespace android
+
+#endif // ANDROID_DISPLAY_HARDWARE_BASE_H