auto import from //depot/cupcake/@135843
diff --git a/libs/ui/Android.mk b/libs/ui/Android.mk
new file mode 100644
index 0000000..f944357
--- /dev/null
+++ b/libs/ui/Android.mk
@@ -0,0 +1,41 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+	Camera.cpp \
+	CameraParameters.cpp \
+	EGLDisplaySurface.cpp \
+	EGLNativeWindowSurface.cpp \
+	EventHub.cpp \
+	EventRecurrence.cpp \
+	KeyLayoutMap.cpp \
+	KeyCharacterMap.cpp \
+	ICamera.cpp \
+	ICameraClient.cpp \
+	ICameraService.cpp \
+	IOverlay.cpp \
+	ISurfaceComposer.cpp \
+	ISurface.cpp \
+	ISurfaceFlingerClient.cpp \
+	LayerState.cpp \
+	Overlay.cpp \
+	PixelFormat.cpp \
+	Point.cpp \
+	Rect.cpp \
+	Region.cpp \
+	Surface.cpp \
+	SurfaceComposerClient.cpp \
+	SurfaceFlingerSynchro.cpp \
+	Time.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+	libcorecg \
+	libcutils \
+	libutils \
+	libpixelflinger \
+	libhardware \
+	libhardware_legacy
+
+LOCAL_MODULE:= libui
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/libs/ui/Camera.cpp b/libs/ui/Camera.cpp
new file mode 100644
index 0000000..b3cbda1
--- /dev/null
+++ b/libs/ui/Camera.cpp
@@ -0,0 +1,408 @@
+/*
+**
+** Copyright (C) 2008, The Android Open Source Project
+** Copyright (C) 2008 HTC Inc.
+**
+** 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_NDEBUG 0
+#define LOG_TAG "Camera"
+#include <utils/Log.h>
+#include <utils/IServiceManager.h>
+#include <utils/threads.h>
+#include <utils/IMemory.h>
+#include <ui/Surface.h>
+#include <ui/Camera.h>
+#include <ui/ICameraService.h>
+
+namespace android {
+
+// client singleton for camera service binder interface
+Mutex Camera::mLock;
+sp<ICameraService> Camera::mCameraService;
+sp<Camera::DeathNotifier> Camera::mDeathNotifier;
+
+// establish binder interface to camera service
+const sp<ICameraService>& Camera::getCameraService()
+{
+    Mutex::Autolock _l(mLock);
+    if (mCameraService.get() == 0) {
+        sp<IServiceManager> sm = defaultServiceManager();
+        sp<IBinder> binder;
+        do {
+            binder = sm->getService(String16("media.camera"));
+            if (binder != 0)
+                break;
+            LOGW("CameraService not published, waiting...");
+            usleep(500000); // 0.5 s
+        } while(true);
+        if (mDeathNotifier == NULL) {
+            mDeathNotifier = new DeathNotifier();
+        }
+        binder->linkToDeath(mDeathNotifier);
+        mCameraService = interface_cast<ICameraService>(binder);
+    }
+    LOGE_IF(mCameraService==0, "no CameraService!?");
+    return mCameraService;
+}
+
+// ---------------------------------------------------------------------------
+
+Camera::Camera()
+{
+    init();
+}
+
+Camera::Camera(const sp<ICamera>& camera)
+{
+    init();
+    // connect this client to existing camera remote
+    if (camera->connect(this) == NO_ERROR) {
+        mStatus = NO_ERROR;
+        mCamera = camera;
+        camera->asBinder()->linkToDeath(this);
+    }
+}
+
+void Camera::init()
+{
+    mStatus = UNKNOWN_ERROR;
+    mShutterCallback = 0;
+    mShutterCallbackCookie = 0;
+    mRawCallback = 0;
+    mRawCallbackCookie = 0;
+    mJpegCallback = 0;
+    mJpegCallbackCookie = 0;
+    mPreviewCallback = 0;
+    mPreviewCallbackCookie = 0;
+    mRecordingCallback = 0;
+    mRecordingCallbackCookie = 0;
+    mErrorCallback = 0;
+    mErrorCallbackCookie = 0;
+    mAutoFocusCallback = 0;
+    mAutoFocusCallbackCookie = 0;
+}
+
+Camera::~Camera()
+{
+    disconnect();
+}
+
+sp<Camera> Camera::connect()
+{
+    LOGV("connect");
+    sp<Camera> c = new Camera();
+    const sp<ICameraService>& cs = getCameraService();
+    if (cs != 0) {
+        c->mCamera = cs->connect(c);
+    }
+    if (c->mCamera != 0) {
+        c->mCamera->asBinder()->linkToDeath(c);
+        c->mStatus = NO_ERROR;
+    } else {
+        c.clear();
+    }
+    return c;
+}
+
+void Camera::disconnect()
+{
+    LOGV("disconnect");
+    if (mCamera != 0) {
+        mErrorCallback = 0;
+        mCamera->disconnect();
+        mCamera = 0;
+    }
+}
+
+status_t Camera::reconnect()
+{
+    LOGV("reconnect");
+    sp <ICamera> c = mCamera;
+    if (c == 0) return NO_INIT;
+    return c->connect(this);
+}
+
+sp<ICamera> Camera::remote()
+{
+    return mCamera;
+}
+
+status_t Camera::lock()
+{
+    sp <ICamera> c = mCamera;
+    if (c == 0) return NO_INIT;
+    return c->lock();
+}
+
+status_t Camera::unlock()
+{
+    sp <ICamera> c = mCamera;
+    if (c == 0) return NO_INIT;
+    return c->unlock();
+}
+
+// pass the buffered ISurface to the camera service
+status_t Camera::setPreviewDisplay(const sp<Surface>& surface)
+{
+    LOGV("setPreviewDisplay");
+    if (surface == 0) {
+        LOGE("app passed NULL surface");
+        return NO_INIT;
+    }
+    sp <ICamera> c = mCamera;
+    if (c == 0) return NO_INIT;
+    return c->setPreviewDisplay(surface->getISurface());
+}
+
+status_t Camera::setPreviewDisplay(const sp<ISurface>& surface)
+{
+    LOGV("setPreviewDisplay");
+    if (surface == 0) {
+        LOGE("app passed NULL surface");
+        return NO_INIT;
+    }
+    sp <ICamera> c = mCamera;
+    if (c == 0) return NO_INIT;
+    return c->setPreviewDisplay(surface);
+}
+
+
+// start preview mode, must call setPreviewDisplay first
+status_t Camera::startPreview()
+{
+    LOGV("startPreview");
+    sp <ICamera> c = mCamera;
+    if (c == 0) return NO_INIT;
+    return c->startPreview();
+}
+
+// start recording mode, must call setPreviewDisplay first
+status_t Camera::startRecording()
+{
+    LOGV("startRecording");
+    sp <ICamera> c = mCamera;
+    if (c == 0) return NO_INIT;
+    return c->startRecording();
+}
+
+// stop preview mode
+void Camera::stopPreview()
+{
+    LOGV("stopPreview");
+    sp <ICamera> c = mCamera;
+    if (c == 0) return;
+    c->stopPreview();
+}
+
+// stop recording mode
+void Camera::stopRecording()
+{
+    LOGV("stopRecording");
+    sp <ICamera> c = mCamera;
+    if (c == 0) return;
+    c->stopRecording();
+}
+
+// release a recording frame
+void Camera::releaseRecordingFrame(const sp<IMemory>& mem)
+{
+    LOGV("releaseRecordingFrame");
+    sp <ICamera> c = mCamera;
+    if (c == 0) return;
+    c->releaseRecordingFrame(mem);
+}
+
+// get preview state
+bool Camera::previewEnabled()
+{
+    LOGV("previewEnabled");
+    sp <ICamera> c = mCamera;
+    if (c == 0) return false;
+    return c->previewEnabled();
+}
+
+// get recording state
+bool Camera::recordingEnabled()
+{
+    LOGV("recordingEnabled");
+    sp <ICamera> c = mCamera;
+    if (c == 0) return false;
+    return c->recordingEnabled();
+}
+
+status_t Camera::autoFocus()
+{
+    LOGV("autoFocus");
+    sp <ICamera> c = mCamera;
+    if (c == 0) return NO_INIT;
+    return c->autoFocus();
+}
+
+// take a picture
+status_t Camera::takePicture()
+{
+    LOGV("takePicture");
+    sp <ICamera> c = mCamera;
+    if (c == 0) return NO_INIT;
+    return c->takePicture();
+}
+
+// set preview/capture parameters - key/value pairs
+status_t Camera::setParameters(const String8& params)
+{
+    LOGV("setParameters");
+    sp <ICamera> c = mCamera;
+    if (c == 0) return NO_INIT;
+    return c->setParameters(params);
+}
+
+// get preview/capture parameters - key/value pairs
+String8 Camera::getParameters() const
+{
+    LOGV("getParameters");
+    String8 params;
+    sp <ICamera> c = mCamera;
+    if (c != 0) params = mCamera->getParameters();
+    return params;
+}
+
+void Camera::setAutoFocusCallback(autofocus_callback cb, void *cookie)
+{
+    LOGV("setAutoFocusCallback");
+    mAutoFocusCallback = cb;
+    mAutoFocusCallbackCookie = cookie;
+}
+
+void Camera::setShutterCallback(shutter_callback cb, void *cookie)
+{
+    LOGV("setShutterCallback");
+    mShutterCallback = cb;
+    mShutterCallbackCookie = cookie;
+}
+
+void Camera::setRawCallback(frame_callback cb, void *cookie)
+{
+    LOGV("setRawCallback");
+    mRawCallback = cb;
+    mRawCallbackCookie = cookie;
+}
+
+void Camera::setJpegCallback(frame_callback cb, void *cookie)
+{
+    LOGV("setJpegCallback");
+    mJpegCallback = cb;
+    mJpegCallbackCookie = cookie;
+}
+
+void Camera::setPreviewCallback(frame_callback cb, void *cookie, int flag)
+{
+    LOGV("setPreviewCallback");
+    mPreviewCallback = cb;
+    mPreviewCallbackCookie = cookie;
+    sp <ICamera> c = mCamera;
+    if (c == 0) return;
+    mCamera->setPreviewCallbackFlag(flag);
+}
+
+void Camera::setRecordingCallback(frame_callback cb, void *cookie)
+{
+    LOGV("setRecordingCallback");
+    mRecordingCallback = cb;
+    mRecordingCallbackCookie = cookie;
+}
+
+void Camera::setErrorCallback(error_callback cb, void *cookie)
+{
+    LOGV("setErrorCallback");
+    mErrorCallback = cb;
+    mErrorCallbackCookie = cookie;
+}
+
+void Camera::autoFocusCallback(bool focused)
+{
+    LOGV("autoFocusCallback");
+    if (mAutoFocusCallback) {
+        mAutoFocusCallback(focused, mAutoFocusCallbackCookie);
+    }
+}
+
+void Camera::shutterCallback()
+{
+    LOGV("shutterCallback");
+    if (mShutterCallback) {
+        mShutterCallback(mShutterCallbackCookie);
+    }
+}
+
+void Camera::rawCallback(const sp<IMemory>& picture)
+{
+    LOGV("rawCallback");
+    if (mRawCallback) {
+        mRawCallback(picture, mRawCallbackCookie);
+    }
+}
+
+// callback from camera service when image is ready
+void Camera::jpegCallback(const sp<IMemory>& picture)
+{
+    LOGV("jpegCallback");
+    if (mJpegCallback) {
+        mJpegCallback(picture, mJpegCallbackCookie);
+    }
+}
+
+// callback from camera service when preview frame is ready
+void Camera::previewCallback(const sp<IMemory>& frame)
+{
+    LOGV("frameCallback");
+    if (mPreviewCallback) {
+        mPreviewCallback(frame, mPreviewCallbackCookie);
+    }
+}
+
+// callback from camera service when a recording frame is ready
+void Camera::recordingCallback(const sp<IMemory>& frame)
+{
+    LOGV("recordingCallback");
+    if (mRecordingCallback) {
+        mRecordingCallback(frame, mRecordingCallbackCookie);
+    }
+}
+
+// callback from camera service when an error occurs in preview or takePicture
+void Camera::errorCallback(status_t error)
+{
+    LOGV("errorCallback");
+    if (mErrorCallback) {
+        mErrorCallback(error, mErrorCallbackCookie);
+    }
+}
+
+void Camera::binderDied(const wp<IBinder>& who) {
+    LOGW("ICamera died");
+    if (mErrorCallback) {
+        mErrorCallback(DEAD_OBJECT, mErrorCallbackCookie);
+    }
+}
+
+void Camera::DeathNotifier::binderDied(const wp<IBinder>& who) {
+    LOGV("binderDied");
+    Mutex::Autolock _l(Camera::mLock);
+    Camera::mCameraService.clear();
+    LOGW("Camera server died!");
+}
+
+}; // namespace android
+
diff --git a/libs/ui/CameraParameters.cpp b/libs/ui/CameraParameters.cpp
new file mode 100644
index 0000000..6c25836
--- /dev/null
+++ b/libs/ui/CameraParameters.cpp
@@ -0,0 +1,273 @@
+/*
+**
+** Copyright 2008, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License"); 
+** you may not use this file except in compliance with the License. 
+** You may obtain a copy of the License at 
+**
+**     http://www.apache.org/licenses/LICENSE-2.0 
+**
+** Unless required by applicable law or agreed to in writing, software 
+** distributed under the License is distributed on an "AS IS" BASIS, 
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+** See the License for the specific language governing permissions and 
+** limitations under the License.
+*/
+
+#define LOG_TAG "CameraParams"
+#include <utils/Log.h>
+
+#include <string.h>
+#include <stdlib.h>
+#include <ui/CameraParameters.h>
+
+namespace android {
+
+static const char* portrait = "portrait";
+static const char* landscape = "landscape";
+
+CameraParameters::CameraParameters()
+                : mMap()
+{
+}
+
+CameraParameters::~CameraParameters()
+{
+}
+
+String8 CameraParameters::flatten() const
+{
+    String8 flattened("");
+    size_t size = mMap.size();
+
+    for (size_t i = 0; i < size; i++) {
+        String8 k, v;
+        k = mMap.keyAt(i);
+        v = mMap.valueAt(i);
+
+        flattened += k;
+        flattened += "=";
+        flattened += v;
+        if (i != size-1)
+            flattened += ";";
+    }
+
+    return flattened;
+}
+
+void CameraParameters::unflatten(const String8 &params)
+{
+    const char *a = params.string();
+    const char *b;
+
+    mMap.clear();
+
+    for (;;) {
+        // Find the bounds of the key name.
+        b = strchr(a, '=');
+        if (b == 0)
+            break;
+
+        // Create the key string.
+        String8 k(a, (size_t)(b-a));
+
+        // Find the value.
+        a = b+1;
+        b = strchr(a, ';');
+        if (b == 0) {
+            // If there's no semicolon, this is the last item.
+            String8 v(a);
+            mMap.add(k, v);
+            break;
+        }
+
+        String8 v(a, (size_t)(b-a));
+        mMap.add(k, v);
+        a = b+1;
+    }
+}
+
+
+void CameraParameters::set(const char *key, const char *value)
+{
+    // XXX i think i can do this with strspn() 
+    if (strchr(key, '=') || strchr(key, ';')) {
+        //XXX LOGE("Key \"%s\"contains invalid character (= or ;)", key);
+        return;
+    }
+
+    if (strchr(value, '=') || strchr(key, ';')) {
+        //XXX LOGE("Value \"%s\"contains invalid character (= or ;)", value);
+        return;
+    }
+
+    mMap.replaceValueFor(String8(key), String8(value));
+}
+
+void CameraParameters::set(const char *key, int value)
+{
+    char str[16];
+    sprintf(str, "%d", value);
+    set(key, str);
+}
+
+const char *CameraParameters::get(const char *key) const
+{
+    String8 v = mMap.valueFor(String8(key));
+    if (v.length() == 0)
+        return 0;
+    return v.string();
+}
+
+int CameraParameters::getInt(const char *key) const
+{
+    const char *v = get(key);
+    if (v == 0)
+        return -1;
+    return strtol(v, 0, 0);
+}
+
+static int parse_size(const char *str, int &width, int &height)
+{
+    // Find the width.
+    char *end;
+    int w = (int)strtol(str, &end, 10);
+    // If an 'x' does not immediately follow, give up.
+    if (*end != 'x')
+        return -1;
+
+    // Find the height, immediately after the 'x'.
+    int h = (int)strtol(end+1, 0, 10);
+
+    width = w;
+    height = h;
+
+    return 0;
+}
+
+void CameraParameters::setPreviewSize(int width, int height)
+{
+    char str[32];
+    sprintf(str, "%dx%d", width, height);
+    set("preview-size", str);
+}
+
+void CameraParameters::getPreviewSize(int *width, int *height) const
+{
+    *width = -1;
+    *height = -1;
+
+    // Get the current string, if it doesn't exist, leave the -1x-1
+    const char *p = get("preview-size");
+    if (p == 0)
+        return;
+
+    int w, h;
+    if (parse_size(p, w, h) == 0) {
+        *width = w;
+        *height = h;
+    }
+}
+
+void CameraParameters::setPreviewFrameRate(int fps)
+{
+    set("preview-frame-rate", fps);
+}
+
+int CameraParameters::getPreviewFrameRate() const
+{
+    return getInt("preview-frame-rate");
+}
+
+void CameraParameters::setPreviewFormat(const char *format)
+{
+    set("preview-format", format);
+}
+
+int CameraParameters::getOrientation() const
+{
+    const char* orientation = get("orientation");
+    if (orientation && !strcmp(orientation, portrait))
+        return CAMERA_ORIENTATION_PORTRAIT;
+    return CAMERA_ORIENTATION_LANDSCAPE;
+}
+
+void CameraParameters::setOrientation(int orientation)
+{
+    if (orientation == CAMERA_ORIENTATION_PORTRAIT) {
+        set("preview-format", portrait);
+    } else {
+        set("preview-format", landscape);
+    }
+}
+
+const char *CameraParameters::getPreviewFormat() const
+{
+    return get("preview-format");
+}
+
+void CameraParameters::setPictureSize(int width, int height)
+{
+    char str[32];
+    sprintf(str, "%dx%d", width, height);
+    set("picture-size", str);
+}
+
+void CameraParameters::getPictureSize(int *width, int *height) const
+{
+    *width = -1;
+    *height = -1;
+
+    // Get the current string, if it doesn't exist, leave the -1x-1
+    const char *p = get("picture-size");
+    if (p == 0)
+        return;
+
+    int w, h;
+    if (parse_size(p, w, h) == 0) {
+        *width = w;
+        *height = h;
+    }
+}
+
+void CameraParameters::setPictureFormat(const char *format)
+{
+    set("picture-format", format);
+}
+
+const char *CameraParameters::getPictureFormat() const
+{
+    return get("picture-format");
+}
+
+void CameraParameters::dump() const
+{
+    LOGD("dump: mMap.size = %d", mMap.size());
+    for (size_t i = 0; i < mMap.size(); i++) {
+        String8 k, v;
+        k = mMap.keyAt(i);
+        v = mMap.valueAt(i);
+        LOGD("%s: %s\n", k.string(), v.string());
+    }
+}
+
+status_t CameraParameters::dump(int fd, const Vector<String16>& args) const
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+    snprintf(buffer, 255, "CameraParameters::dump: mMap.size = %d\n", mMap.size());
+    result.append(buffer);
+    for (size_t i = 0; i < mMap.size(); i++) {
+        String8 k, v;
+        k = mMap.keyAt(i);
+        v = mMap.valueAt(i);
+        snprintf(buffer, 255, "\t%s: %s\n", k.string(), v.string());
+        result.append(buffer);
+    }
+    write(fd, result.string(), result.size());
+    return NO_ERROR;
+}
+
+}; // namespace android
diff --git a/libs/ui/EGLDisplaySurface.cpp b/libs/ui/EGLDisplaySurface.cpp
new file mode 100644
index 0000000..d06c98b
--- /dev/null
+++ b/libs/ui/EGLDisplaySurface.cpp
@@ -0,0 +1,519 @@
+/*
+ **
+ ** Copyright 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 "EGLDisplaySurface"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+
+#include <cutils/log.h>
+#include <cutils/atomic.h>
+#include <cutils/properties.h>
+
+#include <hardware/copybit.h>
+
+#include <ui/SurfaceComposerClient.h>
+#include <ui/DisplayInfo.h>
+#include <ui/Rect.h>
+#include <ui/Region.h>
+#include <ui/EGLDisplaySurface.h>
+
+#if HAVE_ANDROID_OS
+#include <linux/msm_mdp.h>
+#endif
+
+#include <EGL/egl.h>
+
+#include <pixelflinger/format.h>
+
+
+// ----------------------------------------------------------------------------
+
+egl_native_window_t* android_createDisplaySurface()
+{
+    egl_native_window_t* s = new android::EGLDisplaySurface();
+    s->memory_type = NATIVE_MEMORY_TYPE_GPU;
+    return s;
+}
+
+#define LIKELY( exp )       (__builtin_expect( (exp) != 0, true  ))
+#define UNLIKELY( exp )     (__builtin_expect( (exp) != 0, false ))
+
+// ----------------------------------------------------------------------------
+namespace android {
+// ----------------------------------------------------------------------------
+
+EGLDisplaySurface::EGLDisplaySurface()
+    : EGLNativeSurface<EGLDisplaySurface>()
+{
+    egl_native_window_t::version = sizeof(egl_native_window_t);
+    egl_native_window_t::ident = 0;
+    egl_native_window_t::incRef = &EGLDisplaySurface::hook_incRef;
+    egl_native_window_t::decRef = &EGLDisplaySurface::hook_decRef;
+    egl_native_window_t::swapBuffers = &EGLDisplaySurface::hook_swapBuffers;
+    egl_native_window_t::connect = 0;
+    egl_native_window_t::disconnect = 0;
+
+    mFb[0].data = 0;
+    mFb[1].data = 0;
+    mBlitEngine = 0;
+    egl_native_window_t::fd = mapFrameBuffer();
+    if (egl_native_window_t::fd >= 0) {
+        
+        hw_module_t const* module;
+        if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) {
+            copybit_open(module, &mBlitEngine);
+        }
+        
+        const float in2mm = 25.4f;
+        float refreshRate = 1000000000000000LLU / (
+                float( mInfo.upper_margin + mInfo.lower_margin + mInfo.yres )
+                * ( mInfo.left_margin  + mInfo.right_margin + mInfo.xres )
+                * mInfo.pixclock);
+
+        const GGLSurface& buffer = mFb[1 - mIndex];
+        egl_native_window_t::width  = buffer.width;
+        egl_native_window_t::height = buffer.height;
+        egl_native_window_t::stride = buffer.stride;
+        egl_native_window_t::format = buffer.format;
+        egl_native_window_t::base   = intptr_t(mFb[0].data);
+        egl_native_window_t::offset =
+            intptr_t(buffer.data) - egl_native_window_t::base;
+        egl_native_window_t::flags  = 0;
+        egl_native_window_t::xdpi = (mInfo.xres * in2mm) / mInfo.width;
+        egl_native_window_t::ydpi = (mInfo.yres * in2mm) / mInfo.height;
+        egl_native_window_t::fps  = refreshRate;
+        egl_native_window_t::memory_type = NATIVE_MEMORY_TYPE_FB;
+        // no error, set the magic word
+        egl_native_window_t::magic = 0x600913;
+    }
+    mSwapCount = -1;
+    mPageFlipCount = 0;
+}
+
+EGLDisplaySurface::~EGLDisplaySurface()
+{
+    magic = 0;
+    copybit_close(mBlitEngine);
+    mBlitEngine = 0;
+    close(egl_native_window_t::fd);
+    munmap(mFb[0].data, mSize);
+    if (!(mFlags & PAGE_FLIP))
+        free((void*)mFb[1].data);
+}
+
+void EGLDisplaySurface::hook_incRef(NativeWindowType window) {
+    EGLDisplaySurface* that = static_cast<EGLDisplaySurface*>(window);
+    that->incStrong(that);
+}
+void EGLDisplaySurface::hook_decRef(NativeWindowType window) {
+    EGLDisplaySurface* that = static_cast<EGLDisplaySurface*>(window);
+    that->decStrong(that);
+}
+uint32_t EGLDisplaySurface::hook_swapBuffers(NativeWindowType window) {
+    EGLDisplaySurface* that = static_cast<EGLDisplaySurface*>(window);
+    return that->swapBuffers();
+}
+
+void EGLDisplaySurface::setSwapRectangle(int l, int t, int w, int h)
+{
+    mInfo.reserved[0] = 0x54445055; // "UPDT";
+    mInfo.reserved[1] = (uint16_t)l | ((uint32_t)t << 16);
+    mInfo.reserved[2] = (uint16_t)(l+w) | ((uint32_t)(t+h) << 16);
+}
+
+uint32_t EGLDisplaySurface::swapBuffers()
+{
+#define SHOW_FPS 0
+#if SHOW_FPS
+    nsecs_t now = systemTime();
+    if (mSwapCount == -1) {
+        mTime = now;
+        mSwapCount = 0;
+        mSleep = 0;
+    } else {
+        nsecs_t d = now-mTime;
+        if (d >= seconds(1)) {
+            double fps = (mSwapCount * double(seconds(1))) / double(d);
+            LOGD("%f fps, sleep=%d / frame",
+                    fps, (int)ns2us(mSleep / mSwapCount));
+            mSwapCount = 0;
+            mTime = now;
+            mSleep = 0;
+        } else {
+            mSwapCount++;
+        }
+    }
+#endif
+    /* If we can't do the page_flip, just copy the back buffer to the front */
+    if (!(mFlags & PAGE_FLIP)) {
+        memcpy(mFb[0].data, mFb[1].data, mInfo.xres*mInfo.yres*2);
+        return 0;
+    }
+
+    // do the actual flip
+    mIndex = 1 - mIndex;
+    mInfo.activate = FB_ACTIVATE_VBL;
+    mInfo.yoffset = mIndex ? mInfo.yres : 0;
+    if (ioctl(egl_native_window_t::fd, FBIOPUT_VSCREENINFO, &mInfo) == -1) {
+        LOGE("FBIOPUT_VSCREENINFO failed");
+        return 0;
+    }
+
+    /*
+     * this is a monstrous hack: Because the h/w accelerator is not able
+     * to render directly into the framebuffer, we need to copy its
+     * internal framebuffer out to the fb.
+     * oem[0] is used to access the fd of internal fb.
+     * All this is needed only in standalone mode, in SurfaceFlinger mode
+     * we control where the GPU renders.
+     * We do this only if we have copybit, since this hack is needed only
+     * with msm7k.
+     */
+    if (egl_native_window_t::memory_type == NATIVE_MEMORY_TYPE_GPU && oem[0] && mBlitEngine) {
+        copybit_device_t *copybit = mBlitEngine;
+        copybit_rect_t sdrect = { 0, 0,
+                egl_native_window_t::width, egl_native_window_t::height };
+        copybit_image_t dst = {
+                egl_native_window_t::width,
+                egl_native_window_t::height,
+                egl_native_window_t::format,
+                egl_native_window_t::offset,
+                (void*)egl_native_window_t::base,
+                egl_native_window_t::fd
+        };
+        copybit_image_t src = {
+                egl_native_window_t::width,
+                egl_native_window_t::height,
+                egl_native_window_t::format, // XXX: use proper format
+                egl_native_window_t::offset,
+                (void*)egl_native_window_t::base,  // XXX: use proper base
+                egl_native_window_t::oem[0]
+        };
+        region_iterator it(Region(Rect(
+                egl_native_window_t::width, egl_native_window_t::height)));
+        copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0);
+        copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF);
+        copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_DISABLE);
+        copybit->stretch(copybit, &dst, &src, &sdrect, &sdrect, &it);
+    }
+
+    // update the address of the buffer to draw to next
+    const GGLSurface& buffer = mFb[1 - mIndex];
+    egl_native_window_t::offset =
+        intptr_t(buffer.data) - egl_native_window_t::base;
+
+#if SHOW_FPS
+    mSleep += systemTime()-now;
+#endif
+
+    mPageFlipCount++;
+
+    // We don't support screen-size changes for now
+    return 0;
+}
+
+int32_t EGLDisplaySurface::getPageFlipCount() const
+{
+    return mPageFlipCount;
+}
+
+void EGLDisplaySurface::copyFrontToBack(const Region& copyback)
+{
+#if HAVE_ANDROID_OS
+    if (mBlitEngine) {
+        copybit_image_t dst = {
+                w:      egl_native_window_t::stride,
+                h:      egl_native_window_t::height,
+                format: egl_native_window_t::format,
+                offset: mFb[1-mIndex].data - mFb[0].data,
+                base:   (void*)egl_native_window_t::base,
+                fd:     egl_native_window_t::fd
+        };
+        copybit_image_t src = {
+                w:      egl_native_window_t::stride,
+                h:      egl_native_window_t::height,
+                format: egl_native_window_t::format,
+                offset: mFb[mIndex].data - mFb[0].data,
+                base:   (void*)egl_native_window_t::base,
+                fd:     egl_native_window_t::fd
+        };
+        region_iterator it(copyback);
+        mBlitEngine->blit(mBlitEngine, &dst, &src, &it);
+    } else
+#endif
+    {
+        /* no extra copy needed since we copied back to front instead of
+         * flipping */
+        if (!(mFlags & PAGE_FLIP)) {
+            return;
+        }
+
+        Region::iterator iterator(copyback);
+        if (iterator) {
+            Rect r;
+            uint8_t* const screen_src = mFb[  mIndex].data;
+            uint8_t* const screen_dst = mFb[1-mIndex].data;
+            const size_t bpp = bytesPerPixel(egl_native_window_t::format);
+            const size_t bpr = egl_native_window_t::stride * bpp;
+            while (iterator.iterate(&r)) {
+                ssize_t h = r.bottom - r.top;
+                if (h) {
+                    size_t size = (r.right - r.left) * bpp;
+                    size_t o = (r.left + egl_native_window_t::stride * r.top) * bpp;
+                    uint8_t* s = screen_src + o;
+                    uint8_t* d = screen_dst + o;
+                    if (size == bpr) {
+                        size *= h;
+                        h = 1;
+                    }
+                    do {
+                        memcpy(d, s, size);
+                        d += bpr;
+                        s += bpr;
+                    } while (--h > 0);
+                }
+            }
+        }
+    }
+}
+
+void EGLDisplaySurface::copyFrontToImage(const copybit_image_t& dst)
+{
+#if HAVE_ANDROID_OS
+    if (mBlitEngine) {
+        copybit_image_t src = {
+                w:      egl_native_window_t::stride,
+                h:      egl_native_window_t::height,
+                format: egl_native_window_t::format,
+                offset: mFb[mIndex].data - mFb[0].data,
+                base:   (void*)egl_native_window_t::base,
+                fd:     egl_native_window_t::fd
+        };
+        region_iterator it(Region(Rect(
+                egl_native_window_t::width, egl_native_window_t::height)));
+        mBlitEngine->blit(mBlitEngine, &dst, &src, &it);
+    } else
+#endif
+    {
+        uint8_t* const screen_src = mFb[  mIndex].data;
+        const size_t bpp = bytesPerPixel(egl_native_window_t::format);
+        const size_t bpr = egl_native_window_t::stride * bpp;
+        memcpy((char*)dst.base + dst.offset, screen_src,
+                bpr*egl_native_window_t::height);
+    }
+}
+
+void EGLDisplaySurface::copyBackToImage(const copybit_image_t& dst)
+{
+#if HAVE_ANDROID_OS
+    if (mBlitEngine) {
+        copybit_image_t src = {
+                w:      egl_native_window_t::stride,
+                h:      egl_native_window_t::height,
+                format: egl_native_window_t::format,
+                offset: mFb[1-mIndex].data - mFb[0].data,
+                base:   (void*)egl_native_window_t::base,
+                fd:     egl_native_window_t::fd
+        };
+        region_iterator it(Region(Rect(
+                egl_native_window_t::width, egl_native_window_t::height)));
+        mBlitEngine->blit(mBlitEngine, &dst, &src, &it);
+    } else
+#endif
+    {
+        uint8_t* const screen_src = mFb[1-mIndex].data;
+        const size_t bpp = bytesPerPixel(egl_native_window_t::format);
+        const size_t bpr = egl_native_window_t::stride * bpp;
+        memcpy((char*)dst.base + dst.offset, screen_src,
+                bpr*egl_native_window_t::height);
+    }
+}
+
+
+status_t EGLDisplaySurface::mapFrameBuffer()
+{
+    char const * const device_template[] = {
+            "/dev/graphics/fb%u",
+            "/dev/fb%u",
+            0 };
+    int fd = -1;
+    int i=0;
+    char name[64];
+    while ((fd==-1) && device_template[i]) {
+        snprintf(name, 64, device_template[i], 0);
+        fd = open(name, O_RDWR, 0);
+        i++;
+    }
+    if (fd < 0)
+        return -errno;
+
+    struct fb_fix_screeninfo finfo;
+    if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1)
+        return -errno;
+
+    struct fb_var_screeninfo info;
+    if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1)
+        return -errno;
+
+    info.reserved[0] = 0;
+    info.reserved[1] = 0;
+    info.reserved[2] = 0;
+    info.xoffset = 0;
+    info.yoffset = 0;
+    info.yres_virtual = info.yres * 2;
+    info.bits_per_pixel = 16;
+    /* Explicitly request 5/6/5 */
+    info.red.offset = 11;
+    info.red.length = 5;
+    info.green.offset = 5;
+    info.green.length = 6;
+    info.blue.offset = 0;
+    info.blue.length = 5;
+    info.transp.offset = 0;
+    info.transp.length = 0;
+    info.activate = FB_ACTIVATE_NOW;
+
+    uint32_t flags = PAGE_FLIP;
+    if (ioctl(fd, FBIOPUT_VSCREENINFO, &info) == -1) {
+        info.yres_virtual = info.yres;
+        flags &= ~PAGE_FLIP;
+        LOGW("FBIOPUT_VSCREENINFO failed, page flipping not supported");
+    }
+
+    if (info.yres_virtual < info.yres * 2) {
+        info.yres_virtual = info.yres;
+        flags &= ~PAGE_FLIP;
+        LOGW("page flipping not supported (yres_virtual=%d, requested=%d)",
+                info.yres_virtual, info.yres*2);
+    }
+
+    if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1)
+        return -errno;
+
+    int refreshRate = 1000000000000000LLU /
+    (
+            uint64_t( info.upper_margin + info.lower_margin + info.yres )
+            * ( info.left_margin  + info.right_margin + info.xres )
+            * info.pixclock
+    );
+
+    if (refreshRate == 0) {
+        // bleagh, bad info from the driver
+        refreshRate = 60*1000;  // 60 Hz
+    }
+    if (int(info.width) <= 0 || int(info.height) <= 0) {
+        // the driver doesn't return that information
+        // default to 160 dpi
+        info.width  = ((info.xres * 25.4f)/160.0f + 0.5f);
+        info.height = ((info.yres * 25.4f)/160.0f + 0.5f);
+    }
+
+    float xdpi = (info.xres * 25.4f) / info.width;
+    float ydpi = (info.yres * 25.4f) / info.height;
+    float fps  = refreshRate / 1000.0f;
+
+    LOGI(   "using (fd=%d)\n"
+            "id           = %s\n"
+            "xres         = %d px\n"
+            "yres         = %d px\n"
+            "xres_virtual = %d px\n"
+            "yres_virtual = %d px\n"
+            "bpp          = %d\n"
+            "r            = %2u:%u\n"
+            "g            = %2u:%u\n"
+            "b            = %2u:%u\n",
+            fd,
+            finfo.id,
+            info.xres,
+            info.yres,
+            info.xres_virtual,
+            info.yres_virtual,
+            info.bits_per_pixel,
+            info.red.offset, info.red.length,
+            info.green.offset, info.green.length,
+            info.blue.offset, info.blue.length
+    );
+
+    LOGI(   "width        = %d mm (%f dpi)\n"
+            "height       = %d mm (%f dpi)\n"
+            "refresh rate = %.2f Hz\n",
+            info.width,  xdpi,
+            info.height, ydpi,
+            fps
+    );
+
+
+    if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1)
+        return -errno;
+
+    if (finfo.smem_len <= 0)
+        return -errno;
+
+    /*
+     * Open and map the display.
+     */
+
+    void* buffer  = (uint16_t*) mmap(
+            0, finfo.smem_len,
+            PROT_READ | PROT_WRITE,
+            MAP_SHARED,
+            fd, 0);
+
+    if (buffer == MAP_FAILED)
+        return -errno;
+
+    // at least for now, always clear the fb
+    memset(buffer, 0, finfo.smem_len);
+
+    uint8_t* offscreen[2];
+    offscreen[0] = (uint8_t*)buffer;
+    if (flags & PAGE_FLIP) {
+        offscreen[1] = (uint8_t*)buffer + finfo.line_length*info.yres;
+    } else {
+        offscreen[1] = (uint8_t*)malloc(finfo.smem_len);
+        if (offscreen[1] == 0) {
+            munmap(buffer, finfo.smem_len);
+            return NO_MEMORY;
+        }
+    }
+
+    mFlags = flags;
+    mInfo = info;
+    mFinfo = finfo;
+    mSize = finfo.smem_len;
+    mIndex = 0;
+    for (int i=0 ; i<2 ; i++) {
+        mFb[i].version = sizeof(GGLSurface);
+        mFb[i].width   = info.xres;
+        mFb[i].height  = info.yres;
+        mFb[i].stride  = finfo.line_length / (info.bits_per_pixel >> 3);
+        mFb[i].data    = (GGLubyte*)(offscreen[i]);
+        mFb[i].format  = GGL_PIXEL_FORMAT_RGB_565;
+    }
+    return fd;
+}
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+// ----------------------------------------------------------------------------
diff --git a/libs/ui/EGLNativeWindowSurface.cpp b/libs/ui/EGLNativeWindowSurface.cpp
new file mode 100644
index 0000000..f1071cf
--- /dev/null
+++ b/libs/ui/EGLNativeWindowSurface.cpp
@@ -0,0 +1,161 @@
+/* 
+**
+** Copyright 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 "EGLNativeWindowSurface"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <cutils/log.h>
+#include <cutils/atomic.h>
+
+#include <ui/SurfaceComposerClient.h>
+#include <ui/DisplayInfo.h>
+#include <ui/Rect.h>
+
+#include <EGL/egl.h>
+
+#include <pixelflinger/format.h>
+
+#include <ui/EGLNativeWindowSurface.h>
+
+// ----------------------------------------------------------------------------
+namespace android {
+// ----------------------------------------------------------------------------
+
+EGLNativeWindowSurface::EGLNativeWindowSurface(const sp<Surface>& surface)
+    : EGLNativeSurface<EGLNativeWindowSurface>(),
+    mSurface(surface), mConnected(false)
+{
+    egl_native_window_t::magic = 0x600913;
+    egl_native_window_t::version = sizeof(egl_native_window_t);
+    egl_native_window_t::ident = 0;
+    egl_native_window_t::incRef = &EGLNativeWindowSurface::hook_incRef;
+    egl_native_window_t::decRef = &EGLNativeWindowSurface::hook_decRef;
+    egl_native_window_t::swapBuffers = &EGLNativeWindowSurface::hook_swapBuffers;
+    egl_native_window_t::connect = &EGLNativeWindowSurface::hook_connect;
+    egl_native_window_t::disconnect = &EGLNativeWindowSurface::hook_disconnect;
+    
+    DisplayInfo dinfo;
+    SurfaceComposerClient::getDisplayInfo(0, &dinfo);
+    egl_native_window_t::xdpi = dinfo.xdpi;
+    egl_native_window_t::ydpi = dinfo.ydpi;
+    egl_native_window_t::fps  = dinfo.fps;
+    egl_native_window_t::flags= EGL_NATIVES_FLAG_DESTROY_BACKBUFFER;
+}
+
+EGLNativeWindowSurface::~EGLNativeWindowSurface()
+{
+    disconnect();
+    mSurface.clear();
+    magic = 0;
+}
+
+void EGLNativeWindowSurface::hook_incRef(NativeWindowType window)
+{
+    EGLNativeWindowSurface* that = static_cast<EGLNativeWindowSurface*>(window);
+    that->incStrong(that);
+}
+
+void EGLNativeWindowSurface::hook_decRef(NativeWindowType window)
+{
+    EGLNativeWindowSurface* that = static_cast<EGLNativeWindowSurface*>(window);
+    that->decStrong(that);
+}
+
+void EGLNativeWindowSurface::hook_connect(NativeWindowType window)
+{
+    EGLNativeWindowSurface* that = static_cast<EGLNativeWindowSurface*>(window);
+    that->connect();
+}
+
+void EGLNativeWindowSurface::hook_disconnect(NativeWindowType window)
+{
+    EGLNativeWindowSurface* that = static_cast<EGLNativeWindowSurface*>(window);
+    that->disconnect();
+}
+
+uint32_t EGLNativeWindowSurface::hook_swapBuffers(NativeWindowType window)
+{
+    EGLNativeWindowSurface* that = static_cast<EGLNativeWindowSurface*>(window);
+    return that->swapBuffers();
+}
+
+void EGLNativeWindowSurface::setSwapRectangle(int l, int t, int w, int h)
+{
+    mSurface->setSwapRectangle(Rect(l, t, l+w, t+h));
+}
+
+uint32_t EGLNativeWindowSurface::swapBuffers()
+{
+    const int w = egl_native_window_t::width;
+    const int h = egl_native_window_t::height;
+    const sp<Surface>& surface(mSurface);
+    Surface::SurfaceInfo info;
+    surface->unlockAndPost();
+    surface->lock(&info);
+    // update the address of the buffer to draw to next
+    egl_native_window_t::base   = intptr_t(info.base);
+    egl_native_window_t::offset = intptr_t(info.bits) - intptr_t(info.base);
+    
+    // update size if it changed
+    if (w != int(info.w) || h != int(info.h)) {
+        egl_native_window_t::width  = info.w;
+        egl_native_window_t::height = info.h;
+        egl_native_window_t::stride = info.bpr / bytesPerPixel(info.format);
+        egl_native_window_t::format = info.format;
+        return EGL_NATIVES_FLAG_SIZE_CHANGED;
+    }
+    return 0;
+}
+
+void EGLNativeWindowSurface::connect()
+{   
+    if (!mConnected) {
+        Surface::SurfaceInfo info;
+        mSurface->lock(&info);
+        mSurface->setSwapRectangle(Rect(info.w, info.h));
+        mConnected = true;
+
+        egl_native_window_t::width  = info.w;
+        egl_native_window_t::height = info.h;
+        egl_native_window_t::stride = info.bpr / bytesPerPixel(info.format);
+        egl_native_window_t::format = info.format;
+        egl_native_window_t::base   = intptr_t(info.base);
+        egl_native_window_t::offset = intptr_t(info.bits) - intptr_t(info.base);
+        // FIXME: egl_native_window_t::memory_type used to be set from
+        // mSurface, but we wanted to break this dependency. We set it to
+        // GPU because the software rendered doesn't care, but the h/w
+        // accelerator needs it. Eventually, this value should go away
+        // completely, since memory will be managed by OpenGL.
+        egl_native_window_t::memory_type = NATIVE_MEMORY_TYPE_GPU; 
+        egl_native_window_t::fd = 0;
+    }
+}
+
+void EGLNativeWindowSurface::disconnect()
+{
+    if (mConnected) {
+        mSurface->unlock();
+        mConnected = false;
+    }
+}
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+// ----------------------------------------------------------------------------
diff --git a/libs/ui/EventHub.cpp b/libs/ui/EventHub.cpp
new file mode 100644
index 0000000..3b29b09
--- /dev/null
+++ b/libs/ui/EventHub.cpp
@@ -0,0 +1,793 @@
+//
+// Copyright 2005 The Android Open Source Project
+//
+// Handle events, like key input and vsync.
+//
+// The goal is to provide an optimized solution for Linux, not an
+// implementation that works well across all platforms.  We expect
+// events to arrive on file descriptors, so that we can use a select()
+// select() call to sleep.
+//
+// We can't select() on anything but network sockets in Windows, so we
+// provide an alternative implementation of waitEvent for that platform.
+//
+#define LOG_TAG "EventHub"
+
+//#define LOG_NDEBUG 0
+
+#include <ui/EventHub.h>
+#include <hardware_legacy/power.h>
+
+#include <cutils/properties.h>
+#include <utils/IServiceManager.h>
+#include <utils/Log.h>
+#include <utils/Timers.h>
+#include <utils.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <memory.h>
+#include <errno.h>
+#include <assert.h>
+
+#include "KeyLayoutMap.h"
+
+#include <string.h>
+#include <stdint.h>
+#include <dirent.h>
+#ifdef HAVE_INOTIFY
+# include <sys/inotify.h>
+#endif
+#ifdef HAVE_ANDROID_OS
+# include <sys/limits.h>        /* not part of Linux */
+#endif
+#include <sys/poll.h>
+#include <sys/ioctl.h>
+
+/* this macro is used to tell if "bit" is set in "array"
+ * it selects a byte from the array, and does a boolean AND
+ * operation with a byte that only has the relevant bit set.
+ * eg. to check for the 12th bit, we do (array[1] & 1<<4)
+ */
+#define test_bit(bit, array)    (array[bit/8] & (1<<(bit%8)))
+
+#define ID_MASK  0x0000ffff
+#define SEQ_MASK 0x7fff0000
+#define SEQ_SHIFT 16
+#define id_to_index(id)         ((id&ID_MASK)+1)
+
+namespace android {
+
+static const char *WAKE_LOCK_ID = "KeyEvents";
+static const char *device_path = "/dev/input";
+
+/* return the larger integer */
+static inline int max(int v1, int v2)
+{
+    return (v1 > v2) ? v1 : v2;
+}
+
+EventHub::device_t::device_t(int32_t _id, const char* _path)
+    : id(_id), path(_path), classes(0)
+    , keyBitmask(NULL), layoutMap(new KeyLayoutMap()), next(NULL) {
+}
+
+EventHub::device_t::~device_t() {
+    delete [] keyBitmask;
+    delete layoutMap;
+}
+
+EventHub::EventHub(void)
+    : mError(NO_INIT), mHaveFirstKeyboard(false), mFirstKeyboardId(0)
+    , mDevicesById(0), mNumDevicesById(0)
+    , mOpeningDevices(0), mClosingDevices(0)
+    , mDevices(0), mFDs(0), mFDCount(0)
+{
+    acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
+#ifdef EV_SW
+    memset(mSwitches, 0, sizeof(mSwitches));
+#endif
+}
+
+/*
+ * Clean up.
+ */
+EventHub::~EventHub(void)
+{
+    release_wake_lock(WAKE_LOCK_ID);
+    // we should free stuff here...
+}
+
+void EventHub::onFirstRef()
+{
+    mError = openPlatformInput() ? NO_ERROR : UNKNOWN_ERROR;
+}
+
+status_t EventHub::errorCheck() const
+{
+    return mError;
+}
+
+String8 EventHub::getDeviceName(int32_t deviceId) const
+{
+    AutoMutex _l(mLock);
+    device_t* device = getDevice(deviceId);
+    if (device == NULL) return String8();
+    return device->name;
+}
+
+uint32_t EventHub::getDeviceClasses(int32_t deviceId) const
+{
+    AutoMutex _l(mLock);
+    device_t* device = getDevice(deviceId);
+    if (device == NULL) return 0;
+    return device->classes;
+}
+
+int EventHub::getAbsoluteInfo(int32_t deviceId, int axis, int *outMinValue,
+        int* outMaxValue, int* outFlat, int* outFuzz) const
+{
+    AutoMutex _l(mLock);
+    device_t* device = getDevice(deviceId);
+    if (device == NULL) return -1;
+
+    struct input_absinfo info;
+
+    if(ioctl(mFDs[id_to_index(device->id)].fd, EVIOCGABS(axis), &info)) {
+        LOGE("Error reading absolute controller %d for device %s fd %d\n",
+             axis, device->name.string(), mFDs[id_to_index(device->id)].fd);
+        return -1;
+    }
+    *outMinValue = info.minimum;
+    *outMaxValue = info.maximum;
+    *outFlat = info.flat;
+    *outFuzz = info.fuzz;
+    return 0;
+}
+
+int EventHub::getSwitchState(int sw) const
+{
+#ifdef EV_SW
+    if (sw >= 0 && sw <= SW_MAX) {
+        int32_t devid = mSwitches[sw];
+        if (devid != 0) {
+            return getSwitchState(devid, sw);
+        }
+    }
+#endif
+    return -1;
+}
+
+int EventHub::getSwitchState(int32_t deviceId, int sw) const
+{
+#ifdef EV_SW
+    AutoMutex _l(mLock);
+    device_t* device = getDevice(deviceId);
+    if (device == NULL) return -1;
+    
+    if (sw >= 0 && sw <= SW_MAX) {
+        uint8_t sw_bitmask[(SW_MAX+1)/8];
+        memset(sw_bitmask, 0, sizeof(sw_bitmask));
+        if (ioctl(mFDs[id_to_index(device->id)].fd,
+                   EVIOCGSW(sizeof(sw_bitmask)), sw_bitmask) >= 0) {
+            return test_bit(sw, sw_bitmask) ? 1 : 0;
+        }
+    }
+#endif
+    
+    return -1;
+}
+
+int EventHub::getScancodeState(int code) const
+{
+    return getScancodeState(mFirstKeyboardId, code);
+}
+
+int EventHub::getScancodeState(int32_t deviceId, int code) const
+{
+    AutoMutex _l(mLock);
+    device_t* device = getDevice(deviceId);
+    if (device == NULL) return -1;
+    
+    if (code >= 0 && code <= KEY_MAX) {
+        uint8_t key_bitmask[(KEY_MAX+1)/8];
+        memset(key_bitmask, 0, sizeof(key_bitmask));
+        if (ioctl(mFDs[id_to_index(device->id)].fd,
+                   EVIOCGKEY(sizeof(key_bitmask)), key_bitmask) >= 0) {
+            return test_bit(code, key_bitmask) ? 1 : 0;
+        }
+    }
+    
+    return -1;
+}
+
+int EventHub::getKeycodeState(int code) const
+{
+    return getKeycodeState(mFirstKeyboardId, code);
+}
+
+int EventHub::getKeycodeState(int32_t deviceId, int code) const
+{
+    AutoMutex _l(mLock);
+    device_t* device = getDevice(deviceId);
+    if (device == NULL || device->layoutMap == NULL) return -1;
+    
+    Vector<int32_t> scanCodes;
+    device->layoutMap->findScancodes(code, &scanCodes);
+    
+    uint8_t key_bitmask[(KEY_MAX+1)/8];
+    memset(key_bitmask, 0, sizeof(key_bitmask));
+    if (ioctl(mFDs[id_to_index(device->id)].fd,
+               EVIOCGKEY(sizeof(key_bitmask)), key_bitmask) >= 0) {
+        #if 0
+        for (size_t i=0; i<=KEY_MAX; i++) {
+            LOGI("(Scan code %d: down=%d)", i, test_bit(i, key_bitmask));
+        }
+        #endif
+        const size_t N = scanCodes.size();
+        for (size_t i=0; i<N && i<=KEY_MAX; i++) {
+            int32_t sc = scanCodes.itemAt(i);
+            //LOGI("Code %d: down=%d", sc, test_bit(sc, key_bitmask));
+            if (sc >= 0 && sc <= KEY_MAX && test_bit(sc, key_bitmask)) {
+                return 1;
+            }
+        }
+    }
+    
+    return 0;
+}
+
+EventHub::device_t* EventHub::getDevice(int32_t deviceId) const
+{
+    if (deviceId == 0) deviceId = mFirstKeyboardId;
+    int32_t id = deviceId & ID_MASK;
+    if (id >= mNumDevicesById || id < 0) return NULL;
+    device_t* dev = mDevicesById[id].device;
+    if (dev->id == deviceId) {
+        return dev;
+    }
+    return NULL;
+}
+
+bool EventHub::getEvent(int32_t* outDeviceId, int32_t* outType,
+        int32_t* outScancode, int32_t* outKeycode, uint32_t *outFlags,
+        int32_t* outValue, nsecs_t* outWhen)
+{
+    *outDeviceId = 0;
+    *outType = 0;
+    *outScancode = 0;
+    *outKeycode = 0;
+    *outFlags = 0;
+    *outValue = 0;
+    *outWhen = 0;
+
+    status_t err;
+
+    fd_set readfds;
+    int maxFd = -1;
+    int cc;
+    int i;
+    int res;
+    int pollres;
+    struct input_event iev;
+
+    // Note that we only allow one caller to getEvent(), so don't need
+    // to do locking here...  only when adding/removing devices.
+    
+    while(1) {
+
+        // First, report any devices that had last been added/removed.
+        if (mClosingDevices != NULL) {
+            device_t* device = mClosingDevices;
+            LOGV("Reporting device closed: id=0x%x, name=%s\n",
+                 device->id, device->path.string());
+            mClosingDevices = device->next;
+            *outDeviceId = device->id;
+            if (*outDeviceId == mFirstKeyboardId) *outDeviceId = 0;
+            *outType = DEVICE_REMOVED;
+            delete device;
+            return true;
+        }
+        if (mOpeningDevices != NULL) {
+            device_t* device = mOpeningDevices;
+            LOGV("Reporting device opened: id=0x%x, name=%s\n",
+                 device->id, device->path.string());
+            mOpeningDevices = device->next;
+            *outDeviceId = device->id;
+            if (*outDeviceId == mFirstKeyboardId) *outDeviceId = 0;
+            *outType = DEVICE_ADDED;
+            return true;
+        }
+
+        release_wake_lock(WAKE_LOCK_ID);
+
+        pollres = poll(mFDs, mFDCount, -1);
+
+        acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
+
+        if (pollres <= 0) {
+            if (errno != EINTR) {
+                LOGW("select failed (errno=%d)\n", errno);
+                usleep(100000);
+            }
+            continue;
+        }
+
+        //printf("poll %d, returned %d\n", mFDCount, pollres);
+
+        // mFDs[0] is used for inotify, so process regular events starting at mFDs[1]
+        for(i = 1; i < mFDCount; i++) {
+            if(mFDs[i].revents) {
+                LOGV("revents for %d = 0x%08x", i, mFDs[i].revents);
+                if(mFDs[i].revents & POLLIN) {
+                    res = read(mFDs[i].fd, &iev, sizeof(iev));
+                    if (res == sizeof(iev)) {
+                        LOGV("%s got: t0=%d, t1=%d, type=%d, code=%d, v=%d",
+                             mDevices[i]->path.string(),
+                             (int) iev.time.tv_sec, (int) iev.time.tv_usec,
+                             iev.type, iev.code, iev.value);
+                        *outDeviceId = mDevices[i]->id;
+                        if (*outDeviceId == mFirstKeyboardId) *outDeviceId = 0;
+                        *outType = iev.type;
+                        *outScancode = iev.code;
+                        if (iev.type == EV_KEY) {
+                            err = mDevices[i]->layoutMap->map(iev.code, outKeycode, outFlags);
+                            LOGV("iev.code=%d outKeycode=%d outFlags=0x%08x err=%d\n",
+                                iev.code, *outKeycode, *outFlags, err);
+                            if (err != 0) {
+                                *outKeycode = 0;
+                                *outFlags = 0;
+                            }
+                        } else {
+                            *outKeycode = iev.code;
+                        }
+                        *outValue = iev.value;
+                        *outWhen = s2ns(iev.time.tv_sec) + us2ns(iev.time.tv_usec);
+                        return true;
+                    } else {
+                        if (res<0) {
+                            LOGW("could not get event (errno=%d)", errno);
+                        } else {
+                            LOGE("could not get event (wrong size: %d)", res);
+                        }
+                        continue;
+                    }
+                }
+            }
+        }
+        
+        // read_notify() will modify mFDs and mFDCount, so this must be done after
+        // processing all other events.
+        if(mFDs[0].revents & POLLIN) {
+            read_notify(mFDs[0].fd);
+        }
+    }
+}
+
+/*
+ * Open the platform-specific input device.
+ */
+bool EventHub::openPlatformInput(void)
+{
+    /*
+     * Open platform-specific input device(s).
+     */
+    int res;
+
+    mFDCount = 1;
+    mFDs = (pollfd *)calloc(1, sizeof(mFDs[0]));
+    mDevices = (device_t **)calloc(1, sizeof(mDevices[0]));
+    mFDs[0].events = POLLIN;
+    mDevices[0] = NULL;
+#ifdef HAVE_INOTIFY
+    mFDs[0].fd = inotify_init();
+    res = inotify_add_watch(mFDs[0].fd, device_path, IN_DELETE | IN_CREATE);
+    if(res < 0) {
+        LOGE("could not add watch for %s, %s\n", device_path, strerror(errno));
+    }
+#else
+    /*
+     * The code in EventHub::getEvent assumes that mFDs[0] is an inotify fd.
+     * We allocate space for it and set it to something invalid.
+     */
+    mFDs[0].fd = -1;
+#endif
+
+    res = scan_dir(device_path);
+    if(res < 0) {
+        LOGE("scan dir failed for %s\n", device_path);
+        //open_device("/dev/input/event0");
+    }
+
+    return true;
+}
+
+/*
+ * Inspect the known devices to determine whether physical keys exist for the given
+ * framework-domain key codes.
+ */
+bool EventHub::hasKeys(size_t numCodes, int32_t* keyCodes, uint8_t* outFlags) {
+    for (size_t codeIndex = 0; codeIndex < numCodes; codeIndex++) {
+        outFlags[codeIndex] = 0;
+
+        // check each available hardware device for support for this keycode
+        Vector<int32_t> scanCodes;
+        for (int n = 0; (n < mFDCount) && (outFlags[codeIndex] == 0); n++) {
+            if (mDevices[n]) {
+                status_t err = mDevices[n]->layoutMap->findScancodes(keyCodes[codeIndex], &scanCodes);
+                if (!err) {
+                    // check the possible scan codes identified by the layout map against the
+                    // map of codes actually emitted by the driver
+                    for (size_t sc = 0; sc < scanCodes.size(); sc++) {
+                        if (test_bit(scanCodes[sc], mDevices[n]->keyBitmask)) {
+                            outFlags[codeIndex] = 1;
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    return true;
+}
+
+// ----------------------------------------------------------------------------
+
+int EventHub::open_device(const char *deviceName)
+{
+    int version;
+    int fd;
+    struct pollfd *new_mFDs;
+    device_t **new_devices;
+    char **new_device_names;
+    char name[80];
+    char location[80];
+    char idstr[80];
+    struct input_id id;
+
+    LOGV("Opening device: %s", deviceName);
+
+    AutoMutex _l(mLock);
+    
+    fd = open(deviceName, O_RDWR);
+    if(fd < 0) {
+        LOGE("could not open %s, %s\n", deviceName, strerror(errno));
+        return -1;
+    }
+
+    if(ioctl(fd, EVIOCGVERSION, &version)) {
+        LOGE("could not get driver version for %s, %s\n", deviceName, strerror(errno));
+        return -1;
+    }
+    if(ioctl(fd, EVIOCGID, &id)) {
+        LOGE("could not get driver id for %s, %s\n", deviceName, strerror(errno));
+        return -1;
+    }
+    name[sizeof(name) - 1] = '\0';
+    location[sizeof(location) - 1] = '\0';
+    idstr[sizeof(idstr) - 1] = '\0';
+    if(ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) {
+        //fprintf(stderr, "could not get device name for %s, %s\n", deviceName, strerror(errno));
+        name[0] = '\0';
+    }
+    if(ioctl(fd, EVIOCGPHYS(sizeof(location) - 1), &location) < 1) {
+        //fprintf(stderr, "could not get location for %s, %s\n", deviceName, strerror(errno));
+        location[0] = '\0';
+    }
+    if(ioctl(fd, EVIOCGUNIQ(sizeof(idstr) - 1), &idstr) < 1) {
+        //fprintf(stderr, "could not get idstring for %s, %s\n", deviceName, strerror(errno));
+        idstr[0] = '\0';
+    }
+
+    int devid = 0;
+    while (devid < mNumDevicesById) {
+        if (mDevicesById[devid].device == NULL) {
+            break;
+        }
+        devid++;
+    }
+    if (devid >= mNumDevicesById) {
+        device_ent* new_devids = (device_ent*)realloc(mDevicesById,
+                sizeof(mDevicesById[0]) * (devid + 1));
+        if (new_devids == NULL) {
+            LOGE("out of memory");
+            return -1;
+        }
+        mDevicesById = new_devids;
+        mNumDevicesById = devid+1;
+        mDevicesById[devid].device = NULL;
+        mDevicesById[devid].seq = 0;
+    }
+
+    mDevicesById[devid].seq = (mDevicesById[devid].seq+(1<<SEQ_SHIFT))&SEQ_MASK;
+    if (mDevicesById[devid].seq == 0) {
+        mDevicesById[devid].seq = 1<<SEQ_SHIFT;
+    }
+
+    new_mFDs = (pollfd*)realloc(mFDs, sizeof(mFDs[0]) * (mFDCount + 1));
+    new_devices = (device_t**)realloc(mDevices, sizeof(mDevices[0]) * (mFDCount + 1));
+    if (new_mFDs == NULL || new_devices == NULL) {
+        LOGE("out of memory");
+        return -1;
+    }
+    mFDs = new_mFDs;
+    mDevices = new_devices;
+
+#if 0
+    LOGI("add device %d: %s\n", mFDCount, deviceName);
+    LOGI("  bus:      %04x\n"
+         "  vendor    %04x\n"
+         "  product   %04x\n"
+         "  version   %04x\n",
+        id.bustype, id.vendor, id.product, id.version);
+    LOGI("  name:     \"%s\"\n", name);
+    LOGI("  location: \"%s\"\n"
+         "  id:       \"%s\"\n", location, idstr);
+    LOGI("  version:  %d.%d.%d\n",
+        version >> 16, (version >> 8) & 0xff, version & 0xff);
+#endif
+
+    device_t* device = new device_t(devid|mDevicesById[devid].seq, deviceName);
+    if (device == NULL) {
+        LOGE("out of memory");
+        return -1;
+    }
+
+    mFDs[mFDCount].fd = fd;
+    mFDs[mFDCount].events = POLLIN;
+
+    // figure out the kinds of events the device reports
+    uint8_t key_bitmask[(KEY_MAX+1)/8];
+    memset(key_bitmask, 0, sizeof(key_bitmask));
+    LOGV("Getting keys...");
+    if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(key_bitmask)), key_bitmask) >= 0) {
+        //LOGI("MAP\n");
+        //for (int i=0; i<((KEY_MAX+1)/8); i++) {
+        //    LOGI("%d: 0x%02x\n", i, key_bitmask[i]);
+        //}
+        for (int i=0; i<((BTN_MISC+7)/8); i++) {
+            if (key_bitmask[i] != 0) {
+                device->classes |= CLASS_KEYBOARD;
+                // 'Q' key support = cheap test of whether this is an alpha-capable kbd
+                if (test_bit(KEY_Q, key_bitmask)) {
+                    device->classes |= CLASS_ALPHAKEY;
+                }
+                break;
+            }
+        }
+        if ((device->classes & CLASS_KEYBOARD) != 0) {
+            device->keyBitmask = new uint8_t[(KEY_MAX+1)/8];
+            if (device->keyBitmask != NULL) {
+                memcpy(device->keyBitmask, key_bitmask, sizeof(key_bitmask));
+            } else {
+                delete device;
+                LOGE("out of memory allocating key bitmask");
+                return -1;
+            }
+        }
+    }
+    if (test_bit(BTN_MOUSE, key_bitmask)) {
+        uint8_t rel_bitmask[(REL_MAX+1)/8];
+        memset(rel_bitmask, 0, sizeof(rel_bitmask));
+        LOGV("Getting relative controllers...");
+        if (ioctl(fd, EVIOCGBIT(EV_REL, sizeof(rel_bitmask)), rel_bitmask) >= 0)
+        {
+            if (test_bit(REL_X, rel_bitmask) && test_bit(REL_Y, rel_bitmask)) {
+                device->classes |= CLASS_TRACKBALL;
+            }
+        }
+    }
+    if (test_bit(BTN_TOUCH, key_bitmask)) {
+        uint8_t abs_bitmask[(ABS_MAX+1)/8];
+        memset(abs_bitmask, 0, sizeof(abs_bitmask));
+        LOGV("Getting absolute controllers...");
+        if (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(abs_bitmask)), abs_bitmask) >= 0)
+        {
+            if (test_bit(ABS_X, abs_bitmask) && test_bit(ABS_Y, abs_bitmask)) {
+                device->classes |= CLASS_TOUCHSCREEN;
+            }
+        }
+    }
+
+#ifdef EV_SW
+    // figure out the switches this device reports
+    uint8_t sw_bitmask[(SW_MAX+1)/8];
+    memset(sw_bitmask, 0, sizeof(sw_bitmask));
+    if (ioctl(fd, EVIOCGBIT(EV_SW, sizeof(sw_bitmask)), sw_bitmask) >= 0) {
+        for (int i=0; i<EV_SW; i++) {
+            //LOGI("Device 0x%x sw %d: has=%d", device->id, i, test_bit(i, sw_bitmask));
+            if (test_bit(i, sw_bitmask)) {
+                if (mSwitches[i] == 0) {
+                    mSwitches[i] = device->id;
+                }
+            }
+        }
+    }
+#endif
+
+    LOGI("New device: path=%s name=%s id=0x%x (of 0x%x) index=%d fd=%d classes=0x%x\n",
+         deviceName, name, device->id, mNumDevicesById, mFDCount, fd, device->classes);
+
+    if ((device->classes&CLASS_KEYBOARD) != 0) {
+        char devname[101];
+        char tmpfn[101];
+        char keylayoutFilename[300];
+
+        // a more descriptive name
+        ioctl(mFDs[mFDCount].fd, EVIOCGNAME(sizeof(devname)-1), devname);
+        devname[sizeof(devname)-1] = 0;
+        device->name = devname;
+
+        // replace all the spaces with underscores
+        strcpy(tmpfn, devname);
+        for (char *p = strchr(tmpfn, ' '); p && *p; p = strchr(tmpfn, ' '))
+            *p = '_';
+
+        // find the .kl file we need for this device
+        const char* root = getenv("ANDROID_ROOT");
+        snprintf(keylayoutFilename, sizeof(keylayoutFilename),
+                 "%s/usr/keylayout/%s.kl", root, tmpfn);
+        bool defaultKeymap = false;
+        if (access(keylayoutFilename, R_OK)) {
+            snprintf(keylayoutFilename, sizeof(keylayoutFilename),
+                     "%s/usr/keylayout/%s", root, "qwerty.kl");
+            defaultKeymap = true;
+        }
+        device->layoutMap->load(keylayoutFilename);
+
+        // tell the world about the devname (the descriptive name)
+        int32_t publicID;
+        if (!mHaveFirstKeyboard && !defaultKeymap) {
+            publicID = 0;
+            // the built-in keyboard has a well-known device ID of 0,
+            // this device better not go away.
+            mHaveFirstKeyboard = true;
+            mFirstKeyboardId = device->id;
+        } else {
+            publicID = device->id;
+            // ensure mFirstKeyboardId is set to -something-.
+            if (mFirstKeyboardId == 0) {
+                mFirstKeyboardId = device->id;
+            }
+        }
+        char propName[100];
+        sprintf(propName, "hw.keyboards.%u.devname", publicID);
+        property_set(propName, devname);
+
+        LOGI("New keyboard: publicID=%d device->id=%d devname='%s' propName='%s' keylayout='%s'\n",
+                publicID, device->id, devname, propName, keylayoutFilename);
+    }
+
+    LOGV("Adding device %s %p at %d, id = %d, classes = 0x%x\n",
+         deviceName, device, mFDCount, devid, device->classes);
+
+    mDevicesById[devid].device = device;
+    device->next = mOpeningDevices;
+    mOpeningDevices = device;
+    mDevices[mFDCount] = device;
+
+    mFDCount++;
+    return 0;
+}
+
+int EventHub::close_device(const char *deviceName)
+{
+    AutoMutex _l(mLock);
+    
+    int i;
+    for(i = 1; i < mFDCount; i++) {
+        if(strcmp(mDevices[i]->path.string(), deviceName) == 0) {
+            //LOGD("remove device %d: %s\n", i, deviceName);
+            device_t* device = mDevices[i];
+            int count = mFDCount - i - 1;
+            int index = (device->id&ID_MASK);
+            mDevicesById[index].device = NULL;
+            memmove(mDevices + i, mDevices + i + 1, sizeof(mDevices[0]) * count);
+            memmove(mFDs + i, mFDs + i + 1, sizeof(mFDs[0]) * count);
+
+#ifdef EV_SW
+            for (int j=0; j<EV_SW; j++) {
+                if (mSwitches[j] == device->id) {
+                    mSwitches[j] = 0;
+                }
+            }
+#endif
+            
+            device->next = mClosingDevices;
+            mClosingDevices = device;
+
+            mFDCount--;
+
+            uint32_t publicID;
+            if (device->id == mFirstKeyboardId) {
+                LOGW("built-in keyboard device %s (id=%d) is closing! the apps will not like this",
+                        device->path.string(), mFirstKeyboardId);
+                mFirstKeyboardId = 0;
+                publicID = 0;
+            } else {
+                publicID = device->id;
+            }
+            // clear the property
+            char propName[100];
+            sprintf(propName, "hw.keyboards.%u.devname", publicID);
+            property_set(propName, NULL);
+            return 0;
+        }
+    }
+    LOGE("remote device: %s not found\n", deviceName);
+    return -1;
+}
+
+int EventHub::read_notify(int nfd)
+{
+#ifdef HAVE_INOTIFY
+    int res;
+    char devname[PATH_MAX];
+    char *filename;
+    char event_buf[512];
+    int event_size;
+    int event_pos = 0;
+    struct inotify_event *event;
+
+    res = read(nfd, event_buf, sizeof(event_buf));
+    if(res < (int)sizeof(*event)) {
+        if(errno == EINTR)
+            return 0;
+        LOGW("could not get event, %s\n", strerror(errno));
+        return 1;
+    }
+    //printf("got %d bytes of event information\n", res);
+
+    strcpy(devname, device_path);
+    filename = devname + strlen(devname);
+    *filename++ = '/';
+
+    while(res >= (int)sizeof(*event)) {
+        event = (struct inotify_event *)(event_buf + event_pos);
+        //printf("%d: %08x \"%s\"\n", event->wd, event->mask, event->len ? event->name : "");
+        if(event->len) {
+            strcpy(filename, event->name);
+            if(event->mask & IN_CREATE) {
+                open_device(devname);
+            }
+            else {
+                close_device(devname);
+            }
+        }
+        event_size = sizeof(*event) + event->len;
+        res -= event_size;
+        event_pos += event_size;
+    }
+#endif
+    return 0;
+}
+
+
+int EventHub::scan_dir(const char *dirname)
+{
+    char devname[PATH_MAX];
+    char *filename;
+    DIR *dir;
+    struct dirent *de;
+    dir = opendir(dirname);
+    if(dir == NULL)
+        return -1;
+    strcpy(devname, dirname);
+    filename = devname + strlen(devname);
+    *filename++ = '/';
+    while((de = readdir(dir))) {
+        if(de->d_name[0] == '.' &&
+           (de->d_name[1] == '\0' ||
+            (de->d_name[1] == '.' && de->d_name[2] == '\0')))
+            continue;
+        strcpy(filename, de->d_name);
+        open_device(devname);
+    }
+    closedir(dir);
+    return 0;
+}
+
+}; // namespace android
diff --git a/libs/ui/EventRecurrence.cpp b/libs/ui/EventRecurrence.cpp
new file mode 100644
index 0000000..b436b50
--- /dev/null
+++ b/libs/ui/EventRecurrence.cpp
@@ -0,0 +1,484 @@
+/*
+ *  Copyright 2006 The Android Open Source Project
+ */
+
+#include <pim/EventRecurrence.h>
+#include <utils/String8.h>
+#include <stdio.h>
+#include <limits.h>
+
+namespace android {
+
+#define FAIL_HERE() do { \
+            printf("Parsing failed at line %d\n", __LINE__); \
+            return UNKNOWN_ERROR; \
+        } while(0)
+
+EventRecurrence::EventRecurrence()
+    :freq((freq_t)0),
+     until(),
+     count(0),
+     interval(0),
+     bysecond(0),
+     bysecondCount(0),
+     byminute(0),
+     byminuteCount(0),
+     byhour(0),
+     byhourCount(0),
+     byday(0),
+     bydayNum(0),
+     bydayCount(0),
+     bymonthday(0),
+     bymonthdayCount(0),
+     byyearday(0),
+     byyeardayCount(0),
+     byweekno(0),
+     byweeknoCount(0),
+     bymonth(0),
+     bymonthCount(0),
+     bysetpos(0),
+     bysetposCount(0),
+     wkst(0)
+{
+}
+
+EventRecurrence::~EventRecurrence()
+{
+    delete[] bysecond;
+    delete[] byminute;
+    delete[] byhour;
+    delete[] byday;
+    delete[] bydayNum;
+    delete[] byyearday;
+    delete[] bymonthday;
+    delete[] byweekno;
+    delete[] bymonth;
+    delete[] bysetpos;
+}
+
+enum LHS {
+    NONE_LHS = 0,
+    FREQ,
+    UNTIL,
+    COUNT,
+    INTERVAL,
+    BYSECOND,
+    BYMINUTE,
+    BYHOUR,
+    BYDAY,
+    BYMONTHDAY,
+    BYYEARDAY,
+    BYWEEKNO,
+    BYMONTH,
+    BYSETPOS,
+    WKST
+};
+
+struct LHSProc
+{
+    const char16_t* text;
+    size_t textSize;
+    uint32_t value;
+};
+
+const char16_t FREQ_text[] = { 'F', 'R', 'E', 'Q' };
+const char16_t UNTIL_text[] = { 'U', 'N', 'T', 'I', 'L' };
+const char16_t COUNT_text[] = { 'C', 'O', 'U', 'N', 'T' };
+const char16_t INTERVAL_text[] = { 'I', 'N', 'T', 'E', 'R', 'V', 'A', 'L'};
+const char16_t BYSECOND_text[] = { 'B', 'Y', 'S', 'E', 'C', 'O', 'N', 'D' };
+const char16_t BYMINUTE_text[] = { 'B', 'Y', 'M', 'I', 'N', 'U', 'T', 'E' };
+const char16_t BYHOUR_text[] = { 'B', 'Y', 'H', 'O', 'U', 'R' };
+const char16_t BYDAY_text[] = { 'B', 'Y', 'D', 'A', 'Y' };
+const char16_t BYMONTHDAY_text[] = { 'B','Y','M','O','N','T','H','D','A','Y' };
+const char16_t BYYEARDAY_text[] = { 'B','Y','Y','E','A','R','D','A','Y' };
+const char16_t BYWEEKNO_text[] = { 'B', 'Y', 'W', 'E', 'E', 'K', 'N', 'O' };
+const char16_t BYMONTH_text[] = { 'B', 'Y', 'M', 'O', 'N', 'T', 'H' };
+const char16_t BYSETPOS_text[] = { 'B', 'Y', 'S', 'E', 'T', 'P', 'O', 'S' };
+const char16_t WKST_text[] = { 'W', 'K', 'S', 'T' };
+
+#define SIZ(x) (sizeof(x)/sizeof(x[0]))
+
+const LHSProc LHSPROC[] = {
+    { FREQ_text, SIZ(FREQ_text), FREQ },
+    { UNTIL_text, SIZ(UNTIL_text), UNTIL },
+    { COUNT_text, SIZ(COUNT_text), COUNT },
+    { INTERVAL_text, SIZ(INTERVAL_text), INTERVAL },
+    { BYSECOND_text, SIZ(BYSECOND_text), BYSECOND },
+    { BYMINUTE_text, SIZ(BYMINUTE_text), BYMINUTE },
+    { BYHOUR_text, SIZ(BYHOUR_text), BYHOUR },
+    { BYDAY_text, SIZ(BYDAY_text), BYDAY },
+    { BYMONTHDAY_text, SIZ(BYMONTHDAY_text), BYMONTHDAY },
+    { BYYEARDAY_text, SIZ(BYYEARDAY_text), BYYEARDAY },
+    { BYWEEKNO_text, SIZ(BYWEEKNO_text), BYWEEKNO },
+    { BYMONTH_text, SIZ(BYMONTH_text), BYMONTH },
+    { BYSETPOS_text, SIZ(BYSETPOS_text), BYSETPOS },
+    { WKST_text, SIZ(WKST_text), WKST },
+    { NULL, 0, NONE_LHS },
+};
+
+const char16_t SECONDLY_text[] = { 'S','E','C','O','N','D','L','Y' };
+const char16_t MINUTELY_text[] = { 'M','I','N','U','T','E','L','Y' };
+const char16_t HOURLY_text[] = { 'H','O','U','R','L','Y' };
+const char16_t DAILY_text[] = { 'D','A','I','L','Y' };
+const char16_t WEEKLY_text[] = { 'W','E','E','K','L','Y' };
+const char16_t MONTHLY_text[] = { 'M','O','N','T','H','L','Y' };
+const char16_t YEARLY_text[] = { 'Y','E','A','R','L','Y' };
+
+typedef LHSProc FreqProc;
+
+const FreqProc FREQPROC[] = {
+    { SECONDLY_text, SIZ(SECONDLY_text), EventRecurrence::SECONDLY },
+    { MINUTELY_text, SIZ(MINUTELY_text), EventRecurrence::MINUTELY },
+    { HOURLY_text, SIZ(HOURLY_text), EventRecurrence::HOURLY },
+    { DAILY_text, SIZ(DAILY_text), EventRecurrence::DAILY },
+    { WEEKLY_text, SIZ(WEEKLY_text), EventRecurrence::WEEKLY },
+    { MONTHLY_text, SIZ(MONTHLY_text), EventRecurrence::MONTHLY },
+    { YEARLY_text, SIZ(YEARLY_text), EventRecurrence::YEARLY },
+    { NULL, 0, NONE_LHS },
+};
+
+const char16_t SU_text[] = { 'S','U' };
+const char16_t MO_text[] = { 'M','O' };
+const char16_t TU_text[] = { 'T','U' };
+const char16_t WE_text[] = { 'W','E' };
+const char16_t TH_text[] = { 'T','H' };
+const char16_t FR_text[] = { 'F','R' };
+const char16_t SA_text[] = { 'S','A' };
+
+const FreqProc WEEKDAYPROC[] = {
+    { SU_text, SIZ(SU_text), EventRecurrence::SU },
+    { MO_text, SIZ(MO_text), EventRecurrence::MO },
+    { TU_text, SIZ(TU_text), EventRecurrence::TU },
+    { WE_text, SIZ(WE_text), EventRecurrence::WE },
+    { TH_text, SIZ(TH_text), EventRecurrence::TH },
+    { FR_text, SIZ(FR_text), EventRecurrence::FR },
+    { SA_text, SIZ(SA_text), EventRecurrence::SA },
+    { NULL, 0, NONE_LHS },
+};
+
+// returns the index into LHSPROC for the match or -1 if not found
+inline static int
+match_proc(const LHSProc* p, const char16_t* str, size_t len)
+{
+    int i = 0;
+    while (p->text != NULL) {
+        if (p->textSize == len) {
+            if (0 == memcmp(p->text, str, len*sizeof(char16_t))) {
+                return i;
+            }
+        }
+        p++;
+        i++;
+    }
+    return -1;
+}
+
+// rangeMin and rangeMax are inclusive
+static status_t
+parse_int(const char16_t* str, size_t len, int* out,
+            int rangeMin, int rangeMax, bool zeroOK)
+{
+    char16_t c;
+    size_t i=0;
+
+    if (len == 0) {
+        FAIL_HERE();
+    }
+    bool negative = false;
+    c = str[0];
+    if (c == '-' ) {
+        negative = true;
+        i++;
+    }
+    else if (c == '+') {
+        i++;
+    }
+    int n = 0;
+    for (; i<len; i++) {
+        c = str[i];
+        if (c < '0' || c > '9') {
+            FAIL_HERE();
+        }
+        int prev = n;
+        n *= 10;
+        // the spec doesn't address how big these numbers can be,
+        // so we're not going to worry about not being able to represent
+        // INT_MIN, and if we're going to wrap, we'll just clamp to
+        // INT_MAX instead
+        if (n < prev) {
+            n = INT_MAX;
+        } else {
+            n += c - '0';
+        }
+    }
+    if (negative) {
+        n = -n;
+    }
+    if (n < rangeMin || n > rangeMax) {
+        FAIL_HERE();
+    }
+    if (!zeroOK && n == 0) {
+        FAIL_HERE();
+    }
+    *out = n;
+    return NO_ERROR;
+}
+
+static status_t
+parse_int_list(const char16_t* str, size_t len, int* countOut, int** listOut,
+          int rangeMin, int rangeMax, bool zeroOK,
+          status_t (*func)(const char16_t*,size_t,int*,int,int,bool)=parse_int)
+{
+    status_t err;
+
+    if (len == 0) {
+        *countOut = 0;
+        *listOut = NULL;
+        return NO_ERROR;
+    }
+
+    // make one pass through looking for commas so we know how big to make our
+    // out array.
+    int count = 1;
+    for (size_t i=0; i<len; i++) {
+        if (str[i] == ',') {
+            count++;
+        }
+    }
+
+    int* list = new int[count];
+    const char16_t* p = str;
+    int commaIndex = 0;
+    size_t i;
+
+    for (i=0; i<len; i++) {
+        if (str[i] == ',') {
+            err = func(p, (str+i-p), list+commaIndex, rangeMin,
+                    rangeMax, zeroOK);
+            if (err != NO_ERROR) {
+                goto bail;
+            }
+            commaIndex++;
+            p = str+i+1;
+        }
+    }
+
+    err = func(p, (str+i-p), list+commaIndex, rangeMin, rangeMax, zeroOK);
+    if (err != NO_ERROR) {
+        goto bail;
+    }
+    commaIndex++;
+
+    *countOut = count;
+    *listOut = list;
+
+    return NO_ERROR;
+
+bail:
+    delete[] list;
+    FAIL_HERE();
+}
+
+// the numbers here are small, so we pack them both into one value, and then
+// split it out later.  it lets us reuse all the comma separated list code.
+static status_t
+parse_byday(const char16_t* s, size_t len, int* out,
+            int rangeMin, int rangeMax, bool zeroOK)
+{
+    status_t err;
+    int n = 0;
+    const char16_t* p = s;
+    size_t plen = len;
+
+    if (len > 0) {
+        char16_t c = s[0];
+        if (c == '-' || c == '+' || (c >= '0' && c <= '9')) {
+            if (len > 1) {
+                size_t nlen = 0;
+                c = s[nlen];
+                while (nlen < len
+                        && (c == '-' || c == '+' || (c >= '0' && c <= '9'))) {
+                    c = s[nlen];
+                    nlen++;
+                }
+                if (nlen > 0) {
+                    nlen--;
+                    err = parse_int(s, nlen, &n, rangeMin, rangeMax, zeroOK);
+                    if (err != NO_ERROR) {
+                        FAIL_HERE();
+                    }
+                    p += nlen;
+                    plen -= nlen;
+                }
+            }
+        }
+
+        int index = match_proc(WEEKDAYPROC, p, plen);
+        if (index >= 0) {
+            *out = (0xffff0000 & WEEKDAYPROC[index].value)
+                    | (0x0000ffff & n);
+            return NO_ERROR;
+        }
+    }
+    return UNKNOWN_ERROR;
+}
+
+static void
+postprocess_byday(int count, int* byday, int** bydayNum)
+{
+    int* bdn = new int[count];
+    *bydayNum = bdn;
+    for (int i=0; i<count; i++) {
+        uint32_t v = byday[i];
+        int16_t num = v & 0x0000ffff;
+        byday[i] = v & 0xffff0000;  
+        // will sign extend:
+        bdn[i] = num;
+    }
+}
+
+#define PARSE_INT_LIST_CHECKED(name, rangeMin, rangeMax, zeroOK) \
+    if (name##Count != 0 || NO_ERROR != parse_int_list(s, slen, \
+                         &name##Count, &name, rangeMin, rangeMax, zeroOK)) { \
+        FAIL_HERE(); \
+    }
+status_t
+EventRecurrence::parse(const String16& str)
+{
+    char16_t const* work = str.string();
+    size_t len = str.size();
+
+    int lhsIndex = NONE_LHS;
+    int index;
+    
+    size_t start = 0;
+    for (size_t i=0; i<len; i++) {
+        char16_t c = work[i];
+        if (c != ';' && i == len-1) {
+            c = ';';
+            i++;
+        }
+        if (c == ';' || c == '=') {
+            if (i != start) {
+                const char16_t* s = work+start;
+                const size_t slen = i-start;
+
+                String8 thestring(String16(s, slen));
+
+                switch (c)
+                {
+                    case '=':
+                        if (lhsIndex == NONE_LHS) {
+                            lhsIndex = match_proc(LHSPROC, s, slen);
+                            if (lhsIndex >= 0) {
+                                break;
+                            }
+                        }
+                        FAIL_HERE();
+                    case ';':
+                    {
+                        switch (LHSPROC[lhsIndex].value)
+                        {
+                            case FREQ:
+                                if (this->freq != 0) {
+                                    FAIL_HERE();
+                                }
+                                index = match_proc(FREQPROC, s, slen);
+                                if (index >= 0) {
+                                    this->freq = (freq_t)FREQPROC[index].value;
+                                }
+                                break;
+                            case UNTIL:
+                                // XXX should check that this is a valid time
+                                until.setTo(String16(s, slen));
+                                break;
+                            case COUNT:
+                                if (count != 0
+                                     || NO_ERROR != parse_int(s, slen,
+                                             &count, INT_MIN, INT_MAX, true)) {
+                                    FAIL_HERE();
+                                }
+                                break;
+                            case INTERVAL:
+                                if (interval != 0
+                                     || NO_ERROR != parse_int(s, slen,
+                                         &interval, INT_MIN, INT_MAX, false)) {
+                                    FAIL_HERE();
+                                }
+                                break;
+                            case BYSECOND:
+                                PARSE_INT_LIST_CHECKED(bysecond, 0, 59, true)
+                                break;
+                            case BYMINUTE:
+                                PARSE_INT_LIST_CHECKED(byminute, 0, 59, true)
+                                break;
+                            case BYHOUR:
+                                PARSE_INT_LIST_CHECKED(byhour, 0, 23, true)
+                                break;
+                            case BYDAY:
+                                if (bydayCount != 0 || NO_ERROR != 
+                                        parse_int_list(s, slen, &bydayCount,
+                                              &byday, -53, 53, false,
+                                              parse_byday)) {
+                                    FAIL_HERE();
+                                }
+                                postprocess_byday(bydayCount, byday, &bydayNum);
+                                break;
+                            case BYMONTHDAY:
+                                PARSE_INT_LIST_CHECKED(bymonthday, -31, 31,
+                                                        false)
+                                break;
+                            case BYYEARDAY:
+                                PARSE_INT_LIST_CHECKED(byyearday, -366, 366,
+                                                        false)
+                                break;
+                            case BYWEEKNO:
+                                PARSE_INT_LIST_CHECKED(byweekno, -53, 53,
+                                                        false)
+                                break;
+                            case BYMONTH:
+                                PARSE_INT_LIST_CHECKED(bymonth, 1, 12, false)
+                                break;
+                            case BYSETPOS:
+                                PARSE_INT_LIST_CHECKED(bysetpos,
+                                                        INT_MIN, INT_MAX, true)
+                                break;
+                            case WKST:
+                                if (this->wkst != 0) {
+                                    FAIL_HERE();
+                                }
+                                index = match_proc(WEEKDAYPROC, s, slen);
+                                if (index >= 0) {
+                                    this->wkst = (int)WEEKDAYPROC[index].value;
+                                }
+                                break;
+                            default:
+                                FAIL_HERE();
+                        }
+                        lhsIndex = NONE_LHS;
+                        break;
+                    }
+                }
+
+                start = i+1;
+            }
+        }
+    }
+
+    // enforce that there was a FREQ
+    if (freq == 0) {
+        FAIL_HERE();
+    }
+
+    // default wkst to MO if it wasn't specified
+    if (wkst == 0) {
+        wkst = MO;
+    }
+
+    return NO_ERROR;
+}
+
+
+}; // namespace android
+
+
diff --git a/libs/ui/ICamera.cpp b/libs/ui/ICamera.cpp
new file mode 100644
index 0000000..ab0fef1
--- /dev/null
+++ b/libs/ui/ICamera.cpp
@@ -0,0 +1,346 @@
+/*
+**
+** Copyright 2008, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ICamera"
+#include <utils/Log.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <utils/Parcel.h>
+#include <ui/ICamera.h>
+
+namespace android {
+
+enum {
+    DISCONNECT = IBinder::FIRST_CALL_TRANSACTION,
+    SET_PREVIEW_DISPLAY,
+    SET_PREVIEW_CALLBACK_FLAG,
+    START_PREVIEW,
+    STOP_PREVIEW,
+    AUTO_FOCUS,
+    TAKE_PICTURE,
+    SET_PARAMETERS,
+    GET_PARAMETERS,
+    CONNECT,
+    LOCK,
+    UNLOCK,
+    PREVIEW_ENABLED,
+    START_RECORDING,
+    STOP_RECORDING,
+    RECORDING_ENABLED,
+    RELEASE_RECORDING_FRAME,
+};
+
+class BpCamera: public BpInterface<ICamera>
+{
+public:
+    BpCamera(const sp<IBinder>& impl)
+        : BpInterface<ICamera>(impl)
+    {
+    }
+
+    // disconnect from camera service
+    void disconnect()
+    {
+        LOGV("disconnect");
+        Parcel data, reply;
+        data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
+        remote()->transact(DISCONNECT, data, &reply);
+    }
+
+    // pass the buffered ISurface to the camera service
+    status_t setPreviewDisplay(const sp<ISurface>& surface)
+    {
+        LOGV("setPreviewDisplay");
+        Parcel data, reply;
+        data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
+        data.writeStrongBinder(surface->asBinder());
+        remote()->transact(SET_PREVIEW_DISPLAY, data, &reply);
+        return reply.readInt32();
+    }
+
+    // set the preview callback flag to affect how the received frames from
+    // preview are handled. See Camera.h for details.
+    void setPreviewCallbackFlag(int flag)
+    {
+        LOGV("setPreviewCallbackFlag(%d)", flag);
+        Parcel data, reply;
+        data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
+        data.writeInt32(flag);
+        remote()->transact(SET_PREVIEW_CALLBACK_FLAG, data, &reply);
+    }
+
+    // start preview mode, must call setPreviewDisplay first
+    status_t startPreview()
+    {
+        LOGV("startPreview");
+        Parcel data, reply;
+        data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
+        remote()->transact(START_PREVIEW, data, &reply);
+        return reply.readInt32();
+    }
+
+    // start recording mode, must call setPreviewDisplay first
+    status_t startRecording()
+    {
+        LOGV("startRecording");
+        Parcel data, reply;
+        data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
+        remote()->transact(START_RECORDING, data, &reply);
+        return reply.readInt32();
+    }
+
+    // stop preview mode
+    void stopPreview()
+    {
+        LOGV("stopPreview");
+        Parcel data, reply;
+        data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
+        remote()->transact(STOP_PREVIEW, data, &reply);
+    }
+
+    // stop recording mode
+    void stopRecording()
+    {
+        LOGV("stopRecording");
+        Parcel data, reply;
+        data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
+        remote()->transact(STOP_RECORDING, data, &reply);
+    }
+
+    void releaseRecordingFrame(const sp<IMemory>& mem)
+    {
+        LOGV("releaseRecordingFrame");
+        Parcel data, reply;
+        data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
+        data.writeStrongBinder(mem->asBinder());
+        remote()->transact(RELEASE_RECORDING_FRAME, data, &reply);
+    }
+
+    // check preview state
+    bool previewEnabled()
+    {
+        LOGV("previewEnabled");
+        Parcel data, reply;
+        data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
+        remote()->transact(PREVIEW_ENABLED, data, &reply);
+        return reply.readInt32();
+    }
+
+    // check recording state
+    bool recordingEnabled()
+    {
+        LOGV("recordingEnabled");
+        Parcel data, reply;
+        data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
+        remote()->transact(RECORDING_ENABLED, data, &reply);
+        return reply.readInt32();
+    }
+
+    // auto focus
+    status_t autoFocus()
+    {
+        LOGV("autoFocus");
+        Parcel data, reply;
+        data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
+        remote()->transact(AUTO_FOCUS, data, &reply);
+        status_t ret = reply.readInt32();
+        return ret;
+    }
+
+    // take a picture - returns an IMemory (ref-counted mmap)
+    status_t takePicture()
+    {
+        LOGV("takePicture");
+        Parcel data, reply;
+        data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
+        remote()->transact(TAKE_PICTURE, data, &reply);
+        status_t ret = reply.readInt32();
+        return ret;
+    }
+
+    // set preview/capture parameters - key/value pairs
+    status_t setParameters(const String8& params)
+    {
+        LOGV("setParameters");
+        Parcel data, reply;
+        data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
+        data.writeString8(params);
+        remote()->transact(SET_PARAMETERS, data, &reply);
+        return reply.readInt32();
+    }
+
+    // get preview/capture parameters - key/value pairs
+    String8 getParameters() const
+    {
+        LOGV("getParameters");
+        Parcel data, reply;
+        data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
+        remote()->transact(GET_PARAMETERS, data, &reply);
+        return reply.readString8();
+    }
+    virtual status_t connect(const sp<ICameraClient>& cameraClient)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
+        data.writeStrongBinder(cameraClient->asBinder());
+        remote()->transact(CONNECT, data, &reply);
+        return reply.readInt32();
+    }
+    virtual status_t lock()
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
+        remote()->transact(LOCK, data, &reply);
+        return reply.readInt32();
+    }
+    virtual status_t unlock()
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
+        remote()->transact(UNLOCK, data, &reply);
+        return reply.readInt32();
+    }
+};
+
+IMPLEMENT_META_INTERFACE(Camera, "android.hardware.ICamera");
+
+// ----------------------------------------------------------------------
+
+#define CHECK_INTERFACE(interface, data, reply) \
+        do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \
+            LOGW("Call incorrectly routed to " #interface); \
+            return PERMISSION_DENIED; \
+        } } while (0)
+
+status_t BnCamera::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    switch(code) {
+        case DISCONNECT: {
+            LOGV("DISCONNECT");
+            CHECK_INTERFACE(ICamera, data, reply);
+            disconnect();
+            return NO_ERROR;
+        } break;
+        case SET_PREVIEW_DISPLAY: {
+            LOGV("SET_PREVIEW_DISPLAY");
+            CHECK_INTERFACE(ICamera, data, reply);
+            sp<ISurface> surface = interface_cast<ISurface>(data.readStrongBinder());
+            reply->writeInt32(setPreviewDisplay(surface));
+            return NO_ERROR;
+        } break;
+        case SET_PREVIEW_CALLBACK_FLAG: {
+            LOGV("SET_PREVIEW_CALLBACK_TYPE");
+            CHECK_INTERFACE(ICamera, data, reply);
+            int callback_flag = data.readInt32();
+            setPreviewCallbackFlag(callback_flag);
+            return NO_ERROR;
+        } break;
+        case START_PREVIEW: {
+            LOGV("START_PREVIEW");
+            CHECK_INTERFACE(ICamera, data, reply);
+            reply->writeInt32(startPreview());
+            return NO_ERROR;
+        } break;
+        case START_RECORDING: {
+            LOGV("START_RECORDING");
+            CHECK_INTERFACE(ICamera, data, reply);
+            reply->writeInt32(startRecording());
+            return NO_ERROR;
+        } break;
+        case STOP_PREVIEW: {
+            LOGV("STOP_PREVIEW");
+            CHECK_INTERFACE(ICamera, data, reply);
+            stopPreview();
+            return NO_ERROR;
+        } break;
+        case STOP_RECORDING: {
+            LOGV("STOP_RECORDING");
+            CHECK_INTERFACE(ICamera, data, reply);
+            stopRecording();
+            return NO_ERROR;
+        } break;
+        case RELEASE_RECORDING_FRAME: {
+            LOGV("RELEASE_RECORDING_FRAME");
+            CHECK_INTERFACE(ICamera, data, reply);
+            sp<IMemory> mem = interface_cast<IMemory>(data.readStrongBinder());
+            releaseRecordingFrame(mem);
+            return NO_ERROR;
+        } break;
+        case PREVIEW_ENABLED: {
+            LOGV("PREVIEW_ENABLED");
+            CHECK_INTERFACE(ICamera, data, reply);
+            reply->writeInt32(previewEnabled());
+            return NO_ERROR;
+        } break;
+        case RECORDING_ENABLED: {
+            LOGV("RECORDING_ENABLED");
+            CHECK_INTERFACE(ICamera, data, reply);
+            reply->writeInt32(recordingEnabled());
+            return NO_ERROR;
+        } break;
+        case AUTO_FOCUS: {
+            LOGV("AUTO_FOCUS");
+            CHECK_INTERFACE(ICamera, data, reply);
+            reply->writeInt32(autoFocus());
+            return NO_ERROR;
+        } break;
+        case TAKE_PICTURE: {
+            LOGV("TAKE_PICTURE");
+            CHECK_INTERFACE(ICamera, data, reply);
+            reply->writeInt32(takePicture());
+            return NO_ERROR;
+        } break;
+        case SET_PARAMETERS: {
+            LOGV("SET_PARAMETERS");
+            CHECK_INTERFACE(ICamera, data, reply);
+            String8 params(data.readString8());
+            reply->writeInt32(setParameters(params));
+            return NO_ERROR;
+         } break;
+        case GET_PARAMETERS: {
+            LOGV("GET_PARAMETERS");
+            CHECK_INTERFACE(ICamera, data, reply);
+             reply->writeString8(getParameters());
+            return NO_ERROR;
+         } break;
+        case CONNECT: {
+            CHECK_INTERFACE(ICamera, data, reply);
+            sp<ICameraClient> cameraClient = interface_cast<ICameraClient>(data.readStrongBinder());
+            reply->writeInt32(connect(cameraClient));
+            return NO_ERROR;
+        } break;
+        case LOCK: {
+            CHECK_INTERFACE(ICamera, data, reply);
+            reply->writeInt32(lock());
+            return NO_ERROR;
+        } break;
+        case UNLOCK: {
+            CHECK_INTERFACE(ICamera, data, reply);
+            reply->writeInt32(unlock());
+            return NO_ERROR;
+        } break;
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
diff --git a/libs/ui/ICameraClient.cpp b/libs/ui/ICameraClient.cpp
new file mode 100644
index 0000000..4bec9d2
--- /dev/null
+++ b/libs/ui/ICameraClient.cpp
@@ -0,0 +1,185 @@
+/*
+**
+** Copyright 2008, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License"); 
+** you may not use this file except in compliance with the License. 
+** You may obtain a copy of the License at 
+**
+**     http://www.apache.org/licenses/LICENSE-2.0 
+**
+** Unless required by applicable law or agreed to in writing, software 
+** distributed under the License is distributed on an "AS IS" BASIS, 
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+** See the License for the specific language governing permissions and 
+** limitations under the License.
+*/
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ICameraClient"
+#include <utils/Log.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <ui/ICameraClient.h>
+
+namespace android {
+
+enum {
+    SHUTTER_CALLBACK = IBinder::FIRST_CALL_TRANSACTION,
+    RAW_CALLBACK,
+    JPEG_CALLBACK,
+    PREVIEW_CALLBACK,
+    ERROR_CALLBACK,
+    AUTOFOCUS_CALLBACK,
+    RECORDING_CALLBACK,
+};
+
+class BpCameraClient: public BpInterface<ICameraClient>
+{
+public:
+    BpCameraClient(const sp<IBinder>& impl)
+        : BpInterface<ICameraClient>(impl)
+    {
+    }
+
+    // callback to let the app know the shutter has closed, ideal for playing the shutter sound
+    void shutterCallback()
+    {
+        LOGV("shutterCallback");
+        Parcel data, reply;
+        data.writeInterfaceToken(ICameraClient::getInterfaceDescriptor());
+        remote()->transact(SHUTTER_CALLBACK, data, &reply, IBinder::FLAG_ONEWAY);
+    }
+
+    // callback from camera service to app with picture data
+    void rawCallback(const sp<IMemory>& picture)
+    {
+        LOGV("rawCallback");
+        Parcel data, reply;
+        data.writeInterfaceToken(ICameraClient::getInterfaceDescriptor());
+        data.writeStrongBinder(picture->asBinder());
+        remote()->transact(RAW_CALLBACK, data, &reply, IBinder::FLAG_ONEWAY);
+    }
+
+    // callback from camera service to app with picture data
+    void jpegCallback(const sp<IMemory>& picture)
+    {
+        LOGV("jpegCallback");
+        Parcel data, reply;
+        data.writeInterfaceToken(ICameraClient::getInterfaceDescriptor());
+        data.writeStrongBinder(picture->asBinder());
+        remote()->transact(JPEG_CALLBACK, data, &reply, IBinder::FLAG_ONEWAY);
+    }
+
+    // callback from camera service to app with preview frame data
+    void previewCallback(const sp<IMemory>& frame)
+    {
+        LOGV("previewCallback");
+        Parcel data, reply;
+        data.writeInterfaceToken(ICameraClient::getInterfaceDescriptor());
+        data.writeStrongBinder(frame->asBinder());
+        remote()->transact(PREVIEW_CALLBACK, data, &reply, IBinder::FLAG_ONEWAY);
+    }
+
+    // callback from camera service to app with recording frame data
+    void recordingCallback(const sp<IMemory>& frame)
+    {
+        LOGV("recordingCallback");
+        Parcel data, reply;
+        data.writeInterfaceToken(ICameraClient::getInterfaceDescriptor());
+        data.writeStrongBinder(frame->asBinder());
+        remote()->transact(RECORDING_CALLBACK, data, &reply, IBinder::FLAG_ONEWAY);
+    }
+
+    // callback from camera service to app to report error
+    void errorCallback(status_t error)
+    {
+        LOGV("errorCallback");
+        Parcel data, reply;
+        data.writeInterfaceToken(ICameraClient::getInterfaceDescriptor());
+        data.writeInt32(error);
+        remote()->transact(ERROR_CALLBACK, data, &reply, IBinder::FLAG_ONEWAY);
+    }
+
+    // callback from camera service to app to report autofocus completion
+    void autoFocusCallback(bool focused)
+    {
+        LOGV("autoFocusCallback");
+        Parcel data, reply;
+        data.writeInterfaceToken(ICameraClient::getInterfaceDescriptor());
+        data.writeInt32(focused);
+        remote()->transact(AUTOFOCUS_CALLBACK, data, &reply, IBinder::FLAG_ONEWAY);
+    }
+};
+
+IMPLEMENT_META_INTERFACE(CameraClient, "android.hardware.ICameraClient");
+
+// ----------------------------------------------------------------------
+
+#define CHECK_INTERFACE(interface, data, reply) \
+        do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \
+            LOGW("Call incorrectly routed to " #interface); \
+            return PERMISSION_DENIED; \
+        } } while (0)
+
+status_t BnCameraClient::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    switch(code) {
+        case SHUTTER_CALLBACK: {
+            LOGV("SHUTTER_CALLBACK");
+            CHECK_INTERFACE(ICameraClient, data, reply);
+            shutterCallback();
+            return NO_ERROR;
+        } break;
+        case RAW_CALLBACK: {
+            LOGV("RAW_CALLBACK");
+            CHECK_INTERFACE(ICameraClient, data, reply);
+            sp<IMemory> picture = interface_cast<IMemory>(data.readStrongBinder());
+            rawCallback(picture);
+            return NO_ERROR;
+        } break;
+        case JPEG_CALLBACK: {
+            LOGV("JPEG_CALLBACK");
+            CHECK_INTERFACE(ICameraClient, data, reply);
+            sp<IMemory> picture = interface_cast<IMemory>(data.readStrongBinder());
+            jpegCallback(picture);
+            return NO_ERROR;
+        } break;
+        case PREVIEW_CALLBACK: {
+            LOGV("PREVIEW_CALLBACK");
+            CHECK_INTERFACE(ICameraClient, data, reply);
+            sp<IMemory> frame = interface_cast<IMemory>(data.readStrongBinder());
+            previewCallback(frame);
+            return NO_ERROR;
+        } break;
+        case RECORDING_CALLBACK: {
+            LOGV("RECORDING_CALLBACK");
+            CHECK_INTERFACE(ICameraClient, data, reply);
+            sp<IMemory> frame = interface_cast<IMemory>(data.readStrongBinder());
+            recordingCallback(frame);
+            return NO_ERROR;
+        } break;
+        case ERROR_CALLBACK: {
+            LOGV("ERROR_CALLBACK");
+            CHECK_INTERFACE(ICameraClient, data, reply);
+            status_t error = data.readInt32();
+            errorCallback(error);
+            return NO_ERROR;
+        } break;
+        case AUTOFOCUS_CALLBACK: {
+            LOGV("AUTOFOCUS_CALLBACK");
+            CHECK_INTERFACE(ICameraClient, data, reply);
+            bool focused = (bool)data.readInt32();
+            autoFocusCallback(focused);
+            return NO_ERROR;
+        } break;
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
diff --git a/libs/ui/ICameraService.cpp b/libs/ui/ICameraService.cpp
new file mode 100644
index 0000000..e5687fe
--- /dev/null
+++ b/libs/ui/ICameraService.cpp
@@ -0,0 +1,77 @@
+/*
+**
+** Copyright 2008, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License"); 
+** you may not use this file except in compliance with the License. 
+** You may obtain a copy of the License at 
+**
+**     http://www.apache.org/licenses/LICENSE-2.0 
+**
+** Unless required by applicable law or agreed to in writing, software 
+** distributed under the License is distributed on an "AS IS" BASIS, 
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+** See the License for the specific language governing permissions and 
+** limitations under the License.
+*/
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Parcel.h>
+#include <utils/IPCThreadState.h>
+#include <utils/IServiceManager.h>
+
+#include <ui/ICameraService.h>
+
+namespace android {
+
+class BpCameraService: public BpInterface<ICameraService>
+{
+public:
+    BpCameraService(const sp<IBinder>& impl)
+        : BpInterface<ICameraService>(impl)
+    {
+    }
+
+    // connect to camera service
+    virtual sp<ICamera> connect(const sp<ICameraClient>& cameraClient)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
+        data.writeStrongBinder(cameraClient->asBinder());
+        remote()->transact(BnCameraService::CONNECT, data, &reply);
+        return interface_cast<ICamera>(reply.readStrongBinder());
+    }
+};
+
+IMPLEMENT_META_INTERFACE(CameraService, "android.hardware.ICameraService");
+
+// ----------------------------------------------------------------------
+
+#define CHECK_INTERFACE(interface, data, reply) \
+        do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \
+            LOGW("Call incorrectly routed to " #interface); \
+            return PERMISSION_DENIED; \
+        } } while (0)
+
+status_t BnCameraService::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    switch(code) {
+        case CONNECT: {
+            CHECK_INTERFACE(ICameraService, data, reply);
+            sp<ICameraClient> cameraClient = interface_cast<ICameraClient>(data.readStrongBinder());
+            sp<ICamera> camera = connect(cameraClient);
+            reply->writeStrongBinder(camera->asBinder());
+            return NO_ERROR;
+        } break;
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
diff --git a/libs/ui/IOverlay.cpp b/libs/ui/IOverlay.cpp
new file mode 100644
index 0000000..fed47c2
--- /dev/null
+++ b/libs/ui/IOverlay.cpp
@@ -0,0 +1,72 @@
+/*
+ * 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 <stdio.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Parcel.h>
+#include <utils/IInterface.h>
+
+#include <ui/IOverlay.h>
+
+namespace android {
+
+enum {
+    DESTROY = IBinder::FIRST_CALL_TRANSACTION, // one-way transaction
+};
+
+class BpOverlay : public BpInterface<IOverlay>
+{
+public:
+    BpOverlay(const sp<IBinder>& impl)
+        : BpInterface<IOverlay>(impl)
+    {
+    }
+
+    virtual void destroy()
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IOverlay::getInterfaceDescriptor());
+        remote()->transact(DESTROY, data, &reply, IBinder::FLAG_ONEWAY);
+    }
+};
+
+IMPLEMENT_META_INTERFACE(Overlay, "android.ui.IOverlay");
+
+// ----------------------------------------------------------------------
+
+#define CHECK_INTERFACE(interface, data, reply) \
+        do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \
+            LOGW("Call incorrectly routed to " #interface); \
+            return PERMISSION_DENIED; \
+        } } while (0)
+
+status_t BnOverlay::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    switch(code) {
+        case DESTROY: {
+            CHECK_INTERFACE(IOverlay, data, reply);
+            destroy();
+            return NO_ERROR;
+        } break;
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+}; // namespace android
diff --git a/libs/ui/ISurface.cpp b/libs/ui/ISurface.cpp
new file mode 100644
index 0000000..d5e9f81
--- /dev/null
+++ b/libs/ui/ISurface.cpp
@@ -0,0 +1,164 @@
+/*
+ * 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 <stdio.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Parcel.h>
+#include <utils/IMemory.h>
+
+#include <ui/ISurface.h>
+#include <ui/Overlay.h>
+
+
+namespace android {
+
+ISurface::BufferHeap::BufferHeap() 
+    : w(0), h(0), hor_stride(0), ver_stride(0), format(0),
+    transform(0), flags(0) 
+{     
+}
+
+ISurface::BufferHeap::BufferHeap(uint32_t w, uint32_t h,
+        int32_t hor_stride, int32_t ver_stride,
+        PixelFormat format, const sp<IMemoryHeap>& heap)
+    : w(w), h(h), hor_stride(hor_stride), ver_stride(ver_stride),
+      format(format), transform(0), flags(0), heap(heap) 
+{
+}
+
+ISurface::BufferHeap::BufferHeap(uint32_t w, uint32_t h,
+        int32_t hor_stride, int32_t ver_stride,
+        PixelFormat format, uint32_t transform, uint32_t flags,
+        const sp<IMemoryHeap>& heap)
+        : w(w), h(h), hor_stride(hor_stride), ver_stride(ver_stride),
+          format(format), transform(transform), flags(flags), heap(heap) 
+{
+}
+
+
+ISurface::BufferHeap::~BufferHeap() 
+{     
+}
+
+class BpSurface : public BpInterface<ISurface>
+{
+public:
+    BpSurface(const sp<IBinder>& impl)
+        : BpInterface<ISurface>(impl)
+    {
+    }
+
+    virtual status_t registerBuffers(const BufferHeap& buffers)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurface::getInterfaceDescriptor());
+        data.writeInt32(buffers.w);
+        data.writeInt32(buffers.h);
+        data.writeInt32(buffers.hor_stride);
+        data.writeInt32(buffers.ver_stride);
+        data.writeInt32(buffers.format);
+        data.writeInt32(buffers.transform);
+        data.writeInt32(buffers.flags);
+        data.writeStrongBinder(buffers.heap->asBinder());
+        remote()->transact(REGISTER_BUFFERS, data, &reply);
+        status_t result = reply.readInt32();
+        return result;
+    }
+
+    virtual void postBuffer(ssize_t offset)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurface::getInterfaceDescriptor());
+        data.writeInt32(offset);
+        remote()->transact(POST_BUFFER, data, &reply, IBinder::FLAG_ONEWAY);
+    }
+
+    virtual void unregisterBuffers()
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurface::getInterfaceDescriptor());
+        remote()->transact(UNREGISTER_BUFFERS, data, &reply);
+    }
+
+    virtual sp<OverlayRef> createOverlay(
+             uint32_t w, uint32_t h, int32_t format)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurface::getInterfaceDescriptor());
+        data.writeInt32(w);
+        data.writeInt32(h);
+        data.writeInt32(format);
+        remote()->transact(CREATE_OVERLAY, data, &reply);
+        return OverlayRef::readFromParcel(reply);
+    }
+};
+
+IMPLEMENT_META_INTERFACE(Surface, "android.ui.ISurface");
+
+// ----------------------------------------------------------------------
+
+#define CHECK_INTERFACE(interface, data, reply) \
+        do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \
+            LOGW("Call incorrectly routed to " #interface); \
+            return PERMISSION_DENIED; \
+        } } while (0)
+
+status_t BnSurface::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    switch(code) {
+        case REGISTER_BUFFERS: {
+            CHECK_INTERFACE(ISurface, data, reply);
+            BufferHeap buffer;
+            buffer.w = data.readInt32();
+            buffer.h = data.readInt32();
+            buffer.hor_stride = data.readInt32();
+            buffer.ver_stride= data.readInt32();
+            buffer.format = data.readInt32();
+            buffer.transform = data.readInt32();
+            buffer.flags = data.readInt32();
+            buffer.heap = interface_cast<IMemoryHeap>(data.readStrongBinder());
+            status_t err = registerBuffers(buffer);
+            reply->writeInt32(err);
+            return NO_ERROR;
+        } break;
+        case UNREGISTER_BUFFERS: {
+            CHECK_INTERFACE(ISurface, data, reply);
+            unregisterBuffers();
+            return NO_ERROR;
+        } break;
+        case POST_BUFFER: {
+            CHECK_INTERFACE(ISurface, data, reply);
+            ssize_t offset = data.readInt32();
+            postBuffer(offset);
+            return NO_ERROR;
+        } break;
+        case CREATE_OVERLAY: {
+            CHECK_INTERFACE(ISurface, data, reply);
+            int w = data.readInt32();
+            int h = data.readInt32();
+            int f = data.readInt32();
+            sp<OverlayRef> o = createOverlay(w, h, f);
+            return OverlayRef::writeToParcel(reply, o);
+        } break;
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+}; // namespace android
diff --git a/libs/ui/ISurfaceComposer.cpp b/libs/ui/ISurfaceComposer.cpp
new file mode 100644
index 0000000..0fea6f9
--- /dev/null
+++ b/libs/ui/ISurfaceComposer.cpp
@@ -0,0 +1,277 @@
+/*
+ * 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.
+ */
+
+// tag as surfaceflinger
+#define LOG_TAG "SurfaceFlinger"
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Parcel.h>
+#include <utils/IMemory.h>
+#include <utils/IPCThreadState.h>
+#include <utils/IServiceManager.h>
+
+#include <ui/ISurfaceComposer.h>
+#include <ui/DisplayInfo.h>
+
+// ---------------------------------------------------------------------------
+
+#define LIKELY( exp )       (__builtin_expect( (exp) != 0, true  ))
+#define UNLIKELY( exp )     (__builtin_expect( (exp) != 0, false ))
+
+// ---------------------------------------------------------------------------
+
+namespace android {
+
+class BpSurfaceComposer : public BpInterface<ISurfaceComposer>
+{
+public:
+    BpSurfaceComposer(const sp<IBinder>& impl)
+        : BpInterface<ISurfaceComposer>(impl)
+    {
+    }
+
+    virtual sp<ISurfaceFlingerClient> createConnection()
+    {
+        uint32_t n;
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+        remote()->transact(BnSurfaceComposer::CREATE_CONNECTION, data, &reply);
+        return interface_cast<ISurfaceFlingerClient>(reply.readStrongBinder());
+    }
+
+    virtual sp<IMemory> getCblk() const
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+        remote()->transact(BnSurfaceComposer::GET_CBLK, data, &reply);
+        return interface_cast<IMemory>(reply.readStrongBinder());
+    }
+
+    virtual void openGlobalTransaction()
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+        remote()->transact(BnSurfaceComposer::OPEN_GLOBAL_TRANSACTION, data, &reply);
+    }
+
+    virtual void closeGlobalTransaction()
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+        remote()->transact(BnSurfaceComposer::CLOSE_GLOBAL_TRANSACTION, data, &reply);
+    }
+
+    virtual status_t freezeDisplay(DisplayID dpy, uint32_t flags)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+        data.writeInt32(dpy);
+        data.writeInt32(flags);
+        remote()->transact(BnSurfaceComposer::FREEZE_DISPLAY, data, &reply);
+        return reply.readInt32();
+    }
+
+    virtual status_t unfreezeDisplay(DisplayID dpy, uint32_t flags)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+        data.writeInt32(dpy);
+        data.writeInt32(flags);
+        remote()->transact(BnSurfaceComposer::UNFREEZE_DISPLAY, data, &reply);
+        return reply.readInt32();
+    }
+
+    virtual int setOrientation(DisplayID dpy, int orientation)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+        data.writeInt32(dpy);
+        data.writeInt32(orientation);
+        remote()->transact(BnSurfaceComposer::SET_ORIENTATION, data, &reply);
+        return reply.readInt32();
+    }
+
+    virtual void bootFinished()
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+        remote()->transact(BnSurfaceComposer::BOOT_FINISHED, data, &reply);
+    }
+
+    virtual status_t requestGPU(
+            const sp<IGPUCallback>& callback, gpu_info_t* gpu)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+        data.writeStrongBinder(callback->asBinder());
+        remote()->transact(BnSurfaceComposer::REQUEST_GPU, data, &reply);
+        gpu->regs = interface_cast<IMemory>(reply.readStrongBinder());
+        gpu->count = reply.readInt32();
+
+        // FIXME: for now, we don't dynamically allocate the regions array
+        size_t maxCount = sizeof(gpu->regions)/sizeof(*gpu->regions);
+        if (gpu->count > maxCount)
+            return BAD_VALUE;
+
+        for (size_t i=0 ; i<gpu->count ; i++) {
+            gpu->regions[i].region = interface_cast<IMemory>(reply.readStrongBinder());
+            gpu->regions[i].reserved = reply.readInt32();
+        }
+        return reply.readInt32();
+    }
+
+    virtual status_t revokeGPU()
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+        remote()->transact(BnSurfaceComposer::REVOKE_GPU, data, &reply);
+        return reply.readInt32();
+    }
+
+    virtual void signal() const
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+        remote()->transact(BnSurfaceComposer::SIGNAL, data, &reply, IBinder::FLAG_ONEWAY);
+    }
+};
+
+IMPLEMENT_META_INTERFACE(SurfaceComposer, "android.ui.ISurfaceComposer");
+
+// ----------------------------------------------------------------------
+
+#define CHECK_INTERFACE(interface, data, reply) \
+        do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \
+            LOGW("Call incorrectly routed to " #interface); \
+            return PERMISSION_DENIED; \
+        } } while (0)
+
+status_t BnSurfaceComposer::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    status_t err = BnInterface<ISurfaceComposer>::onTransact(code, data, reply, flags);
+    if (err == NO_ERROR)
+        return err;
+
+    CHECK_INTERFACE(ISurfaceComposer, data, reply);
+
+    switch(code) {
+        case CREATE_CONNECTION: {
+            sp<IBinder> b = createConnection()->asBinder();
+            reply->writeStrongBinder(b);
+        } break;
+        case OPEN_GLOBAL_TRANSACTION: {
+            openGlobalTransaction();
+        } break;
+        case CLOSE_GLOBAL_TRANSACTION: {
+            closeGlobalTransaction();
+        } break;
+        case SET_ORIENTATION: {
+            DisplayID dpy = data.readInt32();
+            int orientation = data.readInt32();
+            reply->writeInt32( setOrientation(dpy, orientation) );
+        } break;
+        case FREEZE_DISPLAY: {
+            DisplayID dpy = data.readInt32();
+            uint32_t flags = data.readInt32();
+            reply->writeInt32( freezeDisplay(dpy, flags) );
+        } break;
+        case UNFREEZE_DISPLAY: {
+            DisplayID dpy = data.readInt32();
+            uint32_t flags = data.readInt32();
+            reply->writeInt32( unfreezeDisplay(dpy, flags) );
+        } break;
+        case BOOT_FINISHED: {
+            bootFinished();
+        } break;
+        case REVOKE_GPU: {
+            reply->writeInt32( revokeGPU() );
+        } break;
+        case SIGNAL: {
+            signal();
+        } break;
+        case GET_CBLK: {
+            sp<IBinder> b = getCblk()->asBinder();
+            reply->writeStrongBinder(b);
+        } break;
+        case REQUEST_GPU: {
+            // TODO: this should be protected by a permission
+            gpu_info_t info;
+            sp<IGPUCallback> callback
+                = interface_cast<IGPUCallback>(data.readStrongBinder());
+            status_t res = requestGPU(callback, &info);
+
+            // FIXME: for now, we don't dynamically allocate the regions array
+            size_t maxCount = sizeof(info.regions)/sizeof(*info.regions);
+            if (info.count > maxCount)
+                return BAD_VALUE;
+
+            reply->writeStrongBinder(info.regs->asBinder());
+            reply->writeInt32(info.count);
+            for (size_t i=0 ; i<info.count ; i++) {
+                reply->writeStrongBinder(info.regions[i].region->asBinder());
+                reply->writeInt32(info.regions[i].reserved);
+            }
+            reply->writeInt32(res);
+        } break;
+        default:
+            return UNKNOWN_TRANSACTION;
+    }
+    return NO_ERROR;
+}
+
+// ----------------------------------------------------------------------------
+
+enum {
+    // Note: BOOT_FINISHED must remain this value, it is called by ActivityManagerService.
+    GPU_LOST = IBinder::FIRST_CALL_TRANSACTION
+};
+
+class BpGPUCallback : public BpInterface<IGPUCallback>
+{
+public:
+    BpGPUCallback(const sp<IBinder>& impl)
+        : BpInterface<IGPUCallback>(impl)
+    {
+    }
+
+    virtual void gpuLost()
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IGPUCallback::getInterfaceDescriptor());
+        remote()->transact(GPU_LOST, data, &reply, IBinder::FLAG_ONEWAY);
+    }
+};
+
+IMPLEMENT_META_INTERFACE(GPUCallback, "android.ui.IGPUCallback");
+
+status_t BnGPUCallback::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    switch(code) {
+        case GPU_LOST: {
+            CHECK_INTERFACE(IGPUCallback, data, reply);
+            gpuLost();
+            return NO_ERROR;
+        } break;
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+};
diff --git a/libs/ui/ISurfaceFlingerClient.cpp b/libs/ui/ISurfaceFlingerClient.cpp
new file mode 100644
index 0000000..dd6a798
--- /dev/null
+++ b/libs/ui/ISurfaceFlingerClient.cpp
@@ -0,0 +1,208 @@
+/*
+ * 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.
+ */
+
+// tag as surfaceflinger
+#define LOG_TAG "SurfaceFlinger"
+
+#include <stdio.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Parcel.h>
+#include <utils/IMemory.h>
+#include <utils/IPCThreadState.h>
+#include <utils/IServiceManager.h>
+
+#include <ui/ISurface.h>
+#include <ui/ISurfaceFlingerClient.h>
+#include <ui/Point.h>
+#include <ui/Rect.h>
+
+#include <private/ui/LayerState.h>
+
+// ---------------------------------------------------------------------------
+
+#define LIKELY( exp )       (__builtin_expect( (exp) != 0, true  ))
+#define UNLIKELY( exp )     (__builtin_expect( (exp) != 0, false ))
+
+// ---------------------------------------------------------------------------
+
+namespace android {
+
+enum {
+    GET_CBLK = IBinder::FIRST_CALL_TRANSACTION,
+    CREATE_SURFACE,
+    DESTROY_SURFACE,
+    SET_STATE
+};
+
+class BpSurfaceFlingerClient : public BpInterface<ISurfaceFlingerClient>
+{
+public:
+    BpSurfaceFlingerClient(const sp<IBinder>& impl)
+        : BpInterface<ISurfaceFlingerClient>(impl)
+    {
+    }
+
+    virtual void getControlBlocks(sp<IMemory>* ctl) const
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurfaceFlingerClient::getInterfaceDescriptor());
+        remote()->transact(GET_CBLK, data, &reply);
+        *ctl  = interface_cast<IMemory>(reply.readStrongBinder());
+    }
+
+    virtual sp<ISurface> createSurface( surface_data_t* params,
+                                        int pid,
+                                        DisplayID display,
+                                        uint32_t w,
+                                        uint32_t h,
+                                        PixelFormat format,
+                                        uint32_t flags)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurfaceFlingerClient::getInterfaceDescriptor());
+        data.writeInt32(pid);
+        data.writeInt32(display);
+        data.writeInt32(w);
+        data.writeInt32(h);
+        data.writeInt32(format);
+        data.writeInt32(flags);
+        remote()->transact(CREATE_SURFACE, data, &reply);
+        params->readFromParcel(reply);
+        return interface_cast<ISurface>(reply.readStrongBinder());
+    }
+                                    
+    virtual status_t destroySurface(SurfaceID sid)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurfaceFlingerClient::getInterfaceDescriptor());
+        data.writeInt32(sid);
+        remote()->transact(DESTROY_SURFACE, data, &reply);
+        return reply.readInt32();
+    }
+
+    virtual status_t setState(int32_t count, const layer_state_t* states)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurfaceFlingerClient::getInterfaceDescriptor());
+        data.writeInt32(count);
+        for (int i=0 ; i<count ; i++)
+            states[i].write(data);
+        remote()->transact(SET_STATE, data, &reply);
+        return reply.readInt32();
+    }
+};
+
+IMPLEMENT_META_INTERFACE(SurfaceFlingerClient, "android.ui.ISurfaceFlingerClient");
+
+// ----------------------------------------------------------------------
+
+#define CHECK_INTERFACE(interface, data, reply) \
+        do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \
+            LOGW("Call incorrectly routed to " #interface); \
+            return PERMISSION_DENIED; \
+        } } while (0)
+
+status_t BnSurfaceFlingerClient::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    // codes that don't require permission check
+
+    switch(code) {
+        case GET_CBLK: {
+            CHECK_INTERFACE(ISurfaceFlingerClient, data, reply);
+            sp<IMemory> ctl;
+            getControlBlocks(&ctl);
+            reply->writeStrongBinder(ctl->asBinder());
+            return NO_ERROR;
+        } break;
+    }
+
+    // these must be checked
+     
+     IPCThreadState* ipc = IPCThreadState::self();
+     const int pid = ipc->getCallingPid();
+     const int self_pid    = getpid();
+     if (UNLIKELY(pid != self_pid)) {
+         // we're called from a different process, do the real check
+         if (!checkCallingPermission(
+                 String16("android.permission.ACCESS_SURFACE_FLINGER")))
+         {
+             const int uid = ipc->getCallingUid();
+             LOGE("Permission Denial: "
+                     "can't openGlobalTransaction pid=%d, uid=%d", pid, uid);
+             return PERMISSION_DENIED;
+         }
+     }
+   
+     switch(code) {
+        case CREATE_SURFACE: {
+            CHECK_INTERFACE(ISurfaceFlingerClient, data, reply);
+            surface_data_t params;
+            int32_t pid = data.readInt32();
+            DisplayID display = data.readInt32();
+            uint32_t w = data.readInt32();
+            uint32_t h = data.readInt32();
+            PixelFormat format = data.readInt32();
+            uint32_t flags = data.readInt32();
+            sp<ISurface> s = createSurface(&params, pid, display, w, h, format, flags);
+            params.writeToParcel(reply);
+            reply->writeStrongBinder(s->asBinder());
+            return NO_ERROR;
+        } break;
+        case DESTROY_SURFACE: {
+            CHECK_INTERFACE(ISurfaceFlingerClient, data, reply);
+            reply->writeInt32( destroySurface( data.readInt32() ) );
+            return NO_ERROR;
+        } break;
+        case SET_STATE: {
+            CHECK_INTERFACE(ISurfaceFlingerClient, data, reply);
+            int32_t count = data.readInt32();
+            layer_state_t* states = new layer_state_t[count];
+            for (int i=0 ; i<count ; i++)
+                states[i].read(data);
+            status_t err = setState(count, states);
+            delete [] states;
+            reply->writeInt32(err);
+            return NO_ERROR;
+        } break;
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+// ----------------------------------------------------------------------
+
+status_t ISurfaceFlingerClient::surface_data_t::readFromParcel(const Parcel& parcel)
+{
+    token = parcel.readInt32();
+    identity  = parcel.readInt32();
+    heap[0] = interface_cast<IMemoryHeap>(parcel.readStrongBinder());
+    heap[1] = interface_cast<IMemoryHeap>(parcel.readStrongBinder());
+    return NO_ERROR;
+}
+
+status_t ISurfaceFlingerClient::surface_data_t::writeToParcel(Parcel* parcel) const
+{
+    parcel->writeInt32(token);
+    parcel->writeInt32(identity);
+    parcel->writeStrongBinder(heap[0]!=0 ? heap[0]->asBinder() : NULL);
+    parcel->writeStrongBinder(heap[1]!=0 ? heap[1]->asBinder() : NULL);
+    return NO_ERROR;
+}
+
+}; // namespace android
diff --git a/libs/ui/KeyCharacterMap.cpp b/libs/ui/KeyCharacterMap.cpp
new file mode 100644
index 0000000..e891181
--- /dev/null
+++ b/libs/ui/KeyCharacterMap.cpp
@@ -0,0 +1,263 @@
+#define LOG_TAG "KeyCharacterMap"
+
+#include <ui/KeyCharacterMap.h>
+#include <cutils/properties.h>
+
+#include <utils/Log.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <string.h>
+
+struct Header
+{
+    char magic[8];
+    unsigned int endian;
+    unsigned int version;
+    unsigned int keycount;
+    unsigned char kbdtype;
+    char padding[11];
+};
+
+KeyCharacterMap::KeyCharacterMap()
+{
+}
+
+KeyCharacterMap::~KeyCharacterMap()
+{
+    free(m_keys);
+}
+
+unsigned short
+KeyCharacterMap::get(int keycode, int meta)
+{
+    Key* k = find_key(keycode);
+    if (k != NULL) {
+        return k->data[meta & META_MASK];
+    }
+    return 0;
+}
+
+unsigned short
+KeyCharacterMap::getNumber(int keycode)
+{
+    Key* k = find_key(keycode);
+    if (k != NULL) {
+        return k->number;
+    }
+    return 0;
+}
+
+unsigned short
+KeyCharacterMap::getMatch(int keycode, const unsigned short* chars,
+                          int charsize, uint32_t modifiers)
+{
+    Key* k = find_key(keycode);
+    modifiers &= 3; // ignore the SYM key because we don't have keymap entries for it
+    if (k != NULL) {
+        const uint16_t* data = k->data;
+        for (int j=0; j<charsize; j++) {
+            uint16_t c = chars[j];
+            for (int i=0; i<(META_MASK + 1); i++) {
+                if ((modifiers == 0) || ((modifiers & i) != 0)) {
+                    if (c == data[i]) {
+                        return c;
+                    }
+                }
+            }
+        }
+    }
+    return 0;
+}
+
+unsigned short
+KeyCharacterMap::getDisplayLabel(int keycode)
+{
+    Key* k = find_key(keycode);
+    if (k != NULL) {
+        return k->display_label;
+    }
+    return 0;
+}
+
+bool
+KeyCharacterMap::getKeyData(int keycode, unsigned short *displayLabel,
+                            unsigned short *number, unsigned short* results)
+{
+    Key* k = find_key(keycode);
+    if (k != NULL) {
+        memcpy(results, k->data, sizeof(short)*(META_MASK + 1));
+        *number = k->number;
+        *displayLabel = k->display_label;
+        return true;
+    } else {
+        return false;
+    }
+}
+
+bool
+KeyCharacterMap::find_char(uint16_t c, uint32_t* key, uint32_t* mods)
+{
+    uint32_t N = m_keyCount;
+    for (int j=0; j<(META_MASK + 1); j++) {
+        Key const* keys = m_keys;
+        for (uint32_t i=0; i<N; i++) {
+            if (keys->data[j] == c) {
+                *key = keys->keycode;
+                *mods = j;
+                return true;
+            }
+            keys++;
+        }
+    }
+    return false;
+}
+
+bool
+KeyCharacterMap::getEvents(uint16_t* chars, size_t len,
+                           Vector<int32_t>* keys, Vector<uint32_t>* modifiers)
+{
+    for (size_t i=0; i<len; i++) {
+        uint32_t k, mods;
+        if (find_char(chars[i], &k, &mods)) {
+            keys->add(k);
+            modifiers->add(mods);
+        } else {
+            return false;
+        }
+    }
+    return true;
+}
+
+KeyCharacterMap::Key*
+KeyCharacterMap::find_key(int keycode)
+{
+    Key* keys = m_keys;
+    int low = 0;
+    int high = m_keyCount - 1;
+    int mid;
+    int n;
+    while (low <= high) {
+        mid = (low + high) / 2;
+        n = keys[mid].keycode;
+        if (keycode < n) {
+            high = mid - 1;
+        } else if (keycode > n) {
+            low = mid + 1;
+        } else {
+            return keys + mid;
+        }
+    }
+    return NULL;
+}
+
+KeyCharacterMap*
+KeyCharacterMap::load(int id)
+{
+    KeyCharacterMap* rv = NULL;
+    char path[PATH_MAX];
+    char propName[100];
+    char dev[PROPERTY_VALUE_MAX];
+    char tmpfn[PROPERTY_VALUE_MAX];
+    int err;
+    const char* root = getenv("ANDROID_ROOT");
+
+    sprintf(propName, "hw.keyboards.%u.devname", id);
+    err = property_get(propName, dev, "");
+    if (err > 0) {
+        // replace all the spaces with underscores
+        strcpy(tmpfn, dev);
+        for (char *p = strchr(tmpfn, ' '); p && *p; p = strchr(tmpfn, ' '))
+            *p = '_';
+        snprintf(path, sizeof(path), "%s/usr/keychars/%s.kcm.bin", root, tmpfn);
+        //LOGD("load: dev='%s' path='%s'\n", dev, path);
+        rv = try_file(path);
+        if (rv != NULL) {
+            return rv;
+        }
+        LOGW("Error loading keycharmap file '%s'. %s='%s'", path, propName, dev);
+    } else {
+        LOGW("No keyboard for id %d", id);
+    }
+
+    snprintf(path, sizeof(path), "%s/usr/keychars/qwerty.kcm.bin", root);
+    rv = try_file(path);
+    if (rv == NULL) {
+        LOGE("Can't find any keycharmaps (also tried %s)", path);
+        return NULL;
+    }
+    LOGW("Using default keymap: %s", path);
+
+    return rv;
+}
+
+KeyCharacterMap*
+KeyCharacterMap::try_file(const char* filename)
+{
+    KeyCharacterMap* rv = NULL;
+    Key* keys;
+    int fd;
+    off_t filesize;
+    Header header;
+    int err;
+    
+    fd = open(filename, O_RDONLY);
+    if (fd == -1) {
+        LOGW("Can't open keycharmap file");
+        return NULL;
+    }
+
+    filesize = lseek(fd, 0, SEEK_END);
+    lseek(fd, 0, SEEK_SET);
+
+    // validate the header
+    if (filesize <= (off_t)sizeof(header)) {
+        LOGW("Bad keycharmap - filesize=%d\n", (int)filesize);
+        goto cleanup1;
+    }
+
+    err = read(fd, &header, sizeof(header));
+    if (err == -1) {
+        LOGW("Error reading keycharmap file");
+        goto cleanup1;
+    }
+
+    if (0 != memcmp(header.magic, "keychar", 8)) {
+        LOGW("Bad keycharmap magic token");
+        goto cleanup1;
+    }
+    if (header.endian != 0x12345678) {
+        LOGW("Bad keycharmap endians");
+        goto cleanup1;
+    }
+    if ((header.version & 0xff) != 2) {
+        LOGW("Only support keycharmap version 2 (got 0x%08x)", header.version);
+        goto cleanup1;
+    }
+    if (filesize < (off_t)(sizeof(Header)+(sizeof(Key)*header.keycount))) {
+        LOGW("Bad keycharmap file size\n");
+        goto cleanup1;
+    }
+
+    // read the key data
+    keys = (Key*)malloc(sizeof(Key)*header.keycount);
+    err = read(fd, keys, sizeof(Key)*header.keycount);
+    if (err == -1) {
+        LOGW("Error reading keycharmap file");
+        free(keys);
+        goto cleanup1;
+    }
+
+    // return the object
+    rv = new KeyCharacterMap;
+    rv->m_keyCount = header.keycount;
+    rv->m_keys = keys;
+    rv->m_type = header.kbdtype;
+
+cleanup1:
+    close(fd);
+
+    return rv;
+}
diff --git a/libs/ui/KeyLayoutMap.cpp b/libs/ui/KeyLayoutMap.cpp
new file mode 100644
index 0000000..15ae54c
--- /dev/null
+++ b/libs/ui/KeyLayoutMap.cpp
@@ -0,0 +1,235 @@
+#define LOG_TAG "KeyLayoutMap"
+
+#include "KeyLayoutMap.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <utils/String8.h>
+#include <stdlib.h>
+#include <ui/KeycodeLabels.h>
+#include <utils/Log.h>
+
+namespace android {
+
+KeyLayoutMap::KeyLayoutMap()
+    :m_status(NO_INIT),
+     m_keys()
+{
+}
+
+KeyLayoutMap::~KeyLayoutMap()
+{
+}
+
+static String8
+next_token(char const** p, int *line)
+{
+    bool begun = false;
+    const char* begin = *p;
+    const char* end = *p;
+    while (true) {
+        if (*end == '\n') {
+            (*line)++;
+        }
+        switch (*end)
+        {
+            case '#':
+                if (begun) {
+                    *p = end;
+                    return String8(begin, end-begin);
+                } else {
+                    do {
+                        begin++;
+                        end++;
+                    } while (*begin != '\0' && *begin != '\n');
+                }
+            case '\0':
+            case ' ':
+            case '\n':
+            case '\r':
+            case '\t':
+                if (begun || (*end == '\0')) {
+                    *p = end;
+                    return String8(begin, end-begin);
+                } else {
+                    begin++;
+                    end++;
+                    break;
+                }
+            default:
+                end++;
+                begun = true;
+        }
+    }
+}
+
+static int32_t
+token_to_value(const char *literal, const KeycodeLabel *list)
+{
+    while (list->literal) {
+        if (0 == strcmp(literal, list->literal)) {
+            return list->value;
+        }
+        list++;
+    }
+    return list->value;
+}
+
+status_t
+KeyLayoutMap::load(const char* filename)
+{
+    int fd = open(filename, O_RDONLY);
+    if (fd < 0) {
+        LOGE("error opening file=%s err=%s\n", filename, strerror(errno));
+        m_status = errno;
+        return errno;
+    }
+
+    off_t len = lseek(fd, 0, SEEK_END);
+    off_t errlen = lseek(fd, 0, SEEK_SET);
+    if (len < 0 || errlen < 0) {
+        close(fd);
+        LOGE("error seeking file=%s err=%s\n", filename, strerror(errno));
+        m_status = errno;
+        return errno;
+    }
+
+    char* buf = (char*)malloc(len+1);
+    if (read(fd, buf, len) != len) {
+        LOGE("error reading file=%s err=%s\n", filename, strerror(errno));
+        m_status = errno != 0 ? errno : ((int)NOT_ENOUGH_DATA);
+        return errno != 0 ? errno : ((int)NOT_ENOUGH_DATA);
+    }
+    errno = 0;
+    buf[len] = '\0';
+
+    int32_t scancode = -1;
+    int32_t keycode = -1;
+    uint32_t flags = 0;
+    uint32_t tmp;
+    char* end;
+    status_t err = NO_ERROR;
+    int line = 1;
+    char const* p = buf;
+    enum { BEGIN, SCANCODE, KEYCODE, FLAG } state = BEGIN;
+    while (true) {
+        String8 token = next_token(&p, &line);
+        if (*p == '\0') {
+            break;
+        }
+        switch (state)
+        {
+            case BEGIN:
+                if (token == "key") {
+                    state = SCANCODE;
+                } else {
+                    LOGE("%s:%d: expected key, got '%s'\n", filename, line,
+                            token.string());
+                    err = BAD_VALUE;
+                    goto done;
+                }
+                break;
+            case SCANCODE:
+                scancode = strtol(token.string(), &end, 0);
+                if (*end != '\0') {
+                    LOGE("%s:%d: expected scancode (a number), got '%s'\n",
+                            filename, line, token.string());
+                    goto done;
+                }
+                //LOGI("%s:%d: got scancode %d\n", filename, line, scancode );
+                state = KEYCODE;
+                break;
+            case KEYCODE:
+                keycode = token_to_value(token.string(), KEYCODES);
+                //LOGI("%s:%d: got keycode %d for %s\n", filename, line, keycode, token.string() );
+                if (keycode == 0) {
+                    LOGE("%s:%d: expected keycode, got '%s'\n",
+                            filename, line, token.string());
+                    goto done;
+                }
+                state = FLAG;
+                break;
+            case FLAG:
+                if (token == "key") {
+                    if (scancode != -1) {
+                        //LOGI("got key decl scancode=%d keycode=%d"
+                        //       " flags=0x%08x\n", scancode, keycode, flags);
+                        Key k = { keycode, flags };
+                        m_keys.add(scancode, k);
+                        state = SCANCODE;
+                        scancode = -1;
+                        keycode = -1;
+                        flags = 0;
+                        break;
+                    }
+                }
+                tmp = token_to_value(token.string(), FLAGS);
+                //LOGI("%s:%d: got flags %x for %s\n", filename, line, tmp, token.string() );
+                if (tmp == 0) {
+                    LOGE("%s:%d: expected flag, got '%s'\n",
+                            filename, line, token.string());
+                    goto done;
+                }
+                flags |= tmp;
+                break;
+        }
+    }
+    if (state == FLAG && scancode != -1 ) {
+        //LOGI("got key decl scancode=%d keycode=%d"
+        //       " flags=0x%08x\n", scancode, keycode, flags);
+        Key k = { keycode, flags };
+        m_keys.add(scancode, k);
+    }
+
+done:
+    free(buf);
+    close(fd);
+
+    m_status = err;
+    return err;
+}
+
+status_t
+KeyLayoutMap::map(int32_t scancode, int32_t *keycode, uint32_t *flags) const
+{
+    if (m_status != NO_ERROR) {
+        return m_status;
+    }
+
+    ssize_t index = m_keys.indexOfKey(scancode);
+    if (index < 0) {
+        //LOGW("couldn't map scancode=%d\n", scancode);
+        return NAME_NOT_FOUND;
+    }
+
+    const Key& k = m_keys.valueAt(index);
+
+    *keycode = k.keycode;
+    *flags = k.flags;
+
+    //LOGD("mapped scancode=%d to keycode=%d flags=0x%08x\n", scancode,
+    //        keycode, flags);
+
+    return NO_ERROR;
+}
+
+status_t
+KeyLayoutMap::findScancodes(int32_t keycode, Vector<int32_t>* outScancodes) const
+{
+    if (m_status != NO_ERROR) {
+        return m_status;
+    }
+    
+    const size_t N = m_keys.size();
+    for (size_t i=0; i<N; i++) {
+        if (m_keys.valueAt(i).keycode == keycode) {
+            outScancodes->add(m_keys.keyAt(i));
+        }
+    }
+    
+    return NO_ERROR;
+}
+
+};
diff --git a/libs/ui/KeyLayoutMap.h b/libs/ui/KeyLayoutMap.h
new file mode 100644
index 0000000..43f84ce
--- /dev/null
+++ b/libs/ui/KeyLayoutMap.h
@@ -0,0 +1,31 @@
+#ifndef KEYLAYOUTMAP_H
+#define KEYLAYOUTMAP_H
+
+#include <utils/KeyedVector.h>
+
+namespace android {
+
+class KeyLayoutMap
+{
+public:
+    KeyLayoutMap();
+    ~KeyLayoutMap();
+
+    status_t load(const char* filename);
+
+    status_t map(int32_t scancode, int32_t *keycode, uint32_t *flags) const;
+    status_t findScancodes(int32_t keycode, Vector<int32_t>* outScancodes) const;
+
+private:
+    struct Key {
+        int32_t keycode;
+        uint32_t flags;
+    };
+
+    status_t m_status;
+    KeyedVector<int32_t,Key> m_keys;
+};
+
+};
+
+#endif // KEYLAYOUTMAP_H
diff --git a/libs/ui/LayerState.cpp b/libs/ui/LayerState.cpp
new file mode 100644
index 0000000..0b6374b
--- /dev/null
+++ b/libs/ui/LayerState.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <utils/Errors.h>
+#include <utils/Parcel.h>
+#include <private/ui/LayerState.h>
+
+namespace android {
+
+status_t layer_state_t::write(Parcel& output) const
+{
+    size_t size = sizeof(layer_state_t);
+
+    //output.writeStrongBinder(surface->asBinder());
+    //size -= sizeof(surface);
+
+    transparentRegion.write(output);
+    size -= sizeof(transparentRegion);
+    
+    output.write(this, size);
+    
+    return NO_ERROR;
+}
+
+status_t layer_state_t::read(const Parcel& input)
+{
+    size_t size = sizeof(layer_state_t);
+
+    //surface = interface_cast<ISurface>(input.readStrongBinder());
+    //size -= sizeof(surface);
+
+    transparentRegion.read(input);
+    size -= sizeof(transparentRegion);
+
+    input.read(this, size);
+    
+    return NO_ERROR;
+}
+
+}; // namespace android
diff --git a/libs/ui/MODULE_LICENSE_APACHE2 b/libs/ui/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/libs/ui/MODULE_LICENSE_APACHE2
diff --git a/libs/ui/NOTICE b/libs/ui/NOTICE
new file mode 100644
index 0000000..c5b1efa
--- /dev/null
+++ b/libs/ui/NOTICE
@@ -0,0 +1,190 @@
+
+   Copyright (c) 2005-2008, The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+
+   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.
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
diff --git a/libs/ui/Overlay.cpp b/libs/ui/Overlay.cpp
new file mode 100644
index 0000000..b236edc
--- /dev/null
+++ b/libs/ui/Overlay.cpp
@@ -0,0 +1,181 @@
+/*
+ * 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 <utils/IMemory.h>
+#include <utils/Parcel.h>
+#include <utils/Errors.h>
+#include <utils/MemoryHeapBase.h>
+
+#include <ui/IOverlay.h>
+#include <ui/Overlay.h>
+
+#include <hardware/overlay.h>
+
+namespace android {
+
+Overlay::Overlay(const sp<OverlayRef>& overlayRef)
+    : mOverlayRef(overlayRef), mOverlayData(0), mStatus(NO_INIT)
+{
+    mOverlayData = NULL;
+    hw_module_t const* module;
+    if (overlayRef != 0) {
+        if (hw_get_module(OVERLAY_HARDWARE_MODULE_ID, &module) == 0) {
+            if (overlay_data_open(module, &mOverlayData) == NO_ERROR) {
+                mStatus = mOverlayData->initialize(mOverlayData,
+                        overlayRef->mOverlayHandle);
+            }
+        }
+    }
+}
+
+Overlay::~Overlay() {
+    if (mOverlayData) {
+        overlay_data_close(mOverlayData);
+    }
+}
+
+status_t Overlay::dequeueBuffer(overlay_buffer_t* buffer)
+{
+    if (mStatus != NO_ERROR) return mStatus;
+    return  mOverlayData->dequeueBuffer(mOverlayData, buffer);
+}
+
+status_t Overlay::queueBuffer(overlay_buffer_t buffer)
+{
+    if (mStatus != NO_ERROR) return mStatus;
+    return mOverlayData->queueBuffer(mOverlayData, buffer);
+}
+
+int32_t Overlay::getBufferCount() const
+{
+    if (mStatus != NO_ERROR) return mStatus;
+    return mOverlayData->getBufferCount(mOverlayData);
+}
+
+void* Overlay::getBufferAddress(overlay_buffer_t buffer)
+{
+    if (mStatus != NO_ERROR) return NULL;
+    return mOverlayData->getBufferAddress(mOverlayData, buffer);
+}
+
+void Overlay::destroy() {  
+    if (mStatus != NO_ERROR) return;
+    mOverlayRef->mOverlayChannel->destroy();
+}
+
+status_t Overlay::getStatus() const {
+    return mStatus;
+}
+
+overlay_handle_t Overlay::getHandleRef() const {
+    if (mStatus != NO_ERROR) return NULL;
+    return mOverlayRef->mOverlayHandle;
+}
+
+uint32_t Overlay::getWidth() const {
+    if (mStatus != NO_ERROR) return 0;
+    return mOverlayRef->mWidth;
+}
+
+uint32_t Overlay::getHeight() const {
+    if (mStatus != NO_ERROR) return 0;
+    return mOverlayRef->mHeight;
+}
+
+int32_t Overlay::getFormat() const {
+    if (mStatus != NO_ERROR) return -1;
+    return mOverlayRef->mFormat;
+}
+
+int32_t Overlay::getWidthStride() const {
+    if (mStatus != NO_ERROR) return 0;
+    return mOverlayRef->mWidthStride;
+}
+
+int32_t Overlay::getHeightStride() const {
+    if (mStatus != NO_ERROR) return 0;
+    return mOverlayRef->mHeightStride;
+}
+// ----------------------------------------------------------------------------
+
+OverlayRef::OverlayRef() 
+ : mOverlayHandle(0),
+    mWidth(0), mHeight(0), mFormat(0), mWidthStride(0), mHeightStride(0),
+    mOwnHandle(true)
+{    
+}
+
+OverlayRef::OverlayRef(overlay_handle_t handle, const sp<IOverlay>& channel,
+         uint32_t w, uint32_t h, int32_t f, uint32_t ws, uint32_t hs)
+    : mOverlayHandle(handle), mOverlayChannel(channel),
+    mWidth(w), mHeight(h), mFormat(f), mWidthStride(ws), mHeightStride(hs),
+    mOwnHandle(false)
+{
+}
+
+OverlayRef::~OverlayRef()
+{
+    if (mOwnHandle) {
+        /* FIXME: handles should be promoted to "real" API and be handled by 
+         * the framework */
+        for (int i=0 ; i<mOverlayHandle->numFds ; i++) {
+            close(mOverlayHandle->data[i]);
+        }
+        free((void*)mOverlayHandle);
+    }
+}
+
+sp<OverlayRef> OverlayRef::readFromParcel(const Parcel& data) {
+    sp<OverlayRef> result;
+    sp<IOverlay> overlay = IOverlay::asInterface(data.readStrongBinder());
+    if (overlay != NULL) {
+        uint32_t w = data.readInt32();
+        uint32_t h = data.readInt32();
+        uint32_t f = data.readInt32();
+        uint32_t ws = data.readInt32();
+        uint32_t hs = data.readInt32();
+        native_handle* handle = data.readNativeHandle(NULL, NULL);
+
+        result = new OverlayRef();
+        result->mOverlayHandle = handle;
+        result->mOverlayChannel = overlay;
+        result->mWidth = w;
+        result->mHeight = h;
+        result->mFormat = f;
+        result->mWidthStride = ws;
+        result->mHeightStride = hs;
+    }
+    return result;
+}
+
+status_t OverlayRef::writeToParcel(Parcel* reply, const sp<OverlayRef>& o) {
+    if (o != NULL) {
+        reply->writeStrongBinder(o->mOverlayChannel->asBinder());
+        reply->writeInt32(o->mWidth);
+        reply->writeInt32(o->mHeight);
+        reply->writeInt32(o->mFormat);
+        reply->writeInt32(o->mWidthStride);
+        reply->writeInt32(o->mHeightStride);
+        reply->writeNativeHandle(*(o->mOverlayHandle));
+    } else {
+        reply->writeStrongBinder(NULL);
+    }
+    return NO_ERROR;
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/libs/ui/PixelFormat.cpp b/libs/ui/PixelFormat.cpp
new file mode 100644
index 0000000..b65ed97
--- /dev/null
+++ b/libs/ui/PixelFormat.cpp
@@ -0,0 +1,97 @@
+/*
+ * 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 <ui/PixelFormat.h>
+#include <pixelflinger/format.h>
+
+namespace android {
+
+size_t PixelFormatInfo::getScanlineSize(unsigned int width) const
+{
+    size_t size;
+    if ((components >= 6) && (components <= 8)) {
+        // YCbCr formats are differents.
+        size = (width * bitsPerPixel)>>3;
+    } else {
+        size = width * bytesPerPixel;
+    }
+    return size;
+}
+
+ssize_t bytesPerPixel(PixelFormat format)
+{
+    PixelFormatInfo info;
+    status_t err = getPixelFormatInfo(format, &info);
+    return (err < 0) ? err : info.bytesPerPixel;
+}
+
+ssize_t bitsPerPixel(PixelFormat format)
+{
+    PixelFormatInfo info;
+    status_t err = getPixelFormatInfo(format, &info);
+    return (err < 0) ? err : info.bitsPerPixel;
+}
+
+status_t getPixelFormatInfo(PixelFormat format, PixelFormatInfo* info)
+{
+    if (format < 0)
+        return BAD_VALUE;
+
+    if (info->version != sizeof(PixelFormatInfo))
+        return INVALID_OPERATION;
+
+    size_t numEntries;
+    const GGLFormat *i = gglGetPixelFormatTable(&numEntries) + format;
+    bool valid = uint32_t(format) < numEntries;
+    if (!valid) {
+        return BAD_INDEX;
+    }
+    
+    #define COMPONENT(name) \ 
+        case GGL_##name: info->components = PixelFormatInfo::name; break;
+    
+    switch (i->components) {
+        COMPONENT(ALPHA)
+        COMPONENT(RGB)
+        COMPONENT(RGBA)
+        COMPONENT(LUMINANCE)
+        COMPONENT(LUMINANCE_ALPHA)
+        COMPONENT(Y_CB_CR_SP)
+        COMPONENT(Y_CB_CR_P)
+        COMPONENT(Y_CB_CR_I)
+        default:
+            return BAD_INDEX;
+    }
+    
+    #undef COMPONENT
+    
+    info->format = format;
+    info->bytesPerPixel = i->size;
+    info->bitsPerPixel  = i->bitsPerPixel;
+    info->h_alpha       = i->ah;
+    info->l_alpha       = i->al;
+    info->h_red         = i->rh;
+    info->l_red         = i->rl;
+    info->h_green       = i->gh;
+    info->l_green       = i->gl;
+    info->h_blue        = i->bh;
+    info->l_blue        = i->bl;
+
+    return NO_ERROR;
+}
+
+}; // namespace android
+
diff --git a/libs/ui/Point.cpp b/libs/ui/Point.cpp
new file mode 100644
index 0000000..438d49f
--- /dev/null
+++ b/libs/ui/Point.cpp
@@ -0,0 +1,11 @@
+/*
+ *  Point.cpp
+ *  Android
+ *
+ *  Created on 11/16/2006.
+ *  Copyright 2005 The Android Open Source Project
+ *
+ */
+
+#include <ui/Point.h>
+
diff --git a/libs/ui/Rect.cpp b/libs/ui/Rect.cpp
new file mode 100644
index 0000000..99e68bb
--- /dev/null
+++ b/libs/ui/Rect.cpp
@@ -0,0 +1,86 @@
+/*
+ *  Rect.cpp
+ *  Android
+ *
+ *  Created on 10/14/05.
+ *  Copyright 2005 The Android Open Source Project
+ *
+ */
+
+#include <ui/Rect.h>
+
+namespace android {
+
+inline int min(int a, int b) {
+    return (a<b) ? a : b;
+}
+
+inline int max(int a, int b) {
+    return (a>b) ? a : b;
+}
+
+void Rect::makeInvalid() {
+    left = 0;
+    top = 0;
+    right = -1;
+    bottom = -1;
+}
+
+bool Rect::operator < (const Rect& rhs) const
+{
+    if (top<rhs.top) {
+        return true;
+    } else if (top == rhs.top) {
+        if (left < rhs.left) {
+            return true;
+        } else if (left == rhs.left) {
+            if (bottom<rhs.bottom) {
+                return true;
+            } else if (bottom == rhs.bottom) {
+                if (right<rhs.right) {
+                    return true;
+                }
+            }
+        }
+    }
+    return false;
+}
+
+Rect& Rect::offsetTo(int x, int y)
+{
+    right -= left - x;
+    bottom -= top - y;
+    left = x;
+    top = y;
+    return *this;
+}
+
+Rect& Rect::offsetBy(int x, int y)
+{
+    left += x;
+    top  += y;
+    right+= x;
+    bottom+=y;
+    return *this;
+}
+
+Rect Rect::operator + (const Point& rhs) const
+{
+    return Rect(left+rhs.x, top+rhs.y, right+rhs.x, bottom+rhs.y); 
+}
+
+Rect Rect::operator - (const Point& rhs) const
+{
+    return Rect(left-rhs.x, top-rhs.y, right-rhs.x, bottom-rhs.y); 
+}
+
+bool Rect::intersect(const Rect& with, Rect* result) const
+{
+    result->left    = max(left, with.left);
+    result->top     = max(top, with.top);
+    result->right   = min(right, with.right);
+    result->bottom  = min(bottom, with.bottom);
+    return !(result->isEmpty());
+}
+
+}; // namespace android
diff --git a/libs/ui/Region.cpp b/libs/ui/Region.cpp
new file mode 100644
index 0000000..26e694a
--- /dev/null
+++ b/libs/ui/Region.cpp
@@ -0,0 +1,313 @@
+/*
+ * 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 "Region"
+
+#include <stdio.h>
+#include <utils/Atomic.h>
+#include <utils/Debug.h>
+#include <utils/String8.h>
+#include <ui/Region.h>
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+Region::Region()
+{
+}
+
+Region::Region(const Region& rhs)
+    : mRegion(rhs.mRegion)
+{
+}
+
+Region::Region(const SkRegion& rhs)
+    : mRegion(rhs)
+{
+}
+
+Region::~Region()
+{
+}
+
+Region::Region(const Rect& rhs)
+{
+    set(rhs);
+}
+
+Region::Region(const Parcel& parcel)
+{
+    read(parcel);
+}
+
+Region::Region(const void* buffer)
+{
+    read(buffer);
+}
+
+Region& Region::operator = (const Region& rhs)
+{
+    mRegion = rhs.mRegion;
+    return *this;
+}
+
+const SkRegion& Region::toSkRegion() const
+{
+    return mRegion;
+}
+
+Rect Region::bounds() const
+{
+    const SkIRect& b(mRegion.getBounds());
+    return Rect(b.fLeft, b.fTop, b.fRight, b.fBottom);
+}
+
+void Region::clear()
+{
+    mRegion.setEmpty();
+}
+
+void Region::set(const Rect& r)
+{
+    SkIRect ir;
+    ir.set(r.left, r.top, r.right, r.bottom);
+    mRegion.setRect(ir);
+}
+
+// ----------------------------------------------------------------------------
+
+Region& Region::orSelf(const Rect& r)
+{
+    SkIRect ir;
+    ir.set(r.left, r.top, r.right, r.bottom);
+    mRegion.op(ir, SkRegion::kUnion_Op);
+    return *this;
+}
+
+Region& Region::andSelf(const Rect& r)
+{
+    SkIRect ir;
+    ir.set(r.left, r.top, r.right, r.bottom);
+    mRegion.op(ir, SkRegion::kIntersect_Op);
+    return *this;
+}
+
+// ----------------------------------------------------------------------------
+
+Region& Region::orSelf(const Region& rhs) {
+    mRegion.op(rhs.mRegion, SkRegion::kUnion_Op);
+    return *this;
+}
+
+Region& Region::andSelf(const Region& rhs) {
+    mRegion.op(rhs.mRegion, SkRegion::kIntersect_Op);
+    return *this;
+}
+
+Region& Region::subtractSelf(const Region& rhs) {
+    mRegion.op(rhs.mRegion, SkRegion::kDifference_Op);
+    return *this;
+}
+
+Region& Region::translateSelf(int x, int y) {
+    if (x|y) mRegion.translate(x, y);
+    return *this;
+}
+
+Region Region::merge(const Region& rhs) const {
+    Region result;
+    result.mRegion.op(mRegion, rhs.mRegion, SkRegion::kUnion_Op);
+    return result;
+}
+
+Region Region::intersect(const Region& rhs) const {
+    Region result;
+    result.mRegion.op(mRegion, rhs.mRegion, SkRegion::kIntersect_Op);
+    return result;
+}
+
+Region Region::subtract(const Region& rhs) const {
+    Region result;
+    result.mRegion.op(mRegion, rhs.mRegion, SkRegion::kDifference_Op);
+    return result;
+}
+
+Region Region::translate(int x, int y) const {
+    Region result;
+    mRegion.translate(x, y, &result.mRegion);
+    return result;
+}
+
+// ----------------------------------------------------------------------------
+
+Region& Region::orSelf(const Region& rhs, int dx, int dy) {
+    SkRegion r(rhs.mRegion);
+    r.translate(dx, dy);
+    mRegion.op(r, SkRegion::kUnion_Op);
+    return *this;
+}
+
+Region& Region::andSelf(const Region& rhs, int dx, int dy) {
+    SkRegion r(rhs.mRegion);
+    r.translate(dx, dy);
+    mRegion.op(r, SkRegion::kIntersect_Op);
+    return *this;
+}
+
+Region& Region::subtractSelf(const Region& rhs, int dx, int dy) {
+    SkRegion r(rhs.mRegion);
+    r.translate(dx, dy);
+    mRegion.op(r, SkRegion::kDifference_Op);
+    return *this;
+}
+
+Region Region::merge(const Region& rhs, int dx, int dy) const {
+    Region result;
+    SkRegion r(rhs.mRegion);
+    r.translate(dx, dy);
+    result.mRegion.op(mRegion, r, SkRegion::kUnion_Op);
+    return result;
+}
+
+Region Region::intersect(const Region& rhs, int dx, int dy) const {
+    Region result;
+    SkRegion r(rhs.mRegion);
+    r.translate(dx, dy);
+    result.mRegion.op(mRegion, r, SkRegion::kIntersect_Op);
+    return result;
+}
+
+Region Region::subtract(const Region& rhs, int dx, int dy) const {
+    Region result;
+    SkRegion r(rhs.mRegion);
+    r.translate(dx, dy);
+    result.mRegion.op(mRegion, r, SkRegion::kDifference_Op);
+    return result;
+}
+
+// ----------------------------------------------------------------------------
+
+Region::iterator::iterator(const Region& r)
+    : mIt(r.mRegion)
+{
+}
+
+int Region::iterator::iterate(Rect* rect)
+{
+    if (mIt.done())
+        return 0;
+    const SkIRect& r(mIt.rect());
+    rect->left  = r.fLeft;
+    rect->top   = r.fTop;
+    rect->right = r.fRight;
+    rect->bottom= r.fBottom;
+    mIt.next();
+    return 1;
+}
+
+// ----------------------------------------------------------------------------
+
+// we write a 4byte size ahead of the actual region, so we know how much we'll need for reading
+
+status_t Region::write(Parcel& parcel) const
+{
+    int32_t size = mRegion.flatten(NULL);
+    parcel.writeInt32(size);
+    mRegion.flatten(parcel.writeInplace(size));
+    return NO_ERROR;
+}
+
+status_t Region::read(const Parcel& parcel)
+{
+    size_t size = parcel.readInt32();
+    mRegion.unflatten(parcel.readInplace(size));
+    return NO_ERROR;
+}
+
+ssize_t Region::write(void* buffer, size_t size) const
+{
+    size_t sizeNeeded = mRegion.flatten(NULL);
+    if (sizeNeeded > size) return NO_MEMORY;
+    return mRegion.flatten(buffer);
+}
+
+ssize_t Region::read(const void* buffer)
+{
+    return mRegion.unflatten(buffer);
+}
+
+ssize_t Region::writeEmpty(void* buffer, size_t size)
+{
+    if (size < 4) return NO_MEMORY;
+    // this needs to stay in sync with SkRegion
+    *static_cast<int32_t*>(buffer) = -1;
+    return 4;
+}
+
+bool Region::isEmpty(void* buffer)
+{
+    // this needs to stay in sync with SkRegion
+    return *static_cast<int32_t*>(buffer) == -1;
+}
+
+size_t Region::rects(Vector<Rect>& rectList) const
+{
+    rectList.clear();
+    if (!isEmpty()) {
+        SkRegion::Iterator iterator(mRegion);
+        while( !iterator.done() ) {
+            const SkIRect& ir(iterator.rect());
+            rectList.push(Rect(ir.fLeft, ir.fTop, ir.fRight, ir.fBottom));
+            iterator.next();
+        }
+    }
+    return rectList.size();
+}
+
+void Region::dump(String8& out, const char* what, uint32_t flags) const
+{
+    (void)flags;
+    Vector<Rect> r;
+    rects(r);
+    
+    size_t SIZE = 256;
+    char buffer[SIZE];
+    
+    snprintf(buffer, SIZE, "  Region %s (this=%p, count=%d)\n", what, this, r.size());
+    out.append(buffer);
+    for (size_t i=0 ; i<r.size() ; i++) {
+        snprintf(buffer, SIZE, "    [%3d, %3d, %3d, %3d]\n",
+            r[i].left, r[i].top,r[i].right,r[i].bottom);
+        out.append(buffer);
+    }
+}
+
+void Region::dump(const char* what, uint32_t flags) const
+{
+    (void)flags;
+    Vector<Rect> r;
+    rects(r);
+    LOGD("  Region %s (this=%p, count=%d)\n", what, this, r.size());
+    for (size_t i=0 ; i<r.size() ; i++) {
+        LOGD("    [%3d, %3d, %3d, %3d]\n",
+            r[i].left, r[i].top,r[i].right,r[i].bottom);
+    }
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/libs/ui/Surface.cpp b/libs/ui/Surface.cpp
new file mode 100644
index 0000000..4ea9ae2
--- /dev/null
+++ b/libs/ui/Surface.cpp
@@ -0,0 +1,256 @@
+/*
+ * 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 "Surface"
+
+#include <stdint.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <utils/Atomic.h>
+#include <utils/Errors.h>
+#include <utils/threads.h>
+#include <utils/IPCThreadState.h>
+#include <utils/IMemory.h>
+#include <utils/Log.h>
+
+#include <ui/ISurface.h>
+#include <ui/Surface.h>
+#include <ui/SurfaceComposerClient.h>
+#include <ui/Rect.h>
+
+#include <private/ui/SharedState.h>
+#include <private/ui/LayerState.h>
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+Surface::Surface(const sp<SurfaceComposerClient>& client, 
+        const sp<ISurface>& surface,
+        const ISurfaceFlingerClient::surface_data_t& data,
+        uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
+        bool owner)
+    : mClient(client), mSurface(surface),
+      mToken(data.token), mIdentity(data.identity),
+      mFormat(format), mFlags(flags), mOwner(owner)
+{
+    mSwapRectangle.makeInvalid();
+    mSurfaceHeapBase[0] = 0;
+    mSurfaceHeapBase[1] = 0;
+    mHeap[0] = data.heap[0]; 
+    mHeap[1] = data.heap[1];
+}
+
+Surface::Surface(Surface const* rhs)
+    : mOwner(false)
+{
+    mToken   = rhs->mToken;
+    mIdentity= rhs->mIdentity;
+    mClient  = rhs->mClient;
+    mSurface = rhs->mSurface;
+    mHeap[0] = rhs->mHeap[0];
+    mHeap[1] = rhs->mHeap[1];
+    mFormat  = rhs->mFormat;
+    mFlags   = rhs->mFlags;
+    mSurfaceHeapBase[0] = rhs->mSurfaceHeapBase[0];
+    mSurfaceHeapBase[1] = rhs->mSurfaceHeapBase[1];
+    mSwapRectangle.makeInvalid();
+}
+
+Surface::~Surface()
+{
+    if (mOwner && mToken>=0 && mClient!=0) {
+        mClient->destroySurface(mToken);
+    }
+    mClient.clear();
+    mSurface.clear();
+    mHeap[0].clear();
+    mHeap[1].clear();
+    IPCThreadState::self()->flushCommands();
+}
+
+sp<Surface> Surface::dup() const
+{
+    Surface const * r = this;
+    if (this && mOwner) {
+        // the only reason we need to do this is because of Java's garbage
+        // collector: because we're creating a copy of the Surface
+        // instead of a reference, we can garantee that when our last
+        // reference goes away, the real surface will be deleted.
+        // Without this hack (the code is correct too), we'd have to
+        // wait for a GC for the surface to go away.
+        r = new Surface(this);        
+    }
+    return const_cast<Surface*>(r);
+}
+
+status_t Surface::nextBuffer(SurfaceInfo* info) {
+    return mClient->nextBuffer(this, info);
+}
+
+status_t Surface::lock(SurfaceInfo* info, bool blocking) {
+    return Surface::lock(info, NULL, blocking);
+}
+
+status_t Surface::lock(SurfaceInfo* info, Region* dirty, bool blocking) {
+    if (heapBase(0) == 0) return INVALID_OPERATION;
+    if (heapBase(1) == 0) return INVALID_OPERATION;
+    return mClient->lockSurface(this, info, dirty, blocking);
+}
+
+status_t Surface::unlockAndPost() {
+    if (heapBase(0) == 0) return INVALID_OPERATION;
+    if (heapBase(1) == 0) return INVALID_OPERATION;
+    return mClient->unlockAndPostSurface(this);
+}
+
+status_t Surface::unlock() {
+    if (heapBase(0) == 0) return INVALID_OPERATION;
+    if (heapBase(1) == 0) return INVALID_OPERATION;
+    return mClient->unlockSurface(this);
+}
+
+status_t Surface::setLayer(int32_t layer) {
+    return mClient->setLayer(this, layer);
+}
+status_t Surface::setPosition(int32_t x, int32_t y) {
+    return mClient->setPosition(this, x, y);
+}
+status_t Surface::setSize(uint32_t w, uint32_t h) {
+    return mClient->setSize(this, w, h);
+}
+status_t Surface::hide() {
+    return mClient->hide(this);
+}
+status_t Surface::show(int32_t layer) {
+    return mClient->show(this, layer);
+}
+status_t Surface::freeze() {
+    return mClient->freeze(this);
+}
+status_t Surface::unfreeze() {
+    return mClient->unfreeze(this);
+}
+status_t Surface::setFlags(uint32_t flags, uint32_t mask) {
+    return mClient->setFlags(this, flags, mask);
+}
+status_t Surface::setTransparentRegionHint(const Region& transparent) {
+    return mClient->setTransparentRegionHint(this, transparent);
+}
+status_t Surface::setAlpha(float alpha) {
+    return mClient->setAlpha(this, alpha);
+}
+status_t Surface::setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
+    return mClient->setMatrix(this, dsdx, dtdx, dsdy, dtdy);
+}
+status_t Surface::setFreezeTint(uint32_t tint) {
+    return mClient->setFreezeTint(this, tint);
+}
+
+Region Surface::dirtyRegion() const  {
+    return mDirtyRegion; 
+}
+void Surface::setDirtyRegion(const Region& region) const {
+    mDirtyRegion = region;
+}
+const Rect& Surface::swapRectangle() const {
+    return mSwapRectangle;
+}
+void Surface::setSwapRectangle(const Rect& r) {
+    mSwapRectangle = r;
+}
+
+sp<Surface> Surface::readFromParcel(Parcel* parcel)
+{
+    sp<SurfaceComposerClient> client;
+    ISurfaceFlingerClient::surface_data_t data;
+    sp<IBinder> clientBinder= parcel->readStrongBinder();
+    sp<ISurface> surface    = interface_cast<ISurface>(parcel->readStrongBinder());
+    data.heap[0]            = interface_cast<IMemoryHeap>(parcel->readStrongBinder());
+    data.heap[1]            = interface_cast<IMemoryHeap>(parcel->readStrongBinder());
+    data.token              = parcel->readInt32();
+    data.identity           = parcel->readInt32();
+    PixelFormat format      = parcel->readInt32();
+    uint32_t flags          = parcel->readInt32();
+
+    if (clientBinder != NULL)
+        client = SurfaceComposerClient::clientForConnection(clientBinder);
+
+    return new Surface(client, surface, data, 0, 0, format, flags, false);
+}
+
+status_t Surface::writeToParcel(const sp<Surface>& surface, Parcel* parcel)
+{
+    uint32_t flags=0;
+    uint32_t format=0;
+    SurfaceID token = -1;
+    uint32_t identity = 0;
+    sp<SurfaceComposerClient> client;
+    sp<ISurface> sur;
+    sp<IMemoryHeap> heap[2];
+    if (surface->isValid()) {
+        token = surface->mToken;
+        identity = surface->mIdentity;
+        client = surface->mClient;
+        sur = surface->mSurface;
+        heap[0] = surface->mHeap[0];
+        heap[1] = surface->mHeap[1];
+        format = surface->mFormat;
+        flags = surface->mFlags;
+    }
+    parcel->writeStrongBinder(client!=0  ? client->connection() : NULL);
+    parcel->writeStrongBinder(sur!=0     ? sur->asBinder()      : NULL);
+    parcel->writeStrongBinder(heap[0]!=0 ? heap[0]->asBinder()  : NULL);
+    parcel->writeStrongBinder(heap[1]!=0 ? heap[1]->asBinder()  : NULL);
+    parcel->writeInt32(token);
+    parcel->writeInt32(identity);
+    parcel->writeInt32(format);
+    parcel->writeInt32(flags);
+    return NO_ERROR;
+}
+
+bool Surface::isSameSurface(const sp<Surface>& lhs, const sp<Surface>& rhs) 
+{
+    if (lhs == 0 || rhs == 0)
+        return false;
+    return lhs->mSurface->asBinder() == rhs->mSurface->asBinder();
+}
+
+void* Surface::heapBase(int i) const 
+{
+    void* heapBase = mSurfaceHeapBase[i];
+    // map lazily so it doesn't get mapped in clients that don't need it
+    if (heapBase == 0) {
+        const sp<IMemoryHeap>& heap(mHeap[i]);
+        if (heap != 0) {
+            heapBase = static_cast<uint8_t*>(heap->base());
+            if (heapBase == MAP_FAILED) {
+                heapBase = NULL;
+                LOGE("Couldn't map Surface's heap (binder=%p, heap=%p)",
+                        heap->asBinder().get(), heap.get());
+            }
+            mSurfaceHeapBase[i] = heapBase;
+        }
+    }
+    return heapBase;
+}
+
+}; // namespace android
+
diff --git a/libs/ui/SurfaceComposerClient.cpp b/libs/ui/SurfaceComposerClient.cpp
new file mode 100644
index 0000000..9354a7a
--- /dev/null
+++ b/libs/ui/SurfaceComposerClient.cpp
@@ -0,0 +1,1026 @@
+/*
+ * 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 "SurfaceComposerClient"
+
+#include <stdint.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <cutils/memory.h>
+
+#include <utils/Atomic.h>
+#include <utils/Errors.h>
+#include <utils/threads.h>
+#include <utils/KeyedVector.h>
+#include <utils/IPCThreadState.h>
+#include <utils/IServiceManager.h>
+#include <utils/IMemory.h>
+#include <utils/Log.h>
+
+#include <ui/ISurfaceComposer.h>
+#include <ui/ISurfaceFlingerClient.h>
+#include <ui/ISurface.h>
+#include <ui/SurfaceComposerClient.h>
+#include <ui/DisplayInfo.h>
+#include <ui/Rect.h>
+#include <ui/Point.h>
+
+#include <private/ui/SharedState.h>
+#include <private/ui/LayerState.h>
+#include <private/ui/SurfaceFlingerSynchro.h>
+
+#include <pixelflinger/pixelflinger.h>
+
+#include <utils/BpBinder.h>
+
+#define VERBOSE(...)	((void)0)
+//#define VERBOSE			LOGD
+
+#define LIKELY( exp )       (__builtin_expect( (exp) != 0, true  ))
+#define UNLIKELY( exp )     (__builtin_expect( (exp) != 0, false ))
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+// Must not be holding SurfaceComposerClient::mLock when acquiring gLock here.
+static Mutex                                                gLock;
+static sp<ISurfaceComposer>                                 gSurfaceManager;
+static DefaultKeyedVector< sp<IBinder>, sp<SurfaceComposerClient> > gActiveConnections;
+static SortedVector<sp<SurfaceComposerClient> >             gOpenTransactions;
+static sp<IMemory>                                          gServerCblkMemory;
+static volatile surface_flinger_cblk_t*                     gServerCblk;
+
+const sp<ISurfaceComposer>& _get_surface_manager()
+{
+    if (gSurfaceManager != 0) {
+        return gSurfaceManager;
+    }
+
+    sp<IBinder> binder;
+    sp<IServiceManager> sm = defaultServiceManager();
+    do {
+        binder = sm->getService(String16("SurfaceFlinger"));
+        if (binder == 0) {
+            LOGW("SurfaceFlinger not published, waiting...");
+            usleep(500000); // 0.5 s
+        }
+    } while(binder == 0);
+    sp<ISurfaceComposer> sc(interface_cast<ISurfaceComposer>(binder));
+
+    Mutex::Autolock _l(gLock);
+    if (gSurfaceManager == 0) {
+        gSurfaceManager = sc;
+    }
+    return gSurfaceManager;
+}
+
+static volatile surface_flinger_cblk_t const * get_cblk()
+{
+    if (gServerCblk == 0) {
+        const sp<ISurfaceComposer>& sm(_get_surface_manager());
+        Mutex::Autolock _l(gLock);
+        if (gServerCblk == 0) {
+            gServerCblkMemory = sm->getCblk();
+            LOGE_IF(gServerCblkMemory==0, "Can't get server control block");
+            gServerCblk = (surface_flinger_cblk_t *)gServerCblkMemory->pointer();
+            LOGE_IF(gServerCblk==0, "Can't get server control block address");
+        }
+    }
+    return gServerCblk;
+}
+
+// ---------------------------------------------------------------------------
+
+static void copyBlt(const GGLSurface& dst,
+        const GGLSurface& src, const Region& reg)
+{
+    Region::iterator iterator(reg);
+    if (iterator) {
+        // NOTE: dst and src must be the same format
+        Rect r;
+        const size_t bpp = bytesPerPixel(src.format);
+        const size_t dbpr = dst.stride * bpp;
+        const size_t sbpr = src.stride * bpp;
+        while (iterator.iterate(&r)) {
+            ssize_t h = r.bottom - r.top;
+            if (h) {
+                size_t size = (r.right - r.left) * bpp;
+                uint8_t* s = src.data + (r.left + src.stride * r.top) * bpp;
+                uint8_t* d = dst.data + (r.left + dst.stride * r.top) * bpp;
+                if (dbpr==sbpr && size==sbpr) {
+                    size *= h;
+                    h = 1;
+                }
+                do {
+                    memcpy(d, s, size);
+                    d += dbpr;
+                    s += sbpr;
+                } while (--h > 0);
+            }
+        }
+    }
+}
+
+// ---------------------------------------------------------------------------
+
+surface_flinger_cblk_t::surface_flinger_cblk_t()
+{
+}
+
+// ---------------------------------------------------------------------------
+
+per_client_cblk_t::per_client_cblk_t()
+{
+}
+
+// these functions are used by the clients
+inline status_t per_client_cblk_t::validate(size_t i) const {
+    if (uint32_t(i) >= NUM_LAYERS_MAX)
+        return BAD_INDEX;
+    if (layers[i].swapState & eInvalidSurface)
+        return NO_MEMORY;
+    return NO_ERROR;
+}
+
+int32_t per_client_cblk_t::lock_layer(size_t i, uint32_t flags)
+{
+    int32_t index;
+    uint32_t state;
+    int timeout = 0;
+    status_t result;
+    layer_cblk_t * const layer = layers + i;
+    const bool blocking = flags & BLOCKING;
+    const bool inspect  = flags & INSPECT;
+
+    do {
+        state = layer->swapState;
+
+        if (UNLIKELY((state&(eFlipRequested|eNextFlipPending)) == eNextFlipPending)) {
+            LOGE("eNextFlipPending set but eFlipRequested not set, "
+                 "layer=%d (lcblk=%p), state=%08x",
+                 int(i), layer, int(state));
+            return INVALID_OPERATION;
+        }
+
+        if (UNLIKELY(state&eLocked)) {
+            LOGE("eLocked set when entering lock_layer(), "
+                 "layer=%d (lcblk=%p), state=%08x",
+                 int(i), layer, int(state));
+            return WOULD_BLOCK;
+        }
+
+
+	    if (state & (eFlipRequested | eNextFlipPending | eResizeRequested
+                        | eInvalidSurface))
+        {
+	        int32_t resizeIndex;
+	        Mutex::Autolock _l(lock);
+	            // might block for a very short amount of time
+	            // will never cause the server to block (trylock())
+
+	        goto start_loop_here;
+
+	        // We block the client if:
+	        // eNextFlipPending:  we've used both buffers already, so we need to
+	        //                    wait for one to become availlable.
+	        // eResizeRequested:  the buffer we're going to acquire is being
+	        //                    resized. Block until it is done.
+	        // eFlipRequested && eBusy: the buffer we're going to acquire is
+	        //                    currently in use by the server.
+	        // eInvalidSurface:   this is a special case, we don't block in this
+	        //                    case, we just return an error.
+
+	        while((state & (eNextFlipPending|eInvalidSurface)) ||
+	              (state & ((resizeIndex) ? eResizeBuffer1 : eResizeBuffer0)) ||
+	              ((state & (eFlipRequested|eBusy)) == (eFlipRequested|eBusy)) )
+	        {
+	            if (state & eInvalidSurface)
+	                return NO_MEMORY;
+
+	            if (!blocking)
+	                return WOULD_BLOCK;
+
+                timeout = 0;
+                result = cv.waitRelative(lock, seconds(1));
+	            if (__builtin_expect(result!=NO_ERROR, false)) {
+                    const int newState = layer->swapState;
+                    LOGW(   "lock_layer timed out (is the CPU pegged?) "
+                            "layer=%d, lcblk=%p, state=%08x (was %08x)",
+                            int(i), layer, newState, int(state));
+                    timeout = newState != int(state);
+                }
+
+	        start_loop_here:
+	            state = layer->swapState;
+	            resizeIndex = (state&eIndex) ^ ((state&eFlipRequested)>>1);
+	        }
+
+            LOGW_IF(timeout,
+                    "lock_layer() timed out but didn't appear to need "
+                    "to be locked and we recovered "
+                    "(layer=%d, lcblk=%p, state=%08x)",
+                    int(i), layer, int(state));
+	    }
+
+	    // eFlipRequested is not set and cannot be set by another thread: it's
+	    // safe to use the first buffer without synchronization.
+
+        // Choose the index depending on eFlipRequested.
+        // When it's set, choose the 'other' buffer.
+        index = (state&eIndex) ^ ((state&eFlipRequested)>>1);
+
+	    // make sure this buffer is valid
+	    if (layer->surface[index].bits_offset < 0) {
+	        return status_t(layer->surface[index].bits_offset);
+	    }
+
+        if (inspect) {
+            // we just want to inspect this layer. don't lock it.
+            goto done;
+        }
+
+	    // last thing before we're done, we need to atomically lock the state
+    } while (android_atomic_cmpxchg(state, state|eLocked, &(layer->swapState)));
+
+    VERBOSE("locked layer=%d (lcblk=%p), buffer=%d, state=0x%08x",
+         int(i), layer, int(index), int(state));
+
+    // store the index of the locked buffer (for client use only)
+    layer->flags &= ~eBufferIndex;
+    layer->flags |= ((index << eBufferIndexShift) & eBufferIndex);
+
+done:
+    return index;
+}
+
+uint32_t per_client_cblk_t::unlock_layer_and_post(size_t i)
+{
+    // atomically set eFlipRequested and clear eLocked and optionnaly
+    // set eNextFlipPending if eFlipRequested was already set
+
+    layer_cblk_t * const layer = layers + i;
+    int32_t oldvalue, newvalue;
+    do {
+        oldvalue = layer->swapState;
+            // get current value
+
+        newvalue = oldvalue & ~eLocked;
+            // clear eLocked
+
+        newvalue |= eFlipRequested;
+            // set eFlipRequested
+
+        if (oldvalue & eFlipRequested)
+            newvalue |= eNextFlipPending;
+            // if eFlipRequested was alread set, set eNextFlipPending
+
+    } while (android_atomic_cmpxchg(oldvalue, newvalue, &(layer->swapState)));
+
+    VERBOSE("request pageflip for layer=%d, buffer=%d, state=0x%08x",
+            int(i), int((layer->flags & eBufferIndex) >> eBufferIndexShift),
+            int(newvalue));
+
+    // from this point, the server can kick in at anytime and use the first
+    // buffer, so we cannot use it anymore, and we must use the 'other'
+    // buffer instead (or wait if it is not availlable yet, see lock_layer).
+
+    return newvalue;
+}
+
+void per_client_cblk_t::unlock_layer(size_t i)
+{
+    layer_cblk_t * const layer = layers + i;
+    android_atomic_and(~eLocked, &layer->swapState);
+}
+
+// ---------------------------------------------------------------------------
+
+static inline int compare_type( const layer_state_t& lhs,
+                                const layer_state_t& rhs) {
+    if (lhs.surface < rhs.surface)  return -1;
+    if (lhs.surface > rhs.surface)  return 1;
+    return 0;
+}
+
+SurfaceComposerClient::SurfaceComposerClient()
+{
+    const sp<ISurfaceComposer>& sm(_get_surface_manager());
+    if (sm == 0) {
+        _init(0, 0);
+        return;
+    }
+
+    _init(sm, sm->createConnection());
+
+    if (mClient != 0) {
+        Mutex::Autolock _l(gLock);
+        VERBOSE("Adding client %p to map", this);
+        gActiveConnections.add(mClient->asBinder(), this);
+    }
+}
+
+SurfaceComposerClient::SurfaceComposerClient(
+        const sp<ISurfaceComposer>& sm, const sp<IBinder>& conn)
+{
+    _init(sm, interface_cast<ISurfaceFlingerClient>(conn));
+}
+
+void SurfaceComposerClient::_init(
+        const sp<ISurfaceComposer>& sm, const sp<ISurfaceFlingerClient>& conn)
+{
+    VERBOSE("Creating client %p, conn %p", this, conn.get());
+
+    mSignalServer = 0;
+    mPrebuiltLayerState = 0;
+    mTransactionOpen = 0;
+    mStatus = NO_ERROR;
+    mControl = 0;
+
+    mClient = conn;
+    if (mClient == 0) {
+        mStatus = NO_INIT;
+        return;
+    }
+
+    mClient->getControlBlocks(&mControlMemory);
+    mSignalServer = new SurfaceFlingerSynchro(sm);
+    mControl = static_cast<per_client_cblk_t *>(mControlMemory->pointer());
+}
+
+SurfaceComposerClient::~SurfaceComposerClient()
+{
+    VERBOSE("Destroying client %p, conn %p", this, mClient.get());
+    dispose();
+}
+
+status_t SurfaceComposerClient::initCheck() const
+{
+    return mStatus;
+}
+
+status_t SurfaceComposerClient::validateSurface(
+        per_client_cblk_t const* cblk, Surface const * surface)
+{
+    SurfaceID index = surface->ID();
+    if (cblk == 0) {
+        LOGE("cblk is null (surface id=%d, identity=%u)",
+                index, surface->getIdentity());
+        return NO_INIT;
+    }
+
+    status_t err = cblk->validate(index);
+    if (err != NO_ERROR) {
+        LOGE("surface (id=%d, identity=%u) is invalid, err=%d (%s)",
+                index, surface->getIdentity(), err, strerror(-err));
+        return err;
+    }
+
+    if (surface->getIdentity() != uint32_t(cblk->layers[index].identity)) {
+        LOGE("using an invalid surface id=%d, identity=%u should be %d",
+                index, surface->getIdentity(), cblk->layers[index].identity);
+        return NO_INIT;
+    }
+
+    return NO_ERROR;
+}
+
+sp<IBinder> SurfaceComposerClient::connection() const
+{
+    return (mClient != 0) ? mClient->asBinder() : 0;
+}
+
+sp<SurfaceComposerClient>
+SurfaceComposerClient::clientForConnection(const sp<IBinder>& conn)
+{
+    sp<SurfaceComposerClient> client;
+
+    { // scope for lock
+        Mutex::Autolock _l(gLock);
+        client = gActiveConnections.valueFor(conn);
+    }
+
+    if (client == 0) {
+        // Need to make a new client.
+        const sp<ISurfaceComposer>& sm(_get_surface_manager());
+        client = new SurfaceComposerClient(sm, conn);
+        if (client != 0 && client->initCheck() == NO_ERROR) {
+            Mutex::Autolock _l(gLock);
+            gActiveConnections.add(conn, client);
+            //LOGD("we have %d connections", gActiveConnections.size());
+        } else {
+            client.clear();
+        }
+    }
+
+    return client;
+}
+
+void SurfaceComposerClient::dispose()
+{
+    // this can be called more than once.
+
+    sp<IMemory>                 controlMemory;
+    sp<ISurfaceFlingerClient>   client;
+    sp<IMemoryHeap>             surfaceHeap;
+
+    {
+        Mutex::Autolock _lg(gLock);
+        Mutex::Autolock _lm(mLock);
+
+        delete mSignalServer;
+        mSignalServer = 0;
+
+        if (mClient != 0) {
+            client = mClient;
+            mClient.clear();
+
+            ssize_t i = gActiveConnections.indexOfKey(client->asBinder());
+            if (i >= 0 && gActiveConnections.valueAt(i) == this) {
+                VERBOSE("Removing client %p from map at %d", this, int(i));
+                gActiveConnections.removeItemsAt(i);
+            }
+        }
+
+        delete mPrebuiltLayerState;
+        mPrebuiltLayerState = 0;
+        controlMemory = mControlMemory;
+        surfaceHeap = mSurfaceHeap;
+        mControlMemory.clear();
+        mSurfaceHeap.clear();
+        mControl = 0;
+        mStatus = NO_INIT;
+    }
+}
+
+status_t SurfaceComposerClient::getDisplayInfo(
+        DisplayID dpy, DisplayInfo* info)
+{
+    if (uint32_t(dpy)>=NUM_DISPLAY_MAX)
+        return BAD_VALUE;
+
+    volatile surface_flinger_cblk_t const * cblk = get_cblk();
+    volatile display_cblk_t const * dcblk = cblk->displays + dpy;
+
+    info->w              = dcblk->w;
+    info->h              = dcblk->h;
+    info->orientation    = dcblk->orientation;
+    info->xdpi           = dcblk->xdpi;
+    info->ydpi           = dcblk->ydpi;
+    info->fps            = dcblk->fps;
+    info->density        = dcblk->density;
+    return getPixelFormatInfo(dcblk->format, &(info->pixelFormatInfo));
+}
+
+ssize_t SurfaceComposerClient::getDisplayWidth(DisplayID dpy)
+{
+    if (uint32_t(dpy)>=NUM_DISPLAY_MAX)
+        return BAD_VALUE;
+    volatile surface_flinger_cblk_t const * cblk = get_cblk();
+    volatile display_cblk_t const * dcblk = cblk->displays + dpy;
+    return dcblk->w;
+}
+
+ssize_t SurfaceComposerClient::getDisplayHeight(DisplayID dpy)
+{
+    if (uint32_t(dpy)>=NUM_DISPLAY_MAX)
+        return BAD_VALUE;
+    volatile surface_flinger_cblk_t const * cblk = get_cblk();
+    volatile display_cblk_t const * dcblk = cblk->displays + dpy;
+    return dcblk->h;
+}
+
+ssize_t SurfaceComposerClient::getDisplayOrientation(DisplayID dpy)
+{
+    if (uint32_t(dpy)>=NUM_DISPLAY_MAX)
+        return BAD_VALUE;
+    volatile surface_flinger_cblk_t const * cblk = get_cblk();
+    volatile display_cblk_t const * dcblk = cblk->displays + dpy;
+    return dcblk->orientation;
+}
+
+ssize_t SurfaceComposerClient::getNumberOfDisplays()
+{
+    volatile surface_flinger_cblk_t const * cblk = get_cblk();
+    uint32_t connected = cblk->connected;
+    int n = 0;
+    while (connected) {
+        if (connected&1) n++;
+        connected >>= 1;
+    }
+    return n;
+}
+
+sp<Surface> SurfaceComposerClient::createSurface(
+        int pid,
+        DisplayID display,
+        uint32_t w,
+        uint32_t h,
+        PixelFormat format,
+        uint32_t flags)
+{
+    sp<Surface> result;
+    if (mStatus == NO_ERROR) {
+        ISurfaceFlingerClient::surface_data_t data;
+        sp<ISurface> surface = mClient->createSurface(&data, pid,
+                display, w, h, format, flags);
+        if (surface != 0) {
+            if (uint32_t(data.token) < NUM_LAYERS_MAX) {
+                result = new Surface(this, surface, data, w, h, format, flags);
+            }
+        }
+    }
+    return result;
+}
+
+status_t SurfaceComposerClient::destroySurface(SurfaceID sid)
+{
+    if (mStatus != NO_ERROR)
+        return mStatus;
+
+    // it's okay to destroy a surface while a transaction is open,
+    // (transactions really are a client-side concept)
+    // however, this indicates probably a misuse of the API or a bug
+    // in the client code.
+    LOGW_IF(mTransactionOpen,
+         "Destroying surface while a transaction is open. "
+         "Client %p: destroying surface %d, mTransactionOpen=%d",
+         this, sid, mTransactionOpen);
+
+    status_t err = mClient->destroySurface(sid);
+    return err;
+}
+
+status_t SurfaceComposerClient::nextBuffer(Surface* surface,
+                        Surface::SurfaceInfo* info)
+{
+    SurfaceID index = surface->ID();
+    per_client_cblk_t* const cblk = mControl;
+    status_t err = validateSurface(cblk, surface);
+    if (err != NO_ERROR)
+        return err;
+
+    int32_t backIdx = surface->mBackbufferIndex;
+    layer_cblk_t* const lcblk = &(cblk->layers[index]);
+    const surface_info_t* const front = lcblk->surface + (1-backIdx);
+        info->w      = front->w;
+        info->h      = front->h;
+        info->format = front->format;
+        info->base   = surface->heapBase(1-backIdx);
+        info->bits   = reinterpret_cast<void*>(intptr_t(info->base) + front->bits_offset);
+        info->bpr    = front->bpr;
+
+    return 0;
+}
+
+status_t SurfaceComposerClient::lockSurface(
+        Surface* surface,
+        Surface::SurfaceInfo* other,
+        Region* dirty,
+        bool blocking)
+{
+    Mutex::Autolock _l(surface->getLock());
+
+    SurfaceID index = surface->ID();
+    per_client_cblk_t* const cblk = mControl;
+    status_t err = validateSurface(cblk, surface);
+    if (err != NO_ERROR)
+        return err;
+
+    int32_t backIdx = cblk->lock_layer(size_t(index),
+            per_client_cblk_t::BLOCKING);
+    if (backIdx >= 0) {
+        surface->mBackbufferIndex = backIdx;
+        layer_cblk_t* const lcblk = &(cblk->layers[index]);
+        const surface_info_t* const back = lcblk->surface + backIdx;
+        const surface_info_t* const front = lcblk->surface + (1-backIdx);
+            other->w      = back->w;
+            other->h      = back->h;
+            other->format = back->format;
+            other->base   = surface->heapBase(backIdx);
+            other->bits   = reinterpret_cast<void*>(intptr_t(other->base) + back->bits_offset);
+            other->bpr    = back->bpr;
+
+        const Rect bounds(other->w, other->h);
+        Region newDirtyRegion;
+
+        if (back->flags & surface_info_t::eBufferDirty) {
+            /* it is safe to write *back here, because we're guaranteed
+             * SurfaceFlinger is not touching it (since it just granted
+             * access to us) */
+            const_cast<surface_info_t*>(back)->flags &=
+                    ~surface_info_t::eBufferDirty;
+
+            // content is meaningless in this case and the whole surface
+            // needs to be redrawn.
+
+            newDirtyRegion.set(bounds);
+            if (dirty) {
+                *dirty = newDirtyRegion;
+            }
+
+            //if (bytesPerPixel(other->format) == 4) {
+            //    android_memset32(
+            //        (uint32_t*)other->bits, 0xFF00FF00, other->h * other->bpr);
+            //} else {
+            //    android_memset16( // fill with green
+            //        (uint16_t*)other->bits, 0x7E0, other->h * other->bpr);
+            //}
+        }
+        else
+        {
+            if (dirty) {
+                dirty->andSelf(Region(bounds));
+                newDirtyRegion = *dirty;
+            } else {
+                newDirtyRegion.set(bounds);
+            }
+
+            Region copyback;
+            if (!(lcblk->flags & eNoCopyBack)) {
+                const Region previousDirtyRegion(surface->dirtyRegion());
+                copyback = previousDirtyRegion.subtract(newDirtyRegion);
+            }
+
+            if (!copyback.isEmpty()) {
+                // copy front to back
+                GGLSurface cb;
+                    cb.version = sizeof(GGLSurface);
+                    cb.width = back->w;
+                    cb.height = back->h;
+                    cb.stride = back->stride;
+                    cb.data = (GGLubyte*)surface->heapBase(backIdx);
+                    cb.data += back->bits_offset;
+                    cb.format = back->format;
+
+                GGLSurface t;
+                    t.version = sizeof(GGLSurface);
+                    t.width = front->w;
+                    t.height = front->h;
+                    t.stride = front->stride;
+                    t.data = (GGLubyte*)surface->heapBase(1-backIdx);
+                    t.data += front->bits_offset;
+                    t.format = front->format;
+
+                //const Region copyback(lcblk->region + 1-backIdx);
+                copyBlt(cb, t, copyback);
+            }
+        }
+
+        // update dirty region
+        surface->setDirtyRegion(newDirtyRegion);
+    }
+    return (backIdx < 0) ? status_t(backIdx) : status_t(NO_ERROR);
+}
+
+void SurfaceComposerClient::_signal_server()
+{
+    mSignalServer->signal();
+}
+
+void SurfaceComposerClient::_send_dirty_region(
+        layer_cblk_t* lcblk, const Region& dirty)
+{
+    const int32_t index = (lcblk->flags & eBufferIndex) >> eBufferIndexShift;
+    flat_region_t* flat_region = lcblk->region + index;
+    status_t err = dirty.write(flat_region, sizeof(flat_region_t));
+    if (err < NO_ERROR) {
+        // region doesn't fit, use the bounds
+        const Region reg(dirty.bounds());
+        reg.write(flat_region, sizeof(flat_region_t));
+    }
+}
+
+status_t SurfaceComposerClient::unlockAndPostSurface(Surface* surface)
+{
+    Mutex::Autolock _l(surface->getLock());
+
+    SurfaceID index = surface->ID();
+    per_client_cblk_t* const cblk = mControl;
+    status_t err = validateSurface(cblk, surface);
+    if (err != NO_ERROR)
+        return err;
+
+    Region dirty(surface->dirtyRegion());
+    const Rect& swapRect(surface->swapRectangle());
+    if (swapRect.isValid()) {
+        dirty.set(swapRect);
+    }
+
+    // transmit the dirty region
+    layer_cblk_t* const lcblk = &(cblk->layers[index]);
+    _send_dirty_region(lcblk, dirty);
+    uint32_t newstate = cblk->unlock_layer_and_post(size_t(index));
+    if (!(newstate & eNextFlipPending))
+        _signal_server();
+    return NO_ERROR;
+}
+
+status_t SurfaceComposerClient::unlockSurface(Surface* surface)
+{
+    Mutex::Autolock _l(surface->getLock());
+
+    SurfaceID index = surface->ID();
+    per_client_cblk_t* const cblk = mControl;
+    status_t err = validateSurface(cblk, surface);
+    if (err != NO_ERROR)
+        return err;
+
+    layer_cblk_t* const lcblk = &(cblk->layers[index]);
+    cblk->unlock_layer(size_t(index));
+    return NO_ERROR;
+}
+
+void SurfaceComposerClient::openGlobalTransaction()
+{
+    Mutex::Autolock _l(gLock);
+
+    if (gOpenTransactions.size()) {
+        LOGE("openGlobalTransaction() called more than once. skipping.");
+        return;
+    }
+
+    const size_t N = gActiveConnections.size();
+    VERBOSE("openGlobalTransaction (%ld clients)", N);
+    for (size_t i=0; i<N; i++) {
+        sp<SurfaceComposerClient> client(gActiveConnections.valueAt(i));
+        if (gOpenTransactions.indexOf(client) < 0) {
+            if (client->openTransaction() == NO_ERROR) {
+                if (gOpenTransactions.add(client) < 0) {
+                    // Ooops!
+                    LOGE(   "Unable to add a SurfaceComposerClient "
+                            "to the global transaction set (out of memory?)");
+                    client->closeTransaction();
+                    // let it go, it'll fail later when the user
+                    // tries to do something with the transaction
+                }
+            } else {
+                LOGE("openTransaction on client %p failed", client.get());
+                // let it go, it'll fail later when the user
+                // tries to do something with the transaction
+            }
+        }
+    }
+}
+
+void SurfaceComposerClient::closeGlobalTransaction()
+{
+    gLock.lock();
+        SortedVector< sp<SurfaceComposerClient> > clients(gOpenTransactions);
+        gOpenTransactions.clear();
+    gLock.unlock();
+
+    const size_t N = clients.size();
+    VERBOSE("closeGlobalTransaction (%ld clients)", N);
+    if (N == 1) {
+        clients[0]->closeTransaction();
+    } else {
+        const sp<ISurfaceComposer>& sm(_get_surface_manager());
+        sm->openGlobalTransaction();
+        for (size_t i=0; i<N; i++) {
+            clients[i]->closeTransaction();
+        }
+        sm->closeGlobalTransaction();
+    }
+}
+
+status_t SurfaceComposerClient::freezeDisplay(DisplayID dpy, uint32_t flags)
+{
+    const sp<ISurfaceComposer>& sm(_get_surface_manager());
+    return sm->freezeDisplay(dpy, flags);
+}
+
+status_t SurfaceComposerClient::unfreezeDisplay(DisplayID dpy, uint32_t flags)
+{
+    const sp<ISurfaceComposer>& sm(_get_surface_manager());
+    return sm->unfreezeDisplay(dpy, flags);
+}
+
+int SurfaceComposerClient::setOrientation(DisplayID dpy, int orientation)
+{
+    const sp<ISurfaceComposer>& sm(_get_surface_manager());
+    return sm->setOrientation(dpy, orientation);
+}
+
+status_t SurfaceComposerClient::openTransaction()
+{
+    if (mStatus != NO_ERROR)
+        return mStatus;
+    Mutex::Autolock _l(mLock);
+    VERBOSE(   "openTransaction (client %p, mTransactionOpen=%d)",
+            this, mTransactionOpen);
+    mTransactionOpen++;
+    if (mPrebuiltLayerState == 0) {
+        mPrebuiltLayerState = new layer_state_t;
+    }
+    return NO_ERROR;
+}
+
+
+status_t SurfaceComposerClient::closeTransaction()
+{
+    if (mStatus != NO_ERROR)
+        return mStatus;
+
+    Mutex::Autolock _l(mLock);
+
+    VERBOSE(   "closeTransaction (client %p, mTransactionOpen=%d)",
+            this, mTransactionOpen);
+
+    if (mTransactionOpen <= 0) {
+        LOGE(   "closeTransaction (client %p, mTransactionOpen=%d) "
+                "called more times than openTransaction()",
+                this, mTransactionOpen);
+        return INVALID_OPERATION;
+    }
+
+    if (mTransactionOpen >= 2) {
+        mTransactionOpen--;
+        return NO_ERROR;
+    }
+
+    mTransactionOpen = 0;
+    const ssize_t count = mStates.size();
+    if (count) {
+        mClient->setState(count, mStates.array());
+        mStates.clear();
+    }
+    return NO_ERROR;
+}
+
+layer_state_t* SurfaceComposerClient::_get_state_l(const sp<Surface>& surface)
+{
+    SurfaceID index = surface->ID();
+    per_client_cblk_t* const cblk = mControl;
+    status_t err = validateSurface(cblk, surface.get());
+    if (err != NO_ERROR)
+        return 0;
+
+    // API usage error, do nothing.
+    if (mTransactionOpen<=0) {
+        LOGE("Not in transaction (client=%p, SurfaceID=%d, mTransactionOpen=%d",
+                this, int(index), mTransactionOpen);
+        return 0;
+    }
+
+    // use mPrebuiltLayerState just to find out if we already have it
+    layer_state_t& dummy = *mPrebuiltLayerState;
+    dummy.surface = index;
+    ssize_t i = mStates.indexOf(dummy);
+    if (i < 0) {
+        // we don't have it, add an initialized layer_state to our list
+        i = mStates.add(dummy);
+    }
+    return mStates.editArray() + i;
+}
+
+layer_state_t* SurfaceComposerClient::_lockLayerState(const sp<Surface>& surface)
+{
+    layer_state_t* s;
+    mLock.lock();
+    s = _get_state_l(surface);
+    if (!s) mLock.unlock();
+    return s;
+}
+
+void SurfaceComposerClient::_unlockLayerState()
+{
+    mLock.unlock();
+}
+
+status_t SurfaceComposerClient::setPosition(Surface* surface, int32_t x, int32_t y)
+{
+    layer_state_t* s = _lockLayerState(surface);
+    if (!s) return BAD_INDEX;
+    s->what |= ISurfaceComposer::ePositionChanged;
+    s->x = x;
+    s->y = y;
+    _unlockLayerState();
+    return NO_ERROR;
+}
+
+status_t SurfaceComposerClient::setSize(Surface* surface, uint32_t w, uint32_t h)
+{
+    layer_state_t* s = _lockLayerState(surface);
+    if (!s) return BAD_INDEX;
+    s->what |= ISurfaceComposer::eSizeChanged;
+    s->w = w;
+    s->h = h;
+    _unlockLayerState();
+    return NO_ERROR;
+}
+
+status_t SurfaceComposerClient::setLayer(Surface* surface, int32_t z)
+{
+    layer_state_t* s = _lockLayerState(surface);
+    if (!s) return BAD_INDEX;
+    s->what |= ISurfaceComposer::eLayerChanged;
+    s->z = z;
+    _unlockLayerState();
+    return NO_ERROR;
+}
+
+status_t SurfaceComposerClient::hide(Surface* surface)
+{
+    return setFlags(surface, ISurfaceComposer::eLayerHidden,
+            ISurfaceComposer::eLayerHidden);
+}
+
+status_t SurfaceComposerClient::show(Surface* surface, int32_t)
+{
+    return setFlags(surface, 0, ISurfaceComposer::eLayerHidden);
+}
+
+status_t SurfaceComposerClient::freeze(Surface* surface)
+{
+    return setFlags(surface, ISurfaceComposer::eLayerFrozen,
+            ISurfaceComposer::eLayerFrozen);
+}
+
+status_t SurfaceComposerClient::unfreeze(Surface* surface)
+{
+    return setFlags(surface, 0, ISurfaceComposer::eLayerFrozen);
+}
+
+status_t SurfaceComposerClient::setFlags(Surface* surface,
+        uint32_t flags, uint32_t mask)
+{
+    layer_state_t* s = _lockLayerState(surface);
+    if (!s) return BAD_INDEX;
+    s->what |= ISurfaceComposer::eVisibilityChanged;
+    s->flags &= ~mask;
+    s->flags |= (flags & mask);
+    s->mask |= mask;
+    _unlockLayerState();
+    return NO_ERROR;
+}
+
+
+status_t SurfaceComposerClient::setTransparentRegionHint(
+        Surface* surface, const Region& transparentRegion)
+{
+    layer_state_t* s = _lockLayerState(surface);
+    if (!s) return BAD_INDEX;
+    s->what |= ISurfaceComposer::eTransparentRegionChanged;
+    s->transparentRegion = transparentRegion;
+    _unlockLayerState();
+    return NO_ERROR;
+}
+
+status_t SurfaceComposerClient::setAlpha(Surface* surface, float alpha)
+{
+    layer_state_t* s = _lockLayerState(surface);
+    if (!s) return BAD_INDEX;
+    s->what |= ISurfaceComposer::eAlphaChanged;
+    s->alpha = alpha;
+    _unlockLayerState();
+    return NO_ERROR;
+}
+
+status_t SurfaceComposerClient::setMatrix(
+        Surface* surface,
+        float dsdx, float dtdx,
+        float dsdy, float dtdy )
+{
+    layer_state_t* s = _lockLayerState(surface);
+    if (!s) return BAD_INDEX;
+    s->what |= ISurfaceComposer::eMatrixChanged;
+    layer_state_t::matrix22_t matrix;
+    matrix.dsdx = dsdx;
+    matrix.dtdx = dtdx;
+    matrix.dsdy = dsdy;
+    matrix.dtdy = dtdy;
+    s->matrix = matrix;
+    _unlockLayerState();
+    return NO_ERROR;
+}
+
+status_t SurfaceComposerClient::setFreezeTint(Surface* surface, uint32_t tint)
+{
+    layer_state_t* s = _lockLayerState(surface);
+    if (!s) return BAD_INDEX;
+    s->what |= ISurfaceComposer::eFreezeTintChanged;
+    s->tint = tint;
+    _unlockLayerState();
+    return NO_ERROR;
+}
+
+}; // namespace android
+
diff --git a/libs/ui/SurfaceFlingerSynchro.cpp b/libs/ui/SurfaceFlingerSynchro.cpp
new file mode 100644
index 0000000..5cd9755
--- /dev/null
+++ b/libs/ui/SurfaceFlingerSynchro.cpp
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "SurfaceFlingerSynchro"
+
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <utils/IPCThreadState.h>
+#include <utils/Log.h>
+
+#include <private/ui/SurfaceFlingerSynchro.h>
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+SurfaceFlingerSynchro::Barrier::Barrier()
+    : state(CLOSED) { 
+}
+
+SurfaceFlingerSynchro::Barrier::~Barrier() { 
+}
+
+void SurfaceFlingerSynchro::Barrier::open() {
+    asm volatile ("":::"memory");
+    Mutex::Autolock _l(lock);
+    state = OPENED;
+    cv.broadcast();
+}
+
+void SurfaceFlingerSynchro::Barrier::close() {
+    Mutex::Autolock _l(lock);
+    state = CLOSED;
+}
+
+void SurfaceFlingerSynchro::Barrier::waitAndClose() 
+{
+    Mutex::Autolock _l(lock);
+    while (state == CLOSED) {
+        // we're about to wait, flush the binder command buffer
+        IPCThreadState::self()->flushCommands();
+        cv.wait(lock);
+    }
+    state = CLOSED;
+}
+
+status_t SurfaceFlingerSynchro::Barrier::waitAndClose(nsecs_t timeout) 
+{
+    Mutex::Autolock _l(lock);
+    while (state == CLOSED) {
+        // we're about to wait, flush the binder command buffer
+        IPCThreadState::self()->flushCommands();
+        int err = cv.waitRelative(lock, timeout);
+        if (err != 0)
+            return err;
+    }
+    state = CLOSED;
+    return NO_ERROR;
+}
+
+// ---------------------------------------------------------------------------
+
+SurfaceFlingerSynchro::SurfaceFlingerSynchro(const sp<ISurfaceComposer>& flinger)
+    : mSurfaceComposer(flinger)
+{
+}
+
+SurfaceFlingerSynchro::SurfaceFlingerSynchro()
+{
+}
+
+SurfaceFlingerSynchro::~SurfaceFlingerSynchro()
+{
+}
+
+status_t SurfaceFlingerSynchro::signal()
+{
+    mSurfaceComposer->signal();
+    return NO_ERROR;
+}
+
+status_t SurfaceFlingerSynchro::wait()
+{
+    mBarrier.waitAndClose();
+    return NO_ERROR;
+}
+
+status_t SurfaceFlingerSynchro::wait(nsecs_t timeout)
+{
+    if (timeout == 0)
+        return SurfaceFlingerSynchro::wait();
+    return mBarrier.waitAndClose(timeout);
+}
+
+void SurfaceFlingerSynchro::open()
+{
+    mBarrier.open();
+}
+
+// ---------------------------------------------------------------------------
+
+}; // namespace android
+
diff --git a/libs/ui/Time.cpp b/libs/ui/Time.cpp
new file mode 100644
index 0000000..b5539135
--- /dev/null
+++ b/libs/ui/Time.cpp
@@ -0,0 +1,199 @@
+#include <utils/TimeUtils.h>
+#include <stdio.h>
+#include <cutils/tztime.h>
+
+namespace android {
+
+static void
+dump(const Time& t)
+{
+    #ifdef HAVE_TM_GMTOFF
+        long tm_gmtoff = t.t.tm_gmtoff;
+    #else
+        long tm_gmtoff = 0;
+    #endif
+    printf("%04d-%02d-%02d %02d:%02d:%02d (%d,%ld,%d,%d)\n",
+            t.t.tm_year+1900, t.t.tm_mon+1, t.t.tm_mday,
+            t.t.tm_hour, t.t.tm_min, t.t.tm_sec,
+            t.t.tm_isdst, tm_gmtoff, t.t.tm_wday, t.t.tm_yday);
+}
+
+Time::Time()
+{
+    t.tm_sec = 0;
+    t.tm_min = 0;
+    t.tm_hour = 0;
+    t.tm_mday = 0;
+    t.tm_mon = 0;
+    t.tm_year = 0;
+    t.tm_wday = 0;
+    t.tm_yday = 0;
+    t.tm_isdst = -1; // we don't know, so let the C library determine
+    #ifdef HAVE_TM_GMTOFF
+        t.tm_gmtoff = 0;
+    #endif
+}
+
+
+#define COMPARE_FIELD(field) do { \
+        int diff = a.t.field - b.t.field; \
+        if (diff != 0) return diff; \
+    } while(0)
+
+int
+Time::compare(Time& a, Time& b)
+{
+    if (0 == strcmp(a.timezone, b.timezone)) {
+        // if the timezones are the same, we can easily compare the two
+        // times.  Otherwise, convert to milliseconds and compare that.
+        // This requires that object be normalized.
+        COMPARE_FIELD(tm_year);
+        COMPARE_FIELD(tm_mon);
+        COMPARE_FIELD(tm_mday);
+        COMPARE_FIELD(tm_hour);
+        COMPARE_FIELD(tm_min);
+        COMPARE_FIELD(tm_sec);
+        return 0;
+    } else {
+        int64_t am = a.toMillis(false /* use isDst */);
+        int64_t bm = b.toMillis(false /* use isDst */);
+        int64_t diff = am-bm;
+        return (diff < 0) ? -1 : ((diff > 0) ? 1 : 0);
+    }
+}
+
+static const int DAYS_PER_MONTH[] = {
+                        31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+                    };
+
+static inline int days_this_month(int year, int month)
+{
+    int n = DAYS_PER_MONTH[month];
+    if (n != 28) {
+        return n;
+    } else {
+        int y = year;
+        return ((y%4)==0&&((y%100)!=0||(y%400)==0)) ? 29 : 28;
+    }
+}
+
+void 
+Time::switchTimezone(const char* timezone)
+{
+    time_t seconds = mktime_tz(&(this->t), this->timezone);
+    localtime_tz(&seconds, &(this->t), timezone);
+}
+
+String8 
+Time::format(const char *format, const struct strftime_locale *locale) const
+{
+    char buf[257];
+    int n = strftime_tz(buf, 257, format, &(this->t), locale);
+    if (n > 0) {
+        return String8(buf);
+    } else {
+        return String8();
+    }
+}
+
+static inline short
+tochar(int n)
+{
+    return (n >= 0 && n <= 9) ? ('0'+n) : ' ';
+}
+
+static inline short
+next_char(int *m, int k)
+{
+    int n = *m / k;
+    *m = *m % k;
+    return tochar(n);
+}
+
+void
+Time::format2445(short* buf, bool hasTime) const
+{
+    int n;
+
+    n = t.tm_year+1900;
+    buf[0] = next_char(&n, 1000);
+    buf[1] = next_char(&n, 100);
+    buf[2] = next_char(&n, 10);
+    buf[3] = tochar(n);
+
+    n = t.tm_mon+1;
+    buf[4] = next_char(&n, 10);
+    buf[5] = tochar(n);
+
+    n = t.tm_mday;
+    buf[6] = next_char(&n, 10);
+    buf[7] = tochar(n);
+
+    if (hasTime) {
+      buf[8] = 'T';
+
+      n = t.tm_hour;
+      buf[9] = next_char(&n, 10);
+      buf[10] = tochar(n);
+      
+      n = t.tm_min;
+      buf[11] = next_char(&n, 10);
+      buf[12] = tochar(n);
+      
+      n = t.tm_sec;
+      buf[13] = next_char(&n, 10);
+      buf[14] = tochar(n);
+      bool inUtc = strcmp("UTC", timezone) == 0;
+      if (inUtc) {
+          buf[15] = 'Z';
+      }
+    }
+}
+
+String8 
+Time::toString() const
+{
+    String8 str;
+    char* s = str.lockBuffer(150);
+    #ifdef HAVE_TM_GMTOFF
+        long tm_gmtoff = t.tm_gmtoff;
+    #else
+        long tm_gmtoff = 0;
+    #endif
+    sprintf(s, "%04d%02d%02dT%02d%02d%02d%s(%d,%d,%ld,%d,%d)", 
+            t.tm_year+1900, t.tm_mon+1, t.tm_mday, t.tm_hour, t.tm_min,
+            t.tm_sec, timezone, t.tm_wday, t.tm_yday, tm_gmtoff, t.tm_isdst,
+            (int)(((Time*)this)->toMillis(false /* use isDst */)/1000));
+    str.unlockBuffer();
+    return str;
+}
+
+void 
+Time::setToNow()
+{
+    time_t seconds;
+    time(&seconds);
+    localtime_tz(&seconds, &(this->t), this->timezone);
+}
+
+int64_t 
+Time::toMillis(bool ignoreDst)
+{
+    if (ignoreDst) {
+        this->t.tm_isdst = -1;
+    }
+    int64_t r = mktime_tz(&(this->t), this->timezone);
+    if (r == -1)
+        return -1;
+    return r * 1000;
+}
+
+void 
+Time::set(int64_t millis)
+{
+    time_t seconds = millis / 1000;
+    localtime_tz(&seconds, &(this->t), this->timezone);
+}
+
+}; // namespace android
+