eclair snapshot
diff --git a/camera/libcameraservice/Android.mk b/camera/libcameraservice/Android.mk
index 96cc512..ecaebff 100644
--- a/camera/libcameraservice/Android.mk
+++ b/camera/libcameraservice/Android.mk
@@ -25,6 +25,10 @@
 
 LOCAL_MODULE:= libcamerastub
 
+ifeq ($(TARGET_SIMULATOR),true)
+LOCAL_CFLAGS += -DSINGLE_PROCESS
+endif
+
 LOCAL_SHARED_LIBRARIES:= libui
 
 include $(BUILD_STATIC_LIBRARY)
@@ -42,12 +46,17 @@
 LOCAL_SHARED_LIBRARIES:= \
     libui \
     libutils \
+    libbinder \
     libcutils \
     libmedia
 
 LOCAL_MODULE:= libcameraservice
 
-LOCAL_CFLAGS+=-DLOG_TAG=\"CameraService\"
+LOCAL_CFLAGS += -DLOG_TAG=\"CameraService\"
+
+ifeq ($(TARGET_SIMULATOR),true)
+LOCAL_CFLAGS += -DSINGLE_PROCESS
+endif
 
 ifeq ($(USE_CAMERA_STUB), true)
 LOCAL_STATIC_LIBRARIES += libcamerastub
diff --git a/camera/libcameraservice/CameraHardwareStub.cpp b/camera/libcameraservice/CameraHardwareStub.cpp
index a7af57c..8ad1f69 100644
--- a/camera/libcameraservice/CameraHardwareStub.cpp
+++ b/camera/libcameraservice/CameraHardwareStub.cpp
@@ -33,13 +33,11 @@
                     mRawHeap(0),
                     mFakeCamera(0),
                     mPreviewFrameSize(0),
-                    mRawPictureCallback(0),
-                    mJpegPictureCallback(0),
-                    mPictureCallbackCookie(0),
-                    mPreviewCallback(0),
-                    mPreviewCallbackCookie(0),
-                    mAutoFocusCallback(0),
-                    mAutoFocusCallbackCookie(0),
+                    mNotifyCb(0),
+                    mDataCb(0),
+                    mDataCbTimestamp(0),
+                    mCallbackCookie(0),
+                    mMsgEnabled(0),
                     mCurrentPreviewFrame(0)
 {
     initDefaultParameters();
@@ -112,6 +110,36 @@
     return mRawHeap;
 }
 
+void CameraHardwareStub::setCallbacks(notify_callback notify_cb,
+                                      data_callback data_cb,
+                                      data_callback_timestamp data_cb_timestamp,
+                                      void* user)
+{
+    Mutex::Autolock lock(mLock);
+    mNotifyCb = notify_cb;
+    mDataCb = data_cb;
+    mDataCbTimestamp = data_cb_timestamp;
+    mCallbackCookie = user;
+}
+
+void CameraHardwareStub::enableMsgType(int32_t msgType)
+{
+    Mutex::Autolock lock(mLock);
+    mMsgEnabled |= msgType;
+}
+
+void CameraHardwareStub::disableMsgType(int32_t msgType)
+{
+    Mutex::Autolock lock(mLock);
+    mMsgEnabled &= ~msgType;
+}
+
+bool CameraHardwareStub::msgTypeEnabled(int32_t msgType)
+{
+    Mutex::Autolock lock(mLock);
+    return (mMsgEnabled & msgType);
+}
+
 // ---------------------------------------------------------------------------
 
 int CameraHardwareStub::previewThread()
@@ -150,7 +178,8 @@
         //LOGV("previewThread: generated frame to buffer %d", mCurrentPreviewFrame);
         
         // Notify the client of a new frame.
-        mPreviewCallback(buffer, mPreviewCallbackCookie);
+        if (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME)
+            mDataCb(CAMERA_MSG_PREVIEW_FRAME, buffer, mCallbackCookie);
     
         // Advance the buffer pointer.
         mCurrentPreviewFrame = (mCurrentPreviewFrame + 1) % kBufferCount;
@@ -162,15 +191,13 @@
     return NO_ERROR;
 }
 
-status_t CameraHardwareStub::startPreview(preview_callback cb, void* user)
+status_t CameraHardwareStub::startPreview()
 {
     Mutex::Autolock lock(mLock);
     if (mPreviewThread != 0) {
         // already running
         return INVALID_OPERATION;
     }
-    mPreviewCallback = cb;
-    mPreviewCallbackCookie = user;
     mPreviewThread = new PreviewThread(this);
     return NO_ERROR;
 }
@@ -197,7 +224,7 @@
     return mPreviewThread != 0;
 }
 
-status_t CameraHardwareStub::startRecording(recording_callback cb, void* user)
+status_t CameraHardwareStub::startRecording()
 {
     return UNKNOWN_ERROR;
 }
@@ -225,30 +252,24 @@
 
 int CameraHardwareStub::autoFocusThread()
 {
-    if (mAutoFocusCallback != NULL) {
-        mAutoFocusCallback(true, mAutoFocusCallbackCookie);
-        mAutoFocusCallback = NULL;
-        return NO_ERROR;
-    }
-    return UNKNOWN_ERROR;
+    if (mMsgEnabled & CAMERA_MSG_FOCUS)
+        mNotifyCb(CAMERA_MSG_FOCUS, true, 0, mCallbackCookie);
+    return NO_ERROR;
 }
 
-status_t CameraHardwareStub::autoFocus(autofocus_callback af_cb,
-                                       void *user)
+status_t CameraHardwareStub::autoFocus()
 {
     Mutex::Autolock lock(mLock);
-
-    if (mAutoFocusCallback != NULL) {
-        return mAutoFocusCallback == af_cb ? NO_ERROR : INVALID_OPERATION;
-    }
-
-    mAutoFocusCallback = af_cb;
-    mAutoFocusCallbackCookie = user;
     if (createThread(beginAutoFocusThread, this) == false)
         return UNKNOWN_ERROR;
     return NO_ERROR;
 }
 
+status_t CameraHardwareStub::cancelAutoFocus()
+{
+    return NO_ERROR;
+}
+
 /*static*/ int CameraHardwareStub::beginPictureThread(void *cookie)
 {
     CameraHardwareStub *c = (CameraHardwareStub *)cookie;
@@ -257,10 +278,10 @@
 
 int CameraHardwareStub::pictureThread()
 {
-    if (mShutterCallback)
-        mShutterCallback(mPictureCallbackCookie);
+    if (mMsgEnabled & CAMERA_MSG_SHUTTER)
+        mNotifyCb(CAMERA_MSG_SHUTTER, 0, 0, mCallbackCookie);
 
-    if (mRawPictureCallback) {
+    if (mMsgEnabled & CAMERA_MSG_RAW_IMAGE) {
         //FIXME: use a canned YUV image!
         // In the meantime just make another fake camera picture.
         int w, h;
@@ -268,42 +289,28 @@
         sp<MemoryBase> mem = new MemoryBase(mRawHeap, 0, w * 2 * h);
         FakeCamera cam(w, h);
         cam.getNextFrameAsYuv422((uint8_t *)mRawHeap->base());
-        if (mRawPictureCallback)
-            mRawPictureCallback(mem, mPictureCallbackCookie);
+        mDataCb(CAMERA_MSG_RAW_IMAGE, mem, mCallbackCookie);
     }
 
-    if (mJpegPictureCallback) {
+    if (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE) {
         sp<MemoryHeapBase> heap = new MemoryHeapBase(kCannedJpegSize);
         sp<MemoryBase> mem = new MemoryBase(heap, 0, kCannedJpegSize);
         memcpy(heap->base(), kCannedJpeg, kCannedJpegSize);
-        if (mJpegPictureCallback)
-            mJpegPictureCallback(mem, mPictureCallbackCookie);
+        mDataCb(CAMERA_MSG_COMPRESSED_IMAGE, mem, mCallbackCookie);
     }
     return NO_ERROR;
 }
 
-status_t CameraHardwareStub::takePicture(shutter_callback shutter_cb,
-                                         raw_callback raw_cb,
-                                         jpeg_callback jpeg_cb,
-                                         void* user)
+status_t CameraHardwareStub::takePicture()
 {
     stopPreview();
-    mShutterCallback = shutter_cb;
-    mRawPictureCallback = raw_cb;
-    mJpegPictureCallback = jpeg_cb;
-    mPictureCallbackCookie = user;
     if (createThread(beginPictureThread, this) == false)
         return -1;
     return NO_ERROR;
 }
 
-status_t CameraHardwareStub::cancelPicture(bool cancel_shutter,
-                                           bool cancel_raw,
-                                           bool cancel_jpeg)
+status_t CameraHardwareStub::cancelPicture()
 {
-    if (cancel_shutter) mShutterCallback = NULL;
-    if (cancel_raw) mRawPictureCallback = NULL;
-    if (cancel_jpeg) mJpegPictureCallback = NULL;
     return NO_ERROR;
 }
 
@@ -361,6 +368,12 @@
     return mParameters;
 }
 
+status_t CameraHardwareStub::sendCommand(int32_t command, int32_t arg1,
+                                         int32_t arg2)
+{
+    return BAD_VALUE;
+}
+
 void CameraHardwareStub::release()
 {
 }
diff --git a/camera/libcameraservice/CameraHardwareStub.h b/camera/libcameraservice/CameraHardwareStub.h
index 0d26d47..8a67024 100644
--- a/camera/libcameraservice/CameraHardwareStub.h
+++ b/camera/libcameraservice/CameraHardwareStub.h
@@ -21,8 +21,8 @@
 #include "FakeCamera.h"
 #include <utils/threads.h>
 #include <ui/CameraHardwareInterface.h>
-#include <utils/MemoryBase.h>
-#include <utils/MemoryHeapBase.h>
+#include <binder/MemoryBase.h>
+#include <binder/MemoryHeapBase.h>
 #include <utils/threads.h>
 
 namespace android {
@@ -32,26 +32,33 @@
     virtual sp<IMemoryHeap> getPreviewHeap() const;
     virtual sp<IMemoryHeap> getRawHeap() const;
 
-    virtual status_t    startPreview(preview_callback cb, void* user);
+    virtual void        setCallbacks(notify_callback notify_cb,
+                                     data_callback data_cb,
+                                     data_callback_timestamp data_cb_timestamp,
+                                     void* user);
+
+    virtual void        enableMsgType(int32_t msgType);
+    virtual void        disableMsgType(int32_t msgType);
+    virtual bool        msgTypeEnabled(int32_t msgType);
+
+    virtual status_t    startPreview();
     virtual void        stopPreview();
     virtual bool        previewEnabled();
 
-    virtual status_t    startRecording(recording_callback cb, void* user);
+    virtual status_t    startRecording();
     virtual void        stopRecording();
     virtual bool        recordingEnabled();
     virtual void        releaseRecordingFrame(const sp<IMemory>& mem);
 
-    virtual status_t    autoFocus(autofocus_callback, void *user);
-    virtual status_t    takePicture(shutter_callback,
-                                    raw_callback,
-                                    jpeg_callback,
-                                    void* user);
-    virtual status_t    cancelPicture(bool cancel_shutter,
-                                      bool cancel_raw,
-                                      bool cancel_jpeg);
+    virtual status_t    autoFocus();
+    virtual status_t    cancelAutoFocus();
+    virtual status_t    takePicture();
+    virtual status_t    cancelPicture();
     virtual status_t    dump(int fd, const Vector<String16>& args) const;
     virtual status_t    setParameters(const CameraParameters& params);
     virtual CameraParameters  getParameters() const;
+    virtual status_t    sendCommand(int32_t command, int32_t arg1,
+                                    int32_t arg2);
     virtual void release();
 
     static sp<CameraHardwareInterface> createInstance();
@@ -67,8 +74,15 @@
     class PreviewThread : public Thread {
         CameraHardwareStub* mHardware;
     public:
-        PreviewThread(CameraHardwareStub* hw)
-            : Thread(false), mHardware(hw) { }
+        PreviewThread(CameraHardwareStub* hw) :
+#ifdef SINGLE_PROCESS
+            // In single process mode this thread needs to be a java thread,
+            // since we won't be calling through the binder.
+            Thread(true),
+#else
+            Thread(false),
+#endif
+              mHardware(hw) { }
         virtual void onFirstRef() {
             run("CameraPreviewThread", PRIORITY_URGENT_DISPLAY);
         }
@@ -102,18 +116,15 @@
     bool                mPreviewRunning;
     int                 mPreviewFrameSize;
 
-    shutter_callback    mShutterCallback;
-    raw_callback        mRawPictureCallback;
-    jpeg_callback       mJpegPictureCallback;
-    void                *mPictureCallbackCookie;
-
     // protected by mLock
     sp<PreviewThread>   mPreviewThread;
-    preview_callback    mPreviewCallback;
-    void                *mPreviewCallbackCookie;
 
-    autofocus_callback  mAutoFocusCallback;
-    void                *mAutoFocusCallbackCookie;
+    notify_callback    mNotifyCb;
+    data_callback      mDataCb;
+    data_callback_timestamp mDataCbTimestamp;
+    void               *mCallbackCookie;
+
+    int32_t             mMsgEnabled;
 
     // only used from PreviewThread
     int                 mCurrentPreviewFrame;
diff --git a/camera/libcameraservice/CameraService.cpp b/camera/libcameraservice/CameraService.cpp
index e4b6791..df59dcf 100644
--- a/camera/libcameraservice/CameraService.cpp
+++ b/camera/libcameraservice/CameraService.cpp
@@ -20,12 +20,12 @@
 #define LOG_TAG "CameraService"
 #include <utils/Log.h>
 
-#include <utils/IServiceManager.h>
-#include <utils/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/IPCThreadState.h>
 #include <utils/String16.h>
 #include <utils/Errors.h>
-#include <utils/MemoryBase.h>
-#include <utils/MemoryHeapBase.h>
+#include <binder/MemoryBase.h>
+#include <binder/MemoryHeapBase.h>
 #include <ui/ICameraService.h>
 
 #include <media/mediaplayer.h>
@@ -33,7 +33,6 @@
 #include "CameraService.h"
 
 #include <cutils/atomic.h>
-#include <cutils/properties.h>
 
 namespace android {
 
@@ -60,6 +59,7 @@
 #define DEBUG_DUMP_PREVIEW_FRAME_TO_FILE 0 /* n-th frame to write */
 #define DEBUG_DUMP_JPEG_SNAPSHOT_TO_FILE 0
 #define DEBUG_DUMP_YUV_SNAPSHOT_TO_FILE 0
+#define DEBUG_DUMP_POSTVIEW_SNAPSHOT_TO_FILE 0
 
 #if DEBUG_DUMP_PREVIEW_FRAME_TO_FILE
 static int debug_frame_cnt;
@@ -195,17 +195,11 @@
     android_atomic_dec(&mUsers);
 }
 
-static sp<MediaPlayer> newMediaPlayer(const char *file) 
+static sp<MediaPlayer> newMediaPlayer(const char *file)
 {
     sp<MediaPlayer> mp = new MediaPlayer();
     if (mp->setDataSource(file) == NO_ERROR) {
-        char value[PROPERTY_VALUE_MAX];
-        property_get("ro.camera.sound.forced", value, "0");
-        if (atoi(value)) {
-            mp->setAudioStreamType(AudioSystem::ENFORCED_AUDIBLE);
-        } else {
-            mp->setAudioStreamType(AudioSystem::SYSTEM);            
-        }
+        mp->setAudioStreamType(AudioSystem::ENFORCED_AUDIBLE);
         mp->prepare();
     } else {
         mp.clear();
@@ -225,8 +219,20 @@
     mHardware = openCameraHardware();
     mUseOverlay = mHardware->useOverlay();
 
+    mHardware->setCallbacks(notifyCallback,
+                            dataCallback,
+                            dataCallbackTimestamp,
+                            mCameraService.get());
+
+    // Enable zoom, error, and focus messages by default
+    mHardware->enableMsgType(CAMERA_MSG_ERROR |
+                             CAMERA_MSG_ZOOM |
+                             CAMERA_MSG_FOCUS);
+
     mMediaPlayerClick = newMediaPlayer("/system/media/audio/ui/camera_click.ogg");
     mMediaPlayerBeep = newMediaPlayer("/system/media/audio/ui/VideoRecord.ogg");
+    mOverlayW = 0;
+    mOverlayH = 0;
 
     // Callback is disabled by default
     mPreviewCallbackFlag = FRAME_CALLBACK_FLAG_NOOP;
@@ -261,7 +267,7 @@
 status_t CameraService::Client::unlock()
 {
     int callingPid = getCallingPid();
-    LOGD("unlock from pid %d (mClientPid %d)", callingPid, mClientPid);    
+    LOGD("unlock from pid %d (mClientPid %d)", callingPid, mClientPid);
     Mutex::Autolock _l(mLock);
     // allow anyone to use camera
     status_t result = checkPid();
@@ -303,7 +309,7 @@
             oldClient = mCameraClient;
 
             // did the client actually change?
-            if (client->asBinder() == mCameraClient->asBinder()) {
+            if ((mCameraClient != NULL) && (client->asBinder() == mCameraClient->asBinder())) {
                 LOGD("Connect to the same client");
                 return NO_ERROR;
             }
@@ -396,9 +402,20 @@
     // idle state.
     mHardware->stopPreview();
     // Cancel all picture callbacks.
-    mHardware->cancelPicture(true, true, true);
+    mHardware->disableMsgType(CAMERA_MSG_SHUTTER |
+                              CAMERA_MSG_POSTVIEW_FRAME |
+                              CAMERA_MSG_RAW_IMAGE |
+                              CAMERA_MSG_COMPRESSED_IMAGE);
+    mHardware->cancelPicture();
+    // Turn off remaining messages.
+    mHardware->disableMsgType(CAMERA_MSG_ALL_MSGS);
     // Release the hardware resources.
     mHardware->release();
+    // Release the held overlay resources.
+    if (mUseOverlay)
+    {
+        mOverlayRef = 0;
+    }
     mHardware.clear();
 
     mCameraService->removeClient(mCameraClient);
@@ -420,11 +437,21 @@
     result = NO_ERROR;
     // asBinder() is safe on NULL (returns NULL)
     if (surface->asBinder() != mSurface->asBinder()) {
-        if (mSurface != 0 && !mUseOverlay) {
+        if (mSurface != 0) {
             LOGD("clearing old preview surface %p", mSurface.get());
-            mSurface->unregisterBuffers();
+            if ( !mUseOverlay)
+            {
+                mSurface->unregisterBuffers();
+            }
+            else
+            {
+                // Force the destruction of any previous overlay
+                sp<Overlay> dummy;
+                mHardware->setOverlay( dummy );
+            }
         }
         mSurface = surface;
+        mOverlayRef = 0;
         // If preview has been already started, set overlay or register preview
         // buffers now.
         if (mHardware->previewEnabled()) {
@@ -446,6 +473,13 @@
     Mutex::Autolock lock(mLock);
     if (checkPid() != NO_ERROR) return;
     mPreviewCallbackFlag = callback_flag;
+
+    if(mUseOverlay) {
+        if(mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ENABLE_MASK)
+            mHardware->enableMsgType(CAMERA_MSG_PREVIEW_FRAME);
+        else
+            mHardware->disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
+    }
 }
 
 // start preview mode
@@ -504,7 +538,7 @@
     }
 
     // start recording mode
-    ret = mHardware->startRecording(recordingCallback, mCameraService.get());
+    ret = mHardware->startRecording();
     if (ret != NO_ERROR) {
         LOGE("mHardware->startRecording() failed with status %d", ret);
     }
@@ -518,27 +552,47 @@
     CameraParameters params(mHardware->getParameters());
     params.getPreviewSize(&w, &h);
 
-    const char *format = params.getPreviewFormat();
-    int fmt;
-    if (!strcmp(format, "yuv422i"))
-        fmt = OVERLAY_FORMAT_YCbCr_422_I;
-    else if (!strcmp(format, "rgb565"))
-        fmt = OVERLAY_FORMAT_RGB_565;
-    else {
-        LOGE("Invalid preview format for overlays");
-        return -EINVAL;
+    if ( w != mOverlayW || h != mOverlayH )
+    {
+        // Force the destruction of any previous overlay
+        sp<Overlay> dummy;
+        mHardware->setOverlay( dummy );
+        mOverlayRef = 0;
     }
 
     status_t ret = NO_ERROR;
     if (mSurface != 0) {
-        sp<OverlayRef> ref = mSurface->createOverlay(w, h, fmt);
-        ret = mHardware->setOverlay(new Overlay(ref));
+        if (mOverlayRef.get() == NULL) {
+
+            // FIXME:
+            // Surfaceflinger may hold onto the previous overlay reference for some
+            // time after we try to destroy it. retry a few times. In the future, we
+            // should make the destroy call block, or possibly specify that we can
+            // wait in the createOverlay call if the previous overlay is in the 
+            // process of being destroyed.
+            for (int retry = 0; retry < 50; ++retry) {
+                mOverlayRef = mSurface->createOverlay(w, h, OVERLAY_FORMAT_DEFAULT);
+                if (mOverlayRef != NULL) break;
+                LOGD("Overlay create failed - retrying");
+                usleep(20000);
+            }
+            if ( mOverlayRef.get() == NULL )
+            {
+                LOGE("Overlay Creation Failed!");
+                return -EINVAL;
+            }
+            ret = mHardware->setOverlay(new Overlay(mOverlayRef));
+        }
     } else {
         ret = mHardware->setOverlay(NULL);
     }
     if (ret != NO_ERROR) {
         LOGE("mHardware->setOverlay() failed with status %d\n", ret);
     }
+
+    mOverlayW = w;
+    mOverlayH = h;
+
     return ret;
 }
 
@@ -588,10 +642,10 @@
             ret = setOverlay();
         }
         if (ret != NO_ERROR) return ret;
-        ret = mHardware->startPreview(NULL, mCameraService.get());
+        ret = mHardware->startPreview();
     } else {
-        ret = mHardware->startPreview(previewCallback,
-                                      mCameraService.get());
+        mHardware->enableMsgType(CAMERA_MSG_PREVIEW_FRAME);
+        ret = mHardware->startPreview();
         if (ret != NO_ERROR) return ret;
         // If preview display has been set, register preview buffers now.
         if (mSurface != 0) {
@@ -606,7 +660,7 @@
 status_t CameraService::Client::startPreview()
 {
     LOGD("startPreview (pid %d)", getCallingPid());
-    
+
     return startCameraMode(CAMERA_PREVIEW_MODE);
 }
 
@@ -618,6 +672,9 @@
         mMediaPlayerBeep->seekTo(0);
         mMediaPlayerBeep->start();
     }
+
+    mHardware->enableMsgType(CAMERA_MSG_VIDEO_FRAME);
+
     return startCameraMode(CAMERA_RECORDING_MODE);
 }
 
@@ -626,21 +683,30 @@
 {
     LOGD("stopPreview (pid %d)", getCallingPid());
 
-    Mutex::Autolock lock(mLock);
-    if (checkPid() != NO_ERROR) return;
+    // hold main lock during state transition
+    {
+        Mutex::Autolock lock(mLock);
+        if (checkPid() != NO_ERROR) return;
 
-    if (mHardware == 0) {
-        LOGE("mHardware is NULL, returning.");
-        return;
+        if (mHardware == 0) {
+            LOGE("mHardware is NULL, returning.");
+            return;
+        }
+
+        mHardware->stopPreview();
+        mHardware->disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
+        LOGD("stopPreview(), hardware stopped OK");
+
+        if (mSurface != 0 && !mUseOverlay) {
+            mSurface->unregisterBuffers();
+        }
     }
 
-    mHardware->stopPreview();
-    LOGD("stopPreview(), hardware stopped OK");
-
-    if (mSurface != 0 && !mUseOverlay) {
-        mSurface->unregisterBuffers();
+    // hold preview buffer lock
+    {
+        Mutex::Autolock lock(mPreviewLock);
+        mPreviewBuffer.clear();
     }
-    mPreviewBuffer.clear();
 }
 
 // stop recording mode
@@ -648,21 +714,31 @@
 {
     LOGD("stopRecording (pid %d)", getCallingPid());
 
-    Mutex::Autolock lock(mLock);
-    if (checkPid() != NO_ERROR) return;
+    // hold main lock during state transition
+    {
+        Mutex::Autolock lock(mLock);
+        if (checkPid() != NO_ERROR) return;
 
-    if (mHardware == 0) {
-        LOGE("mHardware is NULL, returning.");
-        return;
+        if (mHardware == 0) {
+            LOGE("mHardware is NULL, returning.");
+            return;
+        }
+
+        if (mMediaPlayerBeep.get() != NULL) {
+            mMediaPlayerBeep->seekTo(0);
+            mMediaPlayerBeep->start();
+        }
+
+        mHardware->stopRecording();
+        mHardware->disableMsgType(CAMERA_MSG_VIDEO_FRAME);
+        LOGD("stopRecording(), hardware stopped OK");
     }
 
-    if (mMediaPlayerBeep.get() != NULL) {
-        mMediaPlayerBeep->seekTo(0);
-        mMediaPlayerBeep->start();
+    // hold preview buffer lock
+    {
+        Mutex::Autolock lock(mPreviewLock);
+        mPreviewBuffer.clear();
     }
-    mHardware->stopRecording();
-    LOGD("stopRecording(), hardware stopped OK");
-    mPreviewBuffer.clear();
 }
 
 // release a recording frame
@@ -749,66 +825,6 @@
 }
 #endif
 
-// preview callback - frame buffer update
-void CameraService::Client::previewCallback(const sp<IMemory>& mem, void* user)
-{
-    LOGV("previewCallback()");
-    sp<Client> client = getClientFromCookie(user);
-    if (client == 0) {
-        return;
-    }
-
-#if DEBUG_HEAP_LEAKS && 0 // debugging
-    if (gWeakHeap == NULL) {
-        ssize_t offset;
-        size_t size;
-        sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
-        if (gWeakHeap != heap) {
-            LOGD("SETTING PREVIEW HEAP");
-            heap->trackMe(true, true);
-            gWeakHeap = heap;
-        }
-    }
-#endif
-
-#if DEBUG_DUMP_PREVIEW_FRAME_TO_FILE
-    {
-        if (debug_frame_cnt++ == DEBUG_DUMP_PREVIEW_FRAME_TO_FILE) {
-            ssize_t offset;
-            size_t size;
-            sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
-            dump_to_file("/data/preview.yuv",
-                         (uint8_t *)heap->base() + offset, size);
-        }
-    }
-#endif
-
-    // The strong pointer guarantees the client will exist, but no lock is held.
-    client->postPreviewFrame(mem);
-
-#if DEBUG_CLIENT_REFERENCES
-    //**** if the client's refcount is 1, then we are about to destroy it here,
-    // which is bad--print all refcounts.
-    if (client->getStrongCount() == 1) {
-        LOGE("++++++++++++++++ (PREVIEW) THIS WILL CAUSE A LOCKUP!");
-        client->printRefs();
-    }
-#endif
-}
-
-// recording callback
-void CameraService::Client::recordingCallback(nsecs_t timestamp, const sp<IMemory>& mem, void* user)
-{
-    LOGV("recordingCallback");
-    sp<Client> client = getClientFromCookie(user);
-    if (client == 0) {
-        return;
-    }
-    // The strong pointer guarantees the client will exist, but no lock is held.
-    client->postRecordingFrame(timestamp, mem);
-}
-
-// take a picture - image is returned in callback
 status_t CameraService::Client::autoFocus()
 {
     LOGD("autoFocus (pid %d)", getCallingPid());
@@ -822,8 +838,23 @@
         return INVALID_OPERATION;
     }
 
-    return mHardware->autoFocus(autoFocusCallback,
-                                mCameraService.get());
+    return mHardware->autoFocus();
+}
+
+status_t CameraService::Client::cancelAutoFocus()
+{
+    LOGD("cancelAutoFocus (pid %d)", getCallingPid());
+
+    Mutex::Autolock lock(mLock);
+    status_t result = checkPid();
+    if (result != NO_ERROR) return result;
+
+    if (mHardware == 0) {
+        LOGE("mHardware is NULL, returning.");
+        return INVALID_OPERATION;
+    }
+
+    return mHardware->cancelAutoFocus();
 }
 
 // take a picture - image is returned in callback
@@ -840,65 +871,155 @@
         return INVALID_OPERATION;
     }
 
-    return mHardware->takePicture(shutterCallback,
-                                  yuvPictureCallback,
-                                  jpegPictureCallback,
-                                  mCameraService.get());
+    mHardware->enableMsgType(CAMERA_MSG_SHUTTER |
+                             CAMERA_MSG_POSTVIEW_FRAME |
+                             CAMERA_MSG_RAW_IMAGE |
+                             CAMERA_MSG_COMPRESSED_IMAGE);
+
+    return mHardware->takePicture();
 }
 
-// picture callback - snapshot taken
-void CameraService::Client::shutterCallback(void *user)
+// snapshot taken
+void CameraService::Client::handleShutter(
+    image_rect_type *size // The width and height of yuv picture for
+                          // registerBuffer. If this is NULL, use the picture
+                          // size from parameters.
+)
 {
-    sp<Client> client = getClientFromCookie(user);
-    if (client == 0) {
-        return;
-    }
-
     // Play shutter sound.
-    if (client->mMediaPlayerClick.get() != NULL) {
-        client->mMediaPlayerClick->seekTo(0);
-        client->mMediaPlayerClick->start();
+    if (mMediaPlayerClick.get() != NULL) {
+        mMediaPlayerClick->seekTo(0);
+        mMediaPlayerClick->start();
     }
 
     // Screen goes black after the buffer is unregistered.
-    if (client->mSurface != 0 && !client->mUseOverlay) {
-        client->mSurface->unregisterBuffers();
+    if (mSurface != 0 && !mUseOverlay) {
+        mSurface->unregisterBuffers();
     }
 
-    client->postShutter();
+    sp<ICameraClient> c = mCameraClient;
+    if (c != NULL) {
+        c->notifyCallback(CAMERA_MSG_SHUTTER, 0, 0);
+    }
+    mHardware->disableMsgType(CAMERA_MSG_SHUTTER);
 
     // It takes some time before yuvPicture callback to be called.
     // Register the buffer for raw image here to reduce latency.
-    if (client->mSurface != 0 && !client->mUseOverlay) {
+    if (mSurface != 0 && !mUseOverlay) {
         int w, h;
-        CameraParameters params(client->mHardware->getParameters());
-        params.getPictureSize(&w, &h);
+        CameraParameters params(mHardware->getParameters());
         uint32_t transform = 0;
         if (params.getOrientation() == CameraParameters::CAMERA_ORIENTATION_PORTRAIT) {
             LOGV("portrait mode");
             transform = ISurface::BufferHeap::ROT_90;
         }
-        ISurface::BufferHeap buffers(w, h, w, h,
-            PIXEL_FORMAT_YCbCr_420_SP, transform, 0, client->mHardware->getRawHeap());
 
-        client->mSurface->registerBuffers(buffers);
+        if (size == NULL) {
+            params.getPictureSize(&w, &h);
+        } else {
+            w = size->width;
+            h = size->height;
+            w &= ~1;
+            h &= ~1;
+            LOGD("Snapshot image width=%d, height=%d", w, h);
+        }
+        ISurface::BufferHeap buffers(w, h, w, h,
+            PIXEL_FORMAT_YCbCr_420_SP, transform, 0, mHardware->getRawHeap());
+
+        mSurface->registerBuffers(buffers);
     }
 }
 
-// picture callback - raw image ready
-void CameraService::Client::yuvPictureCallback(const sp<IMemory>& mem,
-                                               void *user)
+// preview callback - frame buffer update
+void CameraService::Client::handlePreviewData(const sp<IMemory>& mem)
 {
-    sp<Client> client = getClientFromCookie(user);
-    if (client == 0) {
-        return;
+    ssize_t offset;
+    size_t size;
+    sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
+
+#if DEBUG_HEAP_LEAKS && 0 // debugging
+    if (gWeakHeap == NULL) {
+        if (gWeakHeap != heap) {
+            LOGD("SETTING PREVIEW HEAP");
+            heap->trackMe(true, true);
+            gWeakHeap = heap;
+        }
     }
-    if (mem == NULL) {
-        client->postRaw(NULL);
-        client->postError(UNKNOWN_ERROR);
+#endif
+#if DEBUG_DUMP_PREVIEW_FRAME_TO_FILE
+    {
+        if (debug_frame_cnt++ == DEBUG_DUMP_PREVIEW_FRAME_TO_FILE) {
+            dump_to_file("/data/preview.yuv",
+                         (uint8_t *)heap->base() + offset, size);
+        }
+    }
+#endif
+
+    if (!mUseOverlay)
+    {
+        Mutex::Autolock surfaceLock(mSurfaceLock);
+        if (mSurface != NULL) {
+            mSurface->postBuffer(offset);
+        }
+    }
+
+    // local copy of the callback flags
+    int flags = mPreviewCallbackFlag;
+
+    // is callback enabled?
+    if (!(flags & FRAME_CALLBACK_FLAG_ENABLE_MASK)) {
+        // If the enable bit is off, the copy-out and one-shot bits are ignored
+        LOGV("frame callback is diabled");
         return;
     }
 
+    // hold a strong pointer to the client
+    sp<ICameraClient> c = mCameraClient;
+
+    // clear callback flags if no client or one-shot mode
+    if ((c == NULL) || (mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ONE_SHOT_MASK)) {
+        LOGV("Disable preview callback");
+        mPreviewCallbackFlag &= ~(FRAME_CALLBACK_FLAG_ONE_SHOT_MASK |
+                                FRAME_CALLBACK_FLAG_COPY_OUT_MASK |
+                                FRAME_CALLBACK_FLAG_ENABLE_MASK);
+        // TODO: Shouldn't we use this API for non-overlay hardware as well?
+        if (mUseOverlay)
+            mHardware->disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
+    }
+
+    // Is the received frame copied out or not?
+    if (flags & FRAME_CALLBACK_FLAG_COPY_OUT_MASK) {
+        LOGV("frame is copied");
+        copyFrameAndPostCopiedFrame(c, heap, offset, size);
+    } else {
+        LOGV("frame is forwarded");
+        c->dataCallback(CAMERA_MSG_PREVIEW_FRAME, mem);
+    }
+}
+
+// picture callback - postview image ready
+void CameraService::Client::handlePostview(const sp<IMemory>& mem)
+{
+#if DEBUG_DUMP_POSTVIEW_SNAPSHOT_TO_FILE // for testing pursposes only
+    {
+        ssize_t offset;
+        size_t size;
+        sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
+        dump_to_file("/data/postview.yuv",
+                     (uint8_t *)heap->base() + offset, size);
+    }
+#endif
+
+    sp<ICameraClient> c = mCameraClient;
+    if (c != NULL) {
+        c->dataCallback(CAMERA_MSG_POSTVIEW_FRAME, mem);
+    }
+    mHardware->disableMsgType(CAMERA_MSG_POSTVIEW_FRAME);
+}
+
+// picture callback - raw image ready
+void CameraService::Client::handleRawPicture(const sp<IMemory>& mem)
+{
     ssize_t offset;
     size_t size;
     sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
@@ -906,44 +1027,27 @@
     gWeakHeap = heap; // debugging
 #endif
 
-    //LOGV("yuvPictureCallback(%d, %d, %p)", offset, size, user);
+    //LOGV("handleRawPicture(%d, %d)", offset, size);
 #if DEBUG_DUMP_YUV_SNAPSHOT_TO_FILE // for testing pursposes only
     dump_to_file("/data/photo.yuv",
                  (uint8_t *)heap->base() + offset, size);
 #endif
 
     // Put the YUV version of the snapshot in the preview display.
-    if (client->mSurface != 0 && !client->mUseOverlay) {
-        client->mSurface->postBuffer(offset);
+    if (mSurface != 0 && !mUseOverlay) {
+        mSurface->postBuffer(offset);
     }
 
-    client->postRaw(mem);
-
-#if DEBUG_CLIENT_REFERENCES
-    //**** if the client's refcount is 1, then we are about to destroy it here,
-    // which is bad--print all refcounts.
-    if (client->getStrongCount() == 1) {
-        LOGE("++++++++++++++++ (RAW) THIS WILL CAUSE A LOCKUP!");
-        client->printRefs();
+    sp<ICameraClient> c = mCameraClient;
+    if (c != NULL) {
+        c->dataCallback(CAMERA_MSG_RAW_IMAGE, mem);
     }
-#endif
+    mHardware->disableMsgType(CAMERA_MSG_RAW_IMAGE);
 }
 
-// picture callback - jpeg ready
-void CameraService::Client::jpegPictureCallback(const sp<IMemory>& mem, void *user)
+// picture callback - compressed picture ready
+void CameraService::Client::handleCompressedPicture(const sp<IMemory>& mem)
 {
-    sp<Client> client = getClientFromCookie(user);
-    if (client == 0) {
-        return;
-    }
-    if (mem == NULL) {
-        client->postJpeg(NULL);
-        client->postError(UNKNOWN_ERROR);
-        return;
-    }
-
-    /** We absolutely CANNOT call into user code with a lock held **/
-
 #if DEBUG_DUMP_JPEG_SNAPSHOT_TO_FILE // for testing pursposes only
     {
         ssize_t offset;
@@ -954,32 +1058,117 @@
     }
 #endif
 
-    client->postJpeg(mem);
-
-#if DEBUG_CLIENT_REFERENCES
-    //**** if the client's refcount is 1, then we are about to destroy it here,
-    // which is bad--print all refcounts.
-    if (client->getStrongCount() == 1) {
-        LOGE("++++++++++++++++ (JPEG) THIS WILL CAUSE A LOCKUP!");
-        client->printRefs();
+    sp<ICameraClient> c = mCameraClient;
+    if (c != NULL) {
+        c->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mem);
     }
-#endif
+    mHardware->disableMsgType(CAMERA_MSG_COMPRESSED_IMAGE);
 }
 
-void CameraService::Client::autoFocusCallback(bool focused, void *user)
+void CameraService::Client::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2, void* user)
 {
-    LOGV("autoFocusCallback");
+    LOGV("notifyCallback(%d)", msgType);
 
     sp<Client> client = getClientFromCookie(user);
     if (client == 0) {
         return;
     }
 
-    client->postAutoFocus(focused);
+    switch (msgType) {
+        case CAMERA_MSG_SHUTTER:
+            // ext1 is the dimension of the yuv picture.
+            client->handleShutter((image_rect_type *)ext1);
+            break;
+        default:
+            sp<ICameraClient> c = client->mCameraClient;
+            if (c != NULL) {
+                c->notifyCallback(msgType, ext1, ext2);
+            }
+            break;
+    }
 
 #if DEBUG_CLIENT_REFERENCES
     if (client->getStrongCount() == 1) {
-        LOGE("++++++++++++++++ (AUTOFOCUS) THIS WILL CAUSE A LOCKUP!");
+        LOGE("++++++++++++++++ (NOTIFY CALLBACK) THIS WILL CAUSE A LOCKUP!");
+        client->printRefs();
+    }
+#endif
+}
+
+void CameraService::Client::dataCallback(int32_t msgType, const sp<IMemory>& dataPtr, void* user)
+{
+    LOGV("dataCallback(%d)", msgType);
+
+    sp<Client> client = getClientFromCookie(user);
+    if (client == 0) {
+        return;
+    }
+
+    sp<ICameraClient> c = client->mCameraClient;
+    if (dataPtr == NULL) {
+        LOGE("Null data returned in data callback");
+        if (c != NULL) {
+            c->notifyCallback(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
+            c->dataCallback(msgType, NULL);
+        }
+        return;
+    }
+
+    switch (msgType) {
+        case CAMERA_MSG_PREVIEW_FRAME:
+            client->handlePreviewData(dataPtr);
+            break;
+        case CAMERA_MSG_POSTVIEW_FRAME:
+            client->handlePostview(dataPtr);
+            break;
+        case CAMERA_MSG_RAW_IMAGE:
+            client->handleRawPicture(dataPtr);
+            break;
+        case CAMERA_MSG_COMPRESSED_IMAGE:
+            client->handleCompressedPicture(dataPtr);
+            break;
+        default:
+            if (c != NULL) {
+                c->dataCallback(msgType, dataPtr);
+            }
+            break;
+    }
+
+#if DEBUG_CLIENT_REFERENCES
+    if (client->getStrongCount() == 1) {
+        LOGE("++++++++++++++++ (DATA CALLBACK) THIS WILL CAUSE A LOCKUP!");
+        client->printRefs();
+    }
+#endif
+}
+
+void CameraService::Client::dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType,
+                                                  const sp<IMemory>& dataPtr, void* user)
+{
+    LOGV("dataCallbackTimestamp(%d)", msgType);
+
+    sp<Client> client = getClientFromCookie(user);
+    if (client == 0) {
+        return;
+    }
+    sp<ICameraClient> c = client->mCameraClient;
+
+    if (dataPtr == NULL) {
+        LOGE("Null data returned in data with timestamp callback");
+        if (c != NULL) {
+            c->notifyCallback(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
+            c->dataCallbackTimestamp(0, msgType, NULL);
+        }
+        return;
+    }
+
+    if (c != NULL) {
+        c->dataCallbackTimestamp(timestamp, msgType, dataPtr);
+    }
+
+#if DEBUG_CLIENT_REFERENCES
+    if (client->getStrongCount() == 1) {
+        LOGE("++++++++++++++++ (DATA CALLBACK TIMESTAMP) THIS WILL CAUSE A LOCKUP!");
         client->printRefs();
     }
 #endif
@@ -1000,8 +1189,7 @@
     }
 
     CameraParameters p(params);
-    mHardware->setParameters(p);
-    return NO_ERROR;
+    return mHardware->setParameters(p);
 }
 
 // get preview/capture parameters - key/value pairs
@@ -1019,114 +1207,55 @@
     return params;
 }
 
-void CameraService::Client::postAutoFocus(bool focused)
+status_t CameraService::Client::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2)
 {
-    LOGV("postAutoFocus");
-    mCameraClient->notifyCallback(CAMERA_MSG_FOCUS, (int32_t)focused, 0);
+    LOGD("sendCommand (pid %d)", getCallingPid());
+    Mutex::Autolock lock(mLock);
+    status_t result = checkPid();
+    if (result != NO_ERROR) return result;
+
+    if (mHardware == 0) {
+        LOGE("mHardware is NULL, returning.");
+        return INVALID_OPERATION;
+    }
+
+    return mHardware->sendCommand(cmd, arg1, arg2);
 }
 
-void CameraService::Client::postShutter()
-{
-    LOGD("postShutter");
-    mCameraClient->notifyCallback(CAMERA_MSG_SHUTTER, 0, 0);
-}
-
-void CameraService::Client::postRaw(const sp<IMemory>& mem)
-{
-    LOGD("postRaw");
-    mCameraClient->dataCallback(CAMERA_MSG_RAW_IMAGE, mem);
-}
-
-void CameraService::Client::postJpeg(const sp<IMemory>& mem)
-{
-    LOGD("postJpeg");
-    mCameraClient->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mem);
-}
-
-void CameraService::Client::copyFrameAndPostCopiedFrame(sp<IMemoryHeap> heap, size_t offset, size_t size)
+void CameraService::Client::copyFrameAndPostCopiedFrame(const sp<ICameraClient>& client,
+        const sp<IMemoryHeap>& heap, size_t offset, size_t size)
 {
     LOGV("copyFrameAndPostCopiedFrame");
     // It is necessary to copy out of pmem before sending this to
     // the callback. For efficiency, reuse the same MemoryHeapBase
     // provided it's big enough. Don't allocate the memory or
     // perform the copy if there's no callback.
-    if (mPreviewBuffer == 0) {
-        mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
-    } else if (size > mPreviewBuffer->virtualSize()) {
-        mPreviewBuffer.clear();
-        mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
+
+    // hold the preview lock while we grab a reference to the preview buffer
+    sp<MemoryHeapBase> previewBuffer;
+    {
+        Mutex::Autolock lock(mPreviewLock);
+        if (mPreviewBuffer == 0) {
+            mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
+        } else if (size > mPreviewBuffer->virtualSize()) {
+            mPreviewBuffer.clear();
+            mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
+        }
         if (mPreviewBuffer == 0) {
             LOGE("failed to allocate space for preview buffer");
             return;
         }
+        previewBuffer = mPreviewBuffer;
     }
-    memcpy(mPreviewBuffer->base(),
+    memcpy(previewBuffer->base(),
            (uint8_t *)heap->base() + offset, size);
 
-    sp<MemoryBase> frame = new MemoryBase(mPreviewBuffer, 0, size);
+    sp<MemoryBase> frame = new MemoryBase(previewBuffer, 0, size);
     if (frame == 0) {
         LOGE("failed to allocate space for frame callback");
         return;
     }
-    mCameraClient->dataCallback(CAMERA_MSG_PREVIEW_FRAME, frame);
-}
-
-void CameraService::Client::postRecordingFrame(nsecs_t timestamp, const sp<IMemory>& frame)
-{
-    LOGV("postRecordingFrame");
-    if (frame == 0) {
-        LOGW("frame is a null pointer");
-        return;
-    }
-    mCameraClient->dataCallbackTimestamp(timestamp, CAMERA_MSG_VIDEO_FRAME, frame);
-}
-
-void CameraService::Client::postPreviewFrame(const sp<IMemory>& mem)
-{
-    LOGV("postPreviewFrame");
-    if (mem == 0) {
-        LOGW("mem is a null pointer");
-        return;
-    }
-
-    ssize_t offset;
-    size_t size;
-    sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
-    {
-        Mutex::Autolock surfaceLock(mSurfaceLock);
-        if (mSurface != NULL) {
-            mSurface->postBuffer(offset);
-        }
-    }
-
-    // Is the callback enabled or not?
-    if (!(mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ENABLE_MASK)) {
-        // If the enable bit is off, the copy-out and one-shot bits are ignored
-        LOGV("frame callback is diabled");
-        return;
-    }
-
-    // Is the received frame copied out or not?
-    if (mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_COPY_OUT_MASK) {
-        LOGV("frame is copied out");
-        copyFrameAndPostCopiedFrame(heap, offset, size);
-    } else {
-        LOGV("frame is directly sent out without copying");
-        mCameraClient->dataCallback(CAMERA_MSG_PREVIEW_FRAME, mem);
-    }
-
-    // Is this is one-shot only?
-    if (mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ONE_SHOT_MASK) {
-        LOGV("One-shot only, thus clear the bits and disable frame callback");
-        mPreviewCallbackFlag &= ~(FRAME_CALLBACK_FLAG_ONE_SHOT_MASK |
-                                FRAME_CALLBACK_FLAG_COPY_OUT_MASK |
-                                FRAME_CALLBACK_FLAG_ENABLE_MASK);
-    }
-}
-
-void CameraService::Client::postError(status_t error)
-{
-    mCameraClient->notifyCallback(CAMERA_MSG_ERROR, error, 0);
+    client->dataCallback(CAMERA_MSG_PREVIEW_FRAME, frame);
 }
 
 status_t CameraService::dump(int fd, const Vector<String16>& args)
@@ -1160,12 +1289,6 @@
 }
 
 
-#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 CameraService::onTransact(
     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
 {
diff --git a/camera/libcameraservice/CameraService.h b/camera/libcameraservice/CameraService.h
index ea93789..3e3e54f 100644
--- a/camera/libcameraservice/CameraService.h
+++ b/camera/libcameraservice/CameraService.h
@@ -23,10 +23,9 @@
 #include <ui/CameraHardwareInterface.h>
 #include <ui/Camera.h>
 
-class android::MemoryHeapBase;
-
 namespace android {
 
+class MemoryHeapBase;
 class MediaPlayer;
 
 // ----------------------------------------------------------------------------
@@ -110,6 +109,9 @@
         // auto focus
         virtual status_t        autoFocus();
 
+        // cancel auto focus
+        virtual status_t        cancelAutoFocus();
+
         // take a picture - returns an IMemory (ref-counted mmap)
         virtual status_t        takePicture();
 
@@ -119,6 +121,9 @@
         // get preview/capture parameters - key/value pairs
         virtual String8         getParameters() const;
 
+        // send command to camera driver
+        virtual status_t        sendCommand(int32_t cmd, int32_t arg1, int32_t arg2);
+
         // our client...
         const sp<ICameraClient>&    getCameraClient() const { return mCameraClient; }
 
@@ -132,22 +137,21 @@
 
                     status_t    checkPid();
 
-        static      void        recordingCallback(nsecs_t timestamp, const sp<IMemory>& mem, void* user);
-        static      void        previewCallback(const sp<IMemory>& mem, void* user);
-        static      void        shutterCallback(void *user);
-        static      void        yuvPictureCallback(const sp<IMemory>& mem, void* user);
-        static      void        jpegPictureCallback(const sp<IMemory>& mem, void* user);
-        static      void        autoFocusCallback(bool focused, void* user);
+        static      void        notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2, void* user);
+        static      void        dataCallback(int32_t msgType, const sp<IMemory>& dataPtr, void* user);
+        static      void        dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType,
+                                                      const sp<IMemory>& dataPtr, void* user);
+
         static      sp<Client>  getClientFromCookie(void* user);
 
-                    void        postShutter();
-                    void        postRaw(const sp<IMemory>& mem);
-                    void        postJpeg(const sp<IMemory>& mem);
-                    void        postPreviewFrame(const sp<IMemory>& mem);
-                    void        postRecordingFrame(nsecs_t timestamp, const sp<IMemory>& frame);
-                    void        copyFrameAndPostCopiedFrame(sp<IMemoryHeap> heap, size_t offset, size_t size);
-                    void        postError(status_t error);
-                    void        postAutoFocus(bool focused);
+                    void        handlePreviewData(const sp<IMemory>&);
+                    void        handleShutter(image_rect_type *image);
+                    void        handlePostview(const sp<IMemory>&);
+                    void        handleRawPicture(const sp<IMemory>&);
+                    void        handleCompressedPicture(const sp<IMemory>&);
+
+                    void        copyFrameAndPostCopiedFrame(const sp<ICameraClient>& client,
+                                    const sp<IMemoryHeap>& heap, size_t offset, size_t size);
 
         // camera operation mode
         enum camera_mode {
@@ -177,7 +181,6 @@
         mutable     Condition                   mReady;
                     sp<CameraService>           mCameraService;
                     sp<ISurface>                mSurface;
-                    sp<MemoryHeapBase>          mPreviewBuffer;
                     int                         mPreviewCallbackFlag;
 
                     sp<MediaPlayer>             mMediaPlayerClick;
@@ -189,6 +192,13 @@
                     sp<CameraHardwareInterface> mHardware;
                     pid_t                       mClientPid;
                     bool                        mUseOverlay;
+
+                    sp<OverlayRef>              mOverlayRef;
+                    int                         mOverlayW;
+                    int                         mOverlayH;
+
+        mutable     Mutex                       mPreviewLock;
+                    sp<MemoryHeapBase>          mPreviewBuffer;
     };
 
 // ----------------------------------------------------------------------------
diff --git a/cmds/keystore/Android.mk b/cmds/keystore/Android.mk
index 3daf44e..15a199f 100644
--- a/cmds/keystore/Android.mk
+++ b/cmds/keystore/Android.mk
@@ -1,22 +1,36 @@
+#
+# Copyright (C) 2009 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.
+#
+
 ifneq ($(TARGET_SIMULATOR),true)
 
 LOCAL_PATH:= $(call my-dir)
+
 include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-    netkeystore.c keymgmt.c
-
-LOCAL_C_INCLUDES := \
-    $(call include-path-for, system-core)/cutils \
-    external/openssl/include
-
-LOCAL_SHARED_LIBRARIES := \
-    libcutils libssl
-
-LOCAL_STATIC_LIBRARIES :=
-
+LOCAL_SRC_FILES := keystore.c
+LOCAL_C_INCLUDES := external/openssl/include
+LOCAL_SHARED_LIBRARIES := libcutils libcrypto
 LOCAL_MODULE:= keystore
-
 include $(BUILD_EXECUTABLE)
 
-endif # !simulator))
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := keystore_cli.c
+LOCAL_C_INCLUDES := external/openssl/include
+LOCAL_SHARED_LIBRARIES := libcutils libcrypto
+LOCAL_MODULE:= keystore_cli
+LOCAL_MODULE_TAGS := debug
+include $(BUILD_EXECUTABLE)
+
+endif
diff --git a/cmds/keystore/certtool.h b/cmds/keystore/certtool.h
deleted file mode 100644
index aefad66..0000000
--- a/cmds/keystore/certtool.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
-**
-** Copyright 2009, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#ifndef __CERTTOOL_H__
-#define __CERTTOOL_H__
-
-#include <stdio.h>
-#include <string.h>
-#include <cutils/sockets.h>
-#include <cutils/log.h>
-
-#include "common.h"
-#include "netkeystore.h"
-
-#define CERT_NAME_LEN (2 * MAX_KEY_NAME_LENGTH + 2)
-
-/*
- * The specific function 'get_cert' is used in daemons to get the key value
- * from keystore. Caller should allocate the buffer and the length of the buffer
- * should be MAX_KEY_VALUE_LENGTH.
- */
-static inline int get_cert(const char *certname, unsigned char *value, int *size)
-{
-    int count, fd, ret = -1;
-    LPC_MARSHAL cmd;
-    char delimiter[] = "_";
-    char *namespace, *keyname;
-    char *context = NULL;
-    char cname[CERT_NAME_LEN];
-
-    if ((certname == NULL) || (value == NULL)) {
-        LOGE("get_cert: certname or value is null\n");
-        return -1;
-    }
-
-    if (strlcpy(cname, certname, CERT_NAME_LEN) >= CERT_NAME_LEN) {
-        LOGE("get_cert: keyname is too long\n");
-        return -1;
-    }
-
-    fd = socket_local_client(SOCKET_PATH,
-                             ANDROID_SOCKET_NAMESPACE_RESERVED,
-                             SOCK_STREAM);
-    if (fd == -1) {
-        LOGE("Keystore service is not up and running.\n");
-        return -1;
-    }
-
-    cmd.opcode = GET;
-    if (((namespace = strtok_r(cname, delimiter, &context)) == NULL) ||
-        ((keyname = strtok_r(NULL, delimiter, &context)) == NULL)) {
-        goto err;
-    }
-    if ((cmd.len = snprintf((char*)cmd.data, BUFFER_MAX, "%s %s", namespace, keyname))
-        > (2 * MAX_KEY_NAME_LENGTH + 1)) goto err;
-
-    if (write_marshal(fd, &cmd)) {
-        LOGE("Incorrect command or command line is too long.\n");
-        goto err;
-    }
-    if (read_marshal(fd, &cmd)) {
-        LOGE("Failed to read the result.\n");
-        goto err;
-    }
-
-    // copy the result if succeeded.
-    if (!cmd.retcode && cmd.len <= BUFFER_MAX) {
-        memcpy(value, cmd.data, cmd.len);
-        ret = 0;
-        *size = cmd.len;
-    }
-err:
-    close(fd);
-    return ret;
-}
-
-#endif
diff --git a/cmds/keystore/common.h b/cmds/keystore/common.h
deleted file mode 100644
index a18114e..0000000
--- a/cmds/keystore/common.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
-**
-** Copyright 2009, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#ifndef __COMMON_H__
-#define __COMMON_H__
-
-#define SOCKET_PATH             "keystore"
-#define KEYSTORE_DIR            "/data/misc/keystore/"
-
-#define READ_TIMEOUT            3
-#define MAX_KEY_NAME_LENGTH     64
-#define MAX_NAMESPACE_LENGTH    MAX_KEY_NAME_LENGTH
-#define MAX_KEY_VALUE_LENGTH    4096
-
-#define BUFFER_MAX              MAX_KEY_VALUE_LENGTH
-
-typedef enum {
-    BOOTUP,
-    UNINITIALIZED,
-    LOCKED,
-    UNLOCKED,
-} KEYSTORE_STATE;
-
-typedef enum {
-    LOCK,
-    UNLOCK,
-    PASSWD,
-    GETSTATE,
-    LISTKEYS,
-    GET,
-    PUT,
-    REMOVE,
-    RESET,
-    MAX_OPCODE
-} KEYSTORE_OPCODE;
-
-typedef struct {
-    uint32_t  len;
-    union {
-        uint32_t  opcode;
-        uint32_t  retcode;
-    };
-    unsigned char data[BUFFER_MAX + 1];
-} LPC_MARSHAL;
-
-#endif
diff --git a/cmds/keystore/keymgmt.c b/cmds/keystore/keymgmt.c
deleted file mode 100644
index 9a1f845..0000000
--- a/cmds/keystore/keymgmt.c
+++ /dev/null
@@ -1,426 +0,0 @@
-/*
-** Copyright 2009, 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 <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <ctype.h>
-#include <fcntl.h>
-#include <dirent.h>
-#include <errno.h>
-#include <openssl/aes.h>
-#include <openssl/evp.h>
-#include <cutils/log.h>
-
-#include "common.h"
-#include "keymgmt.h"
-
-static int  retry_count = 0;
-static unsigned char iv[IV_LEN];
-static KEYSTORE_STATE state = BOOTUP;
-static AES_KEY encryptKey, decryptKey;
-
-inline void unlock_keystore(unsigned char *master_key)
-{
-    AES_set_encrypt_key(master_key, AES_KEY_LEN, &encryptKey);
-    AES_set_decrypt_key(master_key, AES_KEY_LEN, &decryptKey);
-    memset(master_key, 0, sizeof(master_key));
-    state = UNLOCKED;
-}
-
-inline void lock_keystore()
-{
-    memset(&encryptKey, 0 , sizeof(AES_KEY));
-    memset(&decryptKey, 0 , sizeof(AES_KEY));
-    state = LOCKED;
-}
-
-inline void get_encrypt_key(char *passwd, AES_KEY *key)
-{
-    unsigned char user_key[USER_KEY_LEN];
-    gen_key(passwd, user_key, USER_KEY_LEN);
-    AES_set_encrypt_key(user_key, AES_KEY_LEN, key);
-}
-
-inline void get_decrypt_key(char *passwd, AES_KEY *key)
-{
-    unsigned char user_key[USER_KEY_LEN];
-    gen_key(passwd, user_key, USER_KEY_LEN);
-    AES_set_decrypt_key(user_key, AES_KEY_LEN, key);
-}
-
-static int gen_random_blob(unsigned char *key, int size)
-{
-    int ret = 0;
-    int fd = open("/dev/urandom", O_RDONLY);
-    if (fd == -1) return -1;
-    if (read(fd, key, size) != size) ret = -1;
-    close(fd);
-    return ret;
-}
-
-static int encrypt_n_save(AES_KEY *enc_key, DATA_BLOB *blob,
-                          const char *keyfile)
-{
-    int size, fd, ret = -1;
-    unsigned char enc_blob[MAX_BLOB_LEN];
-    char tmpfile[KEYFILE_LEN];
-
-    if ((keyfile == NULL) || (strlen(keyfile) >= (KEYFILE_LEN - 4))) {
-        LOGE("keyfile name is too long or null");
-        return -1;
-    }
-    strcpy(tmpfile, keyfile);
-    strcat(tmpfile, ".tmp");
-
-    // prepare the blob
-    if (IV_LEN > USER_KEY_LEN) {
-        LOGE("iv length is too long.");
-        return -1;
-    }
-    memcpy(blob->iv, iv, IV_LEN);
-    blob->blob_size = get_blob_size(blob);
-    if (blob->blob_size > MAX_BLOB_LEN) {
-        LOGE("blob data size is too large.");
-        return -1;
-    }
-    memcpy(enc_blob, blob->blob, blob->blob_size);
-    AES_cbc_encrypt((unsigned char *)enc_blob, (unsigned char *)blob->blob,
-                    blob->blob_size, enc_key, iv, AES_ENCRYPT);
-    // write to keyfile
-    size = data_blob_size(blob);
-    if ((fd = open(tmpfile, O_CREAT|O_RDWR)) == -1) return -1;
-    if (write(fd, blob, size) == size) ret = 0;
-    close(fd);
-    if (!ret) {
-        unlink(keyfile);
-        rename(tmpfile, keyfile);
-        chmod(keyfile, 0440);
-    }
-    return ret;
-}
-
-static int load_n_decrypt(const char *keyname, const char *keyfile,
-                          AES_KEY *key, DATA_BLOB *blob)
-{
-    int fd, ret = -1;
-    if ((fd = open(keyfile, O_RDONLY)) == -1) return -1;
-    // get the encrypted blob and iv
-    if ((read(fd, blob->iv, sizeof(blob->iv)) != sizeof(blob->iv)) ||
-        (read(fd, &blob->blob_size, sizeof(uint32_t)) != sizeof(uint32_t)) ||
-        (blob->blob_size > MAX_BLOB_LEN)) {
-        goto err;
-    } else {
-        unsigned char enc_blob[MAX_BLOB_LEN];
-        if (read(fd, enc_blob, blob->blob_size) !=
-            (int) blob->blob_size) goto err;
-        // decrypt the blob
-        AES_cbc_encrypt((unsigned char *)enc_blob, (unsigned char*)blob->blob,
-                        blob->blob_size, key, blob->iv, AES_DECRYPT);
-        if (strcmp(keyname, (char*)blob->keyname) == 0) ret = 0;
-    }
-err:
-    close(fd);
-    return ret;
-}
-
-static int store_master_key(char *upasswd, unsigned char *master_key)
-{
-    AES_KEY key;
-    DATA_BLOB blob;
-
-    // prepare the blob
-    if (strlen(MASTER_KEY_TAG) >= USER_KEY_LEN) return -1;
-    strlcpy(blob.keyname, MASTER_KEY_TAG, USER_KEY_LEN);
-    blob.value_size = USER_KEY_LEN;
-    if (USER_KEY_LEN > MAX_KEY_VALUE_LENGTH) {
-        LOGE("master_key length is too long.");
-        return -1;
-    }
-    memcpy((void*)blob.value, (const void*)master_key, USER_KEY_LEN);
-
-    // generate the encryption key
-    get_encrypt_key(upasswd, &key);
-    return encrypt_n_save(&key, &blob, MASTER_KEY);
-}
-
-static int get_master_key(char *upasswd, unsigned char *master_key)
-{
-    AES_KEY key;
-    int size, ret = 0;
-    DATA_BLOB blob;
-
-    get_decrypt_key(upasswd, &key);
-    ret = load_n_decrypt(MASTER_KEY_TAG, MASTER_KEY, &key, &blob);
-    if (blob.value_size > USER_KEY_LEN) {
-        LOGE("the blob's value size is too large");
-        return -1;
-    }
-    if (!ret) memcpy(master_key, blob.value, blob.value_size);
-    return ret;
-}
-
-static int create_master_key(char *upasswd)
-{
-    int ret;
-    unsigned char mpasswd[AES_KEY_LEN];
-    unsigned char master_key[USER_KEY_LEN];
-
-    gen_random_blob(mpasswd, AES_KEY_LEN);
-    gen_key((char*)mpasswd, master_key, USER_KEY_LEN);
-    if ((ret = store_master_key(upasswd, master_key)) == 0) {
-        unlock_keystore(master_key);
-    }
-    memset(master_key, 0, USER_KEY_LEN);
-    memset(mpasswd, 0, AES_KEY_LEN);
-
-    return ret;
-}
-
-static int change_passwd(char *data)
-{
-    unsigned char master_key[USER_KEY_LEN];
-    char *old_pass, *new_pass = NULL, *p, *delimiter=" ";
-    int ret, count = 0;
-    char *context = NULL;
-
-    old_pass = p = strtok_r(data, delimiter, &context);
-    while (p != NULL) {
-        count++;
-        new_pass = p;
-        p = strtok_r(NULL, delimiter, &context);
-    }
-    if (count != 2) return -1;
-    if (strlen(new_pass) < MIN_PASSWD_LENGTH) return -1;
-    if ((ret = get_master_key(old_pass, master_key)) == 0) {
-        ret = store_master_key(new_pass, master_key);
-        retry_count = 0;
-    } else {
-        ret = MAX_RETRY_COUNT - ++retry_count;
-        if (ret == 0) {
-            retry_count = 0;
-            LOGE("passwd:reach max retry count, reset the keystore now.");
-            reset_keystore();
-            return -1;
-        }
-
-    }
-    return ret;
-}
-
-int remove_key(const char *namespace, const char *keyname)
-{
-    char keyfile[KEYFILE_LEN];
-
-    if (state != UNLOCKED) return -state;
-    if ((strlen(namespace) >= MAX_KEY_NAME_LENGTH) ||
-        (strlen(keyname) >= MAX_KEY_NAME_LENGTH)) {
-        LOGE("keyname is too long.");
-        return -1;
-    }
-    sprintf(keyfile, KEYFILE_NAME, namespace, keyname);
-    return unlink(keyfile);
-}
-
-int put_key(const char *namespace, const char *keyname,
-            unsigned char *data, int size)
-{
-    DATA_BLOB blob;
-    uint32_t  real_size;
-    char keyfile[KEYFILE_LEN];
-
-    if (state != UNLOCKED) {
-        LOGE("Can not store key with current state %d\n", state);
-        return -state;
-    }
-    if ((strlen(namespace) >= MAX_KEY_NAME_LENGTH) ||
-        (strlen(keyname) >= MAX_KEY_NAME_LENGTH)) {
-        LOGE("keyname is too long.");
-        return -1;
-    }
-    sprintf(keyfile, KEYFILE_NAME, namespace, keyname);
-    strcpy(blob.keyname, keyname);
-    blob.value_size = size;
-    if (size > MAX_KEY_VALUE_LENGTH) {
-        LOGE("the data size is too large.");
-        return -1;
-    }
-    memcpy(blob.value, data, size);
-    return encrypt_n_save(&encryptKey, &blob, keyfile);
-}
-
-int get_key(const char *namespace, const char *keyname,
-            unsigned char *data, int *size)
-{
-    int ret;
-    DATA_BLOB blob;
-    uint32_t  blob_size;
-    char keyfile[KEYFILE_LEN];
-
-    if (state != UNLOCKED) {
-        LOGE("Can not retrieve key value with current state %d\n", state);
-        return -state;
-    }
-    if ((strlen(namespace) >= MAX_KEY_NAME_LENGTH) ||
-        (strlen(keyname) >= MAX_KEY_NAME_LENGTH)) {
-        LOGE("keyname is too long.");
-        return -1;
-    }
-    sprintf(keyfile, KEYFILE_NAME, namespace, keyname);
-    ret = load_n_decrypt(keyname, keyfile, &decryptKey, &blob);
-    if (!ret) {
-        if ((blob.value_size > MAX_KEY_VALUE_LENGTH)) {
-            LOGE("blob value size is too large.");
-            ret = -1;
-        } else {
-            *size = blob.value_size;
-            memcpy(data, blob.value, *size);
-        }
-    }
-    return ret;
-}
-
-int list_keys(const char *namespace, char reply[BUFFER_MAX])
-{
-    DIR *d;
-    struct dirent *de;
-
-    if (state != UNLOCKED) {
-        LOGE("Can not list key with current state %d\n", state);
-        return -1;
-    }
-
-    if (!namespace || ((d = opendir("."))) == NULL) {
-        LOGE("cannot open keystore dir or namespace is null\n");
-        return -1;
-    }
-
-    if (strlen(namespace) >= MAX_KEY_NAME_LENGTH) {
-        LOGE("namespace is too long.");
-        return -1;
-    }
-
-    reply[0] = 0;
-    while ((de = readdir(d))) {
-        char *prefix, *name, *keyfile = de->d_name;
-        char *context = NULL;
-
-        if (de->d_type != DT_REG) continue;
-        if ((prefix = strtok_r(keyfile, NAME_DELIMITER, &context))
-            == NULL) continue;
-        if (strcmp(prefix, namespace)) continue;
-        if ((name = strtok_r(NULL, NAME_DELIMITER, &context)) == NULL) continue;
-        // append the key name into reply
-        if (reply[0] != 0) strlcat(reply, " ", BUFFER_MAX);
-        if (strlcat(reply, name, BUFFER_MAX) >= BUFFER_MAX) {
-            LOGE("too many files under keystore directory\n");
-            return -1;
-        }
-    }
-    closedir(d);
-    return 0;
-}
-
-int passwd(char *data)
-{
-    if (state == UNINITIALIZED) {
-        if (strchr(data, ' ')) return -1;
-        if (strlen(data) < MIN_PASSWD_LENGTH) return -1;
-        return create_master_key(data);
-    }
-    return change_passwd(data);
-}
-
-int lock()
-{
-    switch(state) {
-        case UNLOCKED:
-            lock_keystore();
-        case LOCKED:
-            return 0;
-        default:
-            return -1;
-    }
-}
-
-int unlock(char *passwd)
-{
-    unsigned char master_key[USER_KEY_LEN];
-    int ret = get_master_key(passwd, master_key);
-    if (!ret) {
-        unlock_keystore(master_key);
-        retry_count = 0;
-    } else {
-        ret = MAX_RETRY_COUNT - ++retry_count;
-        if (ret == 0) {
-            retry_count = 0;
-            LOGE("unlock:reach max retry count, reset the keystore now.");
-            reset_keystore();
-            return -1;
-        }
-    }
-    return ret;
-}
-
-KEYSTORE_STATE get_state()
-{
-    return state;
-}
-
-int reset_keystore()
-{
-    int ret = 0;
-    DIR *d;
-    struct dirent *de;
-
-    if ((d = opendir(".")) == NULL) {
-        LOGE("cannot open keystore dir\n");
-        return -1;
-    }
-    while ((de = readdir(d))) {
-        if (unlink(de->d_name) != 0) ret = -1;
-    }
-    closedir(d);
-    state = UNINITIALIZED;
-    if (ret == 0) {
-        LOGI("keystore is reset.");
-    } else {
-        LOGI("keystore can not be cleaned up entirely.");
-    }
-    return ret;
-}
-
-int init_keystore(const char *dir)
-{
-    int fd;
-
-    if (dir) mkdir(dir, 0770);
-    if (!dir || chdir(dir)) {
-        LOGE("Can not open/create the keystore directory %s\n",
-             dir ? dir : "(null)");
-        return -1;
-    }
-    gen_random_blob(iv, IV_LEN);
-    if ((fd = open(MASTER_KEY, O_RDONLY)) == -1) {
-        state = UNINITIALIZED;
-        return 0;
-    }
-    close(fd);
-    state = LOCKED;
-    return 0;
-}
diff --git a/cmds/keystore/keymgmt.h b/cmds/keystore/keymgmt.h
deleted file mode 100644
index 0e928db..0000000
--- a/cmds/keystore/keymgmt.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
-** Copyright 2009, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#ifndef __KEYMGMT_H__
-#define __KEYMGMT_H__
-
-#define MASTER_KEY_TAG  "master_key"
-#define MASTER_KEY      ".keymaster"
-#define MAX_PATH_LEN    128
-#define SALT            "Android Keystore 0.1"
-#define NAME_DELIMITER  "_"
-#define KEYFILE_NAME    "%s"NAME_DELIMITER"%s"
-#define KEYGEN_ITER     1024
-#define AES_KEY_LEN     128
-#define USER_KEY_LEN    (AES_KEY_LEN/8)
-#define IV_LEN          USER_KEY_LEN
-#define MAX_RETRY_COUNT   6
-#define MIN_PASSWD_LENGTH 8
-
-#define gen_key(passwd, key, len) \
-                PKCS5_PBKDF2_HMAC_SHA1(passwd, strlen(passwd), \
-                                       (unsigned char*)SALT, \
-                                       strlen(SALT), KEYGEN_ITER, \
-                                       len, key)
-
-#define KEYFILE_LEN MAX_NAMESPACE_LENGTH + MAX_KEY_NAME_LENGTH + 6
-
-#define get_blob_size(blob) \
-        (((blob->value_size + sizeof(uint32_t) + MAX_KEY_NAME_LENGTH \
-        + USER_KEY_LEN - 1) / USER_KEY_LEN) * USER_KEY_LEN)
-
-#define MAX_BLOB_LEN    ((MAX_KEY_VALUE_LENGTH + MAX_KEY_NAME_LENGTH + \
-                         sizeof(uint32_t) + USER_KEY_LEN - 1) / USER_KEY_LEN)\
-                         * USER_KEY_LEN
-
-#define data_blob_size(blob) USER_KEY_LEN + sizeof(uint32_t) + blob->blob_size
-
-typedef struct {
-    unsigned char iv[USER_KEY_LEN];
-    uint32_t blob_size;
-    union {
-        unsigned char blob[1];
-        struct {
-            uint32_t value_size;
-            char keyname[MAX_KEY_NAME_LENGTH];
-            unsigned char value[MAX_KEY_VALUE_LENGTH];
-        } __attribute__((packed));
-    };
-} DATA_BLOB;
-
-typedef struct {
-    char tag[USER_KEY_LEN];
-    unsigned char master_key[USER_KEY_LEN];
-} MASTER_BLOB;
-
-int put_key(const char *namespace, const char *keyname,
-            unsigned char *data, int size);
-int get_key(const char *namespace, const char *keyname,
-            unsigned char *data, int *size);
-int remove_key(const char *namespace, const char *keyname);
-int list_keys(const char *namespace, char reply[BUFFER_MAX]);
-int passwd(char *data);
-int lock();
-int unlock(char *passwd);
-KEYSTORE_STATE get_state();
-int reset_keystore();
-int init_keystore(const char *dir);
-
-#endif
diff --git a/cmds/keystore/keystore.c b/cmds/keystore/keystore.c
new file mode 100644
index 0000000..ba74c78
--- /dev/null
+++ b/cmds/keystore/keystore.c
@@ -0,0 +1,542 @@
+/*
+ * Copyright (C) 2009 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 <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <errno.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <arpa/inet.h>
+
+#include <openssl/aes.h>
+#include <openssl/evp.h>
+#include <openssl/md5.h>
+
+#define LOG_TAG "keystore"
+#include <cutils/log.h>
+#include <cutils/sockets.h>
+#include <private/android_filesystem_config.h>
+
+#include "keystore.h"
+
+/* KeyStore is a secured storage for key-value pairs. In this implementation,
+ * each file stores one key-value pair. Keys are encoded in file names, and
+ * values are encrypted with checksums. The encryption key is protected by a
+ * user-defined password. To keep things simple, buffers are always larger than
+ * the maximum space we needed, so boundary checks on buffers are omitted. */
+
+#define KEY_SIZE        120
+#define VALUE_SIZE      32768
+#define PASSWORD_SIZE   VALUE_SIZE
+
+/* Here is the encoding of keys. This is necessary in order to allow arbitrary
+ * characters in keys. Characters in [0-~] are not encoded. Others are encoded
+ * into two bytes. The first byte is one of [+-.] which represents the first
+ * two bits of the character. The second byte encodes the rest of the bits into
+ * [0-o]. Therefore in the worst case the length of a key gets doubled. Note
+ * that Base64 cannot be used here due to the need of prefix match on keys. */
+
+static int encode_key(char *out, uint8_t *in, int length)
+{
+    int i;
+    for (i = length; i > 0; --i, ++in, ++out) {
+        if (*in >= '0' && *in <= '~') {
+            *out = *in;
+        } else {
+            *out = '+' + (*in >> 6);
+            *++out = '0' + (*in & 0x3F);
+            ++length;
+        }
+    }
+    *out = 0;
+    return length;
+}
+
+static int decode_key(uint8_t *out, char *in, int length)
+{
+    int i;
+    for (i = 0; i < length; ++i, ++in, ++out) {
+        if (*in >= '0' && *in <= '~') {
+            *out = *in;
+        } else {
+            *out = (*in - '+') << 6;
+            *out |= (*++in - '0') & 0x3F;
+            --length;
+        }
+    }
+    *out = 0;
+    return length;
+}
+
+/* Here is the protocol used in both requests and responses:
+ *     code [length_1 message_1 ... length_n message_n] end-of-file
+ * where code is one byte long and lengths are unsigned 16-bit integers in
+ * network order. Thus the maximum length of a message is 65535 bytes. */
+
+static int the_socket = -1;
+
+static int recv_code(int8_t *code)
+{
+    return recv(the_socket, code, 1, 0) == 1;
+}
+
+static int recv_message(uint8_t *message, int length)
+{
+    uint8_t bytes[2];
+    if (recv(the_socket, &bytes[0], 1, 0) != 1 ||
+        recv(the_socket, &bytes[1], 1, 0) != 1) {
+        return -1;
+    } else {
+        int offset = bytes[0] << 8 | bytes[1];
+        if (length < offset) {
+            return -1;
+        }
+        length = offset;
+        offset = 0;
+        while (offset < length) {
+            int n = recv(the_socket, &message[offset], length - offset, 0);
+            if (n <= 0) {
+                return -1;
+            }
+            offset += n;
+        }
+    }
+    return length;
+}
+
+static int recv_end_of_file()
+{
+    uint8_t byte;
+    return recv(the_socket, &byte, 1, 0) == 0;
+}
+
+static void send_code(int8_t code)
+{
+    send(the_socket, &code, 1, 0);
+}
+
+static void send_message(uint8_t *message, int length)
+{
+    uint16_t bytes = htons(length);
+    send(the_socket, &bytes, 2, 0);
+    send(the_socket, message, length, 0);
+}
+
+/* Here is the file format. Values are encrypted by AES CBC, and MD5 is used to
+ * compute their checksums. To make the files portable, the length is stored in
+ * network order. Note that the first four bytes are reserved for future use and
+ * are always set to zero in this implementation. */
+
+static int the_entropy = -1;
+
+static struct __attribute__((packed)) {
+    uint32_t reserved;
+    uint8_t vector[AES_BLOCK_SIZE];
+    uint8_t encrypted[0];
+    uint8_t digest[MD5_DIGEST_LENGTH];
+    uint8_t digested[0];
+    int32_t length;
+    uint8_t value[VALUE_SIZE + AES_BLOCK_SIZE];
+} blob;
+
+static int8_t encrypt_blob(char *name, AES_KEY *aes_key)
+{
+    uint8_t vector[AES_BLOCK_SIZE];
+    int length = blob.length;
+    int fd;
+
+    if (read(the_entropy, vector, AES_BLOCK_SIZE) != AES_BLOCK_SIZE) {
+        return SYSTEM_ERROR;
+    }
+
+    length += blob.value - blob.digested;
+    blob.length = htonl(blob.length);
+    MD5(blob.digested, length, blob.digest);
+
+    length += blob.digested - blob.encrypted;
+    length = (length + AES_BLOCK_SIZE - 1) / AES_BLOCK_SIZE * AES_BLOCK_SIZE;
+    memcpy(vector, blob.vector, AES_BLOCK_SIZE);
+    AES_cbc_encrypt(blob.encrypted, blob.encrypted, length, aes_key, vector,
+                    AES_ENCRYPT);
+
+    blob.reserved = 0;
+    length += blob.encrypted - (uint8_t *)&blob;
+
+    fd = open(".tmp", O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR);
+    if (fd == -1 || write(fd, &blob, length) != length) {
+        return SYSTEM_ERROR;
+    }
+    close(fd);
+    return rename(".tmp", name) ? SYSTEM_ERROR : NO_ERROR;
+}
+
+static int8_t decrypt_blob(char *name, AES_KEY *aes_key)
+{
+    int fd = open(name, O_RDONLY);
+    int length;
+
+    if (fd == -1) {
+        return (errno == ENOENT) ? KEY_NOT_FOUND : SYSTEM_ERROR;
+    }
+    length = read(fd, &blob, sizeof(blob));
+    close(fd);
+
+    length -= blob.encrypted - (uint8_t *)&blob;
+    if (length < blob.value - blob.encrypted || length % AES_BLOCK_SIZE != 0) {
+        return VALUE_CORRUPTED;
+    }
+
+    AES_cbc_encrypt(blob.encrypted, blob.encrypted, length, aes_key,
+                    blob.vector, AES_DECRYPT);
+    length -= blob.digested - blob.encrypted;
+    if (!memcmp(blob.digest, MD5(blob.digested, length, NULL),
+                MD5_DIGEST_LENGTH)) {
+        return VALUE_CORRUPTED;
+    }
+
+    length -= blob.value - blob.digested;
+    blob.length = ntohl(blob.length);
+    return (length < blob.length) ? VALUE_CORRUPTED : NO_ERROR;
+}
+
+/* Here are the actions. Each of them is a function without arguments. All
+ * information is defined in global variables, which are set properly before
+ * performing an action. The number of parameters required by each action is
+ * fixed and defined in a table. If the return value of an action is positive,
+ * it will be treated as a response code and transmitted to the client. Note
+ * that the lengths of parameters are checked when they are received, so
+ * boundary checks on parameters are omitted. */
+
+#define MAX_PARAM   2
+#define MAX_RETRY   4
+
+static uid_t uid = -1;
+static int8_t state = UNINITIALIZED;
+static int8_t retry = MAX_RETRY;
+
+static struct {
+    int length;
+    uint8_t value[VALUE_SIZE];
+} params[MAX_PARAM];
+
+static AES_KEY encryption_key;
+static AES_KEY decryption_key;
+
+static int8_t test()
+{
+    return state;
+}
+
+static int8_t get()
+{
+    char name[NAME_MAX];
+    int n = sprintf(name, "%u_", uid);
+    encode_key(&name[n], params[0].value, params[0].length);
+    n = decrypt_blob(name, &decryption_key);
+    if (n != NO_ERROR) {
+        return n;
+    }
+    send_code(NO_ERROR);
+    send_message(blob.value, blob.length);
+    return -NO_ERROR;
+}
+
+static int8_t insert()
+{
+    char name[NAME_MAX];
+    int n = sprintf(name, "%u_", uid);
+    encode_key(&name[n], params[0].value, params[0].length);
+    blob.length = params[1].length;
+    memcpy(blob.value, params[1].value, params[1].length);
+    return encrypt_blob(name, &encryption_key);
+}
+
+static int8_t delete()
+{
+    char name[NAME_MAX];
+    int n = sprintf(name, "%u_", uid);
+    encode_key(&name[n], params[0].value, params[0].length);
+    return (unlink(name) && errno != ENOENT) ? SYSTEM_ERROR : NO_ERROR;
+}
+
+static int8_t exist()
+{
+    char name[NAME_MAX];
+    int n = sprintf(name, "%u_", uid);
+    encode_key(&name[n], params[0].value, params[0].length);
+    if (access(name, R_OK) == -1) {
+        return (errno != ENOENT) ? SYSTEM_ERROR : KEY_NOT_FOUND;
+    }
+    return NO_ERROR;
+}
+
+static int8_t saw()
+{
+    DIR *dir = opendir(".");
+    struct dirent *file;
+    char name[NAME_MAX];
+    int n;
+
+    if (!dir) {
+        return SYSTEM_ERROR;
+    }
+    n = sprintf(name, "%u_", uid);
+    n += encode_key(&name[n], params[0].value, params[0].length);
+    send_code(NO_ERROR);
+    while ((file = readdir(dir)) != NULL) {
+        if (!strncmp(name, file->d_name, n)) {
+            char *p = &file->d_name[n];
+            params[0].length = decode_key(params[0].value, p, strlen(p));
+            send_message(params[0].value, params[0].length);
+        }
+    }
+    closedir(dir);
+    return -NO_ERROR;
+}
+
+static int8_t reset()
+{
+    DIR *dir = opendir(".");
+    struct dirent *file;
+
+    memset(&encryption_key, 0, sizeof(encryption_key));
+    memset(&decryption_key, 0, sizeof(decryption_key));
+    state = UNINITIALIZED;
+    retry = MAX_RETRY;
+
+    if (!dir) {
+        return SYSTEM_ERROR;
+    }
+    while ((file = readdir(dir)) != NULL) {
+        unlink(file->d_name);
+    }
+    closedir(dir);
+    return NO_ERROR;
+}
+
+#define MASTER_KEY_FILE ".masterkey"
+#define MASTER_KEY_SIZE 16
+
+static void generate_key(uint8_t *key, uint8_t *password, int length)
+{
+    PKCS5_PBKDF2_HMAC_SHA1((char *)password, length, (uint8_t *)"keystore",
+                           sizeof("keystore"), 1024, MASTER_KEY_SIZE, key);
+}
+
+static int8_t password()
+{
+    uint8_t key[MASTER_KEY_SIZE];
+    AES_KEY aes_key;
+    int n;
+
+    if (state == UNINITIALIZED) {
+        blob.length = MASTER_KEY_SIZE;
+        if (read(the_entropy, blob.value, MASTER_KEY_SIZE) != MASTER_KEY_SIZE) {
+           return SYSTEM_ERROR;
+        }
+    } else {
+        generate_key(key, params[0].value, params[0].length);
+        AES_set_decrypt_key(key, MASTER_KEY_SIZE * 8, &aes_key);
+        n = decrypt_blob(MASTER_KEY_FILE, &aes_key);
+        if (n == SYSTEM_ERROR) {
+            return SYSTEM_ERROR;
+        }
+        if (n != NO_ERROR || blob.length != MASTER_KEY_SIZE) {
+            if (retry <= 0) {
+                reset();
+                return UNINITIALIZED;
+            }
+            return WRONG_PASSWORD + --retry;
+        }
+    }
+
+    if (params[1].length == -1) {
+        memcpy(key, blob.value, MASTER_KEY_SIZE);
+    } else {
+        generate_key(key, params[1].value, params[1].length);
+        AES_set_encrypt_key(key, MASTER_KEY_SIZE * 8, &aes_key);
+        memcpy(key, blob.value, MASTER_KEY_SIZE);
+        n = encrypt_blob(MASTER_KEY_FILE, &aes_key);
+    }
+
+    if (n == NO_ERROR) {
+        AES_set_encrypt_key(key, MASTER_KEY_SIZE * 8, &encryption_key);
+        AES_set_decrypt_key(key, MASTER_KEY_SIZE * 8, &decryption_key);
+        state = NO_ERROR;
+        retry = MAX_RETRY;
+    }
+    return n;
+}
+
+static int8_t lock()
+{
+    memset(&encryption_key, 0, sizeof(encryption_key));
+    memset(&decryption_key, 0, sizeof(decryption_key));
+    state = LOCKED;
+    return NO_ERROR;
+}
+
+static int8_t unlock()
+{
+    params[1].length = -1;
+    return password();
+}
+
+/* Here are the permissions, actions, users, and the main function. */
+
+enum perm {
+    TEST     =   1,
+    GET      =   2,
+    INSERT   =   4,
+    DELETE   =   8,
+    EXIST    =  16,
+    SAW      =  32,
+    RESET    =  64,
+    PASSWORD = 128,
+    LOCK     = 256,
+    UNLOCK   = 512,
+};
+
+static struct action {
+    int8_t (*run)();
+    int8_t code;
+    int8_t state;
+    uint32_t perm;
+    int lengths[MAX_PARAM];
+} actions[] = {
+    {test,     't', 0,        TEST,     {0}},
+    {get,      'g', NO_ERROR, GET,      {KEY_SIZE}},
+    {insert,   'i', NO_ERROR, INSERT,   {KEY_SIZE, VALUE_SIZE}},
+    {delete,   'd', 0,        DELETE,   {KEY_SIZE}},
+    {exist,    'e', 0,        EXIST,    {KEY_SIZE}},
+    {saw,      's', 0,        SAW,      {KEY_SIZE}},
+    {reset,    'r', 0,        RESET,    {0}},
+    {password, 'p', 0,        PASSWORD, {PASSWORD_SIZE, PASSWORD_SIZE}},
+    {lock,     'l', NO_ERROR, LOCK,     {0}},
+    {unlock,   'u', LOCKED,   UNLOCK,   {PASSWORD_SIZE}},
+    {NULL,      0 , 0,        0,        {0}},
+};
+
+static struct user {
+    uid_t uid;
+    uid_t euid;
+    uint32_t perms;
+} users[] = {
+    {AID_SYSTEM,   0,          ~GET},
+    {AID_VPN,      AID_SYSTEM, GET},
+    {AID_WIFI,     AID_SYSTEM, GET},
+    {0,            0,          TEST | GET | INSERT | DELETE | EXIST | SAW},
+};
+
+static int8_t process(int8_t code) {
+    struct user *user = users;
+    struct action *action = actions;
+    int i;
+
+    while (user->uid && user->uid != uid) {
+        ++user;
+    }
+    while (action->code && action->code != code) {
+        ++action;
+    }
+    if (!action->code) {
+        return UNDEFINED_ACTION;
+    }
+    if (!(action->perm & user->perms)) {
+        return PERMISSION_DENIED;
+    }
+    if (action->state && action->state != state) {
+        return state;
+    }
+    if (user->euid) {
+        uid = user->euid;
+    }
+    for (i = 0; i < MAX_PARAM && action->lengths[i]; ++i) {
+        params[i].length = recv_message(params[i].value, action->lengths[i]);
+        if (params[i].length == -1) {
+            return PROTOCOL_ERROR;
+        }
+    }
+    if (!recv_end_of_file()) {
+        return PROTOCOL_ERROR;
+    }
+    return action->run();
+}
+
+#define RANDOM_DEVICE   "/dev/urandom"
+
+int main(int argc, char **argv)
+{
+    int control_socket = android_get_control_socket("keystore");
+    if (argc < 2) {
+        LOGE("A directory must be specified!");
+        return 1;
+    }
+    if (chdir(argv[1]) == -1) {
+        LOGE("chdir: %s: %s", argv[1], strerror(errno));
+        return 1;
+    }
+    if ((the_entropy = open(RANDOM_DEVICE, O_RDONLY)) == -1) {
+        LOGE("open: %s: %s", RANDOM_DEVICE, strerror(errno));
+        return 1;
+    }
+    if (listen(control_socket, 3) == -1) {
+        LOGE("listen: %s", strerror(errno));
+        return 1;
+    }
+
+    signal(SIGPIPE, SIG_IGN);
+    if (access(MASTER_KEY_FILE, R_OK) == 0) {
+        state = LOCKED;
+    }
+
+    while ((the_socket = accept(control_socket, NULL, 0)) != -1) {
+        struct timeval tv = {.tv_sec = 3};
+        struct ucred cred;
+        socklen_t size = sizeof(cred);
+        int8_t request;
+
+        setsockopt(the_socket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
+        setsockopt(the_socket, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
+
+        if (getsockopt(the_socket, SOL_SOCKET, SO_PEERCRED, &cred, &size)) {
+            LOGW("getsockopt: %s", strerror(errno));
+        } else if (recv_code(&request)) {
+            int8_t old_state = state;
+            int8_t response;
+            uid = cred.uid;
+
+            if ((response = process(request)) > 0) {
+                send_code(response);
+                response = -response;
+            }
+
+            LOGI("uid: %d action: %c -> %d state: %d -> %d retry: %d",
+                 cred.uid, request, -response, old_state, state, retry);
+        }
+        close(the_socket);
+    }
+    LOGE("accept: %s", strerror(errno));
+    return 1;
+}
diff --git a/cmds/keystore/keystore.h b/cmds/keystore/keystore.h
new file mode 100644
index 0000000..5ef51e9
--- /dev/null
+++ b/cmds/keystore/keystore.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __KEYSTORE_H__
+#define __KEYSTORE_H__
+
+enum response_code {
+    NO_ERROR          =  1,
+    LOCKED            =  2,
+    UNINITIALIZED     =  3,
+    SYSTEM_ERROR      =  4,
+    PROTOCOL_ERROR    =  5,
+    PERMISSION_DENIED =  6,
+    KEY_NOT_FOUND     =  7,
+    VALUE_CORRUPTED   =  8,
+    UNDEFINED_ACTION  =  9,
+    WRONG_PASSWORD    = 10,
+};
+
+#endif
diff --git a/cmds/keystore/keystore_cli.c b/cmds/keystore/keystore_cli.c
new file mode 100644
index 0000000..e8afb5a
--- /dev/null
+++ b/cmds/keystore/keystore_cli.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2009 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 <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <cutils/sockets.h>
+
+#include "keystore.h"
+
+char *responses[256] = {
+    [NO_ERROR]           = "No error",
+    [LOCKED]             = "Locked",
+    [UNINITIALIZED]      = "Uninitialized",
+    [SYSTEM_ERROR]       = "System error",
+    [PROTOCOL_ERROR]     = "Protocol error",
+    [PERMISSION_DENIED]  = "Permission denied",
+    [KEY_NOT_FOUND]      = "Key not found",
+    [VALUE_CORRUPTED]    = "Value corrupted",
+    [UNDEFINED_ACTION]   = "Undefined action",
+    [WRONG_PASSWORD]     = "Wrong password (last chance)",
+    [WRONG_PASSWORD + 1] = "Wrong password (2 tries left)",
+    [WRONG_PASSWORD + 2] = "Wrong password (3 tries left)",
+    [WRONG_PASSWORD + 3] = "Wrong password (4 tries left)",
+};
+
+#define MAX_RESPONSE (WRONG_PASSWORD + 3)
+
+int main(int argc, char **argv)
+{
+    uint8_t bytes[65536];
+    uint8_t code;
+    int sock, i;
+
+    if (argc < 2) {
+        printf("Usage: %s action [parameter ...]\n", argv[0]);
+        return 0;
+    }
+
+    sock = socket_local_client("keystore", ANDROID_SOCKET_NAMESPACE_RESERVED,
+                               SOCK_STREAM);
+    if (sock == -1) {
+        puts("Failed to connect");
+        return 1;
+    }
+
+    send(sock, argv[1], 1, 0);
+    for (i = 2; i < argc; ++i) {
+        uint16_t length = strlen(argv[i]);
+        bytes[0] = length >> 8;
+        bytes[1] = length;
+        send(sock, &bytes, 2, 0);
+        send(sock, argv[i], length, 0);
+    }
+    shutdown(sock, SHUT_WR);
+
+    if (recv(sock, &code, 1, 0) != 1) {
+        puts("Failed to receive");
+        return 1;
+    }
+    printf("%d %s\n", code , responses[code] ? responses[code] : "Unknown");
+    while ((i = recv(sock, &bytes[0], 1, 0)) == 1) {
+        int length;
+        int offset;
+        if ((i = recv(sock, &bytes[1], 1, 0)) != 1) {
+            puts("Failed to receive");
+            return 1;
+        }
+        length = bytes[0] << 8 | bytes[1];
+        for (offset = 0; offset < length; offset += i) {
+            i = recv(sock, &bytes[offset], length - offset, 0);
+            if (i <= 0) {
+                puts("Failed to receive");
+                return 1;
+            }
+        }
+        fwrite(bytes, 1, length, stdout);
+        puts("");
+    }
+    return 0;
+}
diff --git a/cmds/keystore/keystore_get.h b/cmds/keystore/keystore_get.h
index 7665e81..0e7e1ae 100644
--- a/cmds/keystore/keystore_get.h
+++ b/cmds/keystore/keystore_get.h
@@ -1,53 +1,69 @@
 /*
-**
-** Copyright 2009, 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.
-*/
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
 #ifndef __KEYSTORE_GET_H__
 #define __KEYSTORE_GET_H__
 
 #include <stdio.h>
-#include <stdlib.h>
+#include <stdint.h>
 #include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
 
-#include "certtool.h"
+#include <cutils/sockets.h>
 
-/* This function is provided to native components to get values from keystore.
- * Users are required to link against libcutils. If something goes wrong, NULL
- * is returned. Otherwise it returns the value in dynamically allocated memory
- * and sets the size if the pointer is not NULL. One can release the memory by
- * calling free(). */
-static char *keystore_get(const char *key, int *size)
+#define KEYSTORE_MESSAGE_SIZE 65535
+
+/* This function is provided for native components to get values from keystore.
+ * Users are required to link against libcutils. The lengths of keys and values
+ * are limited to KEYSTORE_MESSAGE_SIZE. This function returns the length of
+ * the requested value or -1 if something goes wrong. */
+static int keystore_get(const char *key, char *value)
 {
-    char buffer[MAX_KEY_VALUE_LENGTH];
-    char *value;
-    int length;
+    int length = strlen(key);
+    uint8_t bytes[2] = {length >> 8, length};
+    uint8_t code = 'g';
+    int sock;
 
-    if (get_cert(key, (unsigned char *)buffer, &length) != 0) {
-        return NULL;
+    if (length > KEYSTORE_MESSAGE_SIZE) {
+        return -1;
     }
-    value = malloc(length + 1);
-    if (!value) {
-        return NULL;
+    sock = socket_local_client("keystore", ANDROID_SOCKET_NAMESPACE_RESERVED,
+                               SOCK_STREAM);
+    if (sock == -1) {
+        return -1;
     }
-    memcpy(value, buffer, length);
-    value[length] = 0;
-    if (size) {
-        *size = length;
+    if (send(sock, &code, 1, 0) == 1 && send(sock, bytes, 2, 0) == 2 &&
+        send(sock, key, length, 0) == length && shutdown(sock, SHUT_WR) == 0 &&
+        recv(sock, &code, 1, 0) == 1 && code == /* NO_ERROR */ 1 &&
+        recv(sock, &bytes[0], 1, 0) == 1 && recv(sock, &bytes[1], 1, 0) == 1) {
+        int offset = 0;
+        length = bytes[0] << 8 | bytes[1];
+        while (offset < length) {
+            int n = recv(sock, &value[offset], length - offset, 0);
+            if (n <= 0) {
+                length = -1;
+                break;
+            }
+            offset += n;
+        }
     }
-    return value;
+    close(sock);
+    return length;
 }
 
 #endif
diff --git a/cmds/keystore/netkeystore.c b/cmds/keystore/netkeystore.c
deleted file mode 100644
index 637e0d8..0000000
--- a/cmds/keystore/netkeystore.c
+++ /dev/null
@@ -1,411 +0,0 @@
-/*
-** Copyright 2009, 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 "keystore"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <dirent.h>
-#include <unistd.h>
-#include <ctype.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <utime.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <private/android_filesystem_config.h>
-
-#include <cutils/sockets.h>
-#include <cutils/log.h>
-#include <cutils/properties.h>
-
-#include "netkeystore.h"
-#include "keymgmt.h"
-
-#define  DBG  1
-#define  CMD_PUT_WITH_FILE  "putfile"
-
-typedef void CMD_FUNC(LPC_MARSHAL *cmd, LPC_MARSHAL *reply);
-
-struct cmdinfo {
-    const char *name;
-    CMD_FUNC *func;
-};
-
-static CMD_FUNC do_lock;
-static CMD_FUNC do_unlock;
-static CMD_FUNC do_passwd;
-static CMD_FUNC do_get_state;;
-static CMD_FUNC do_listkeys;
-static CMD_FUNC do_get_key;
-static CMD_FUNC do_put_key;
-static CMD_FUNC do_remove_key;
-static CMD_FUNC do_reset_keystore;
-
-#define str(x)      #x
-
-struct cmdinfo cmds[] = {
-    { str(LOCK),           do_lock },
-    { str(UNLOCK),         do_unlock },
-    { str(PASSWD),         do_passwd },
-    { str(GETSTATE),       do_get_state },
-    { str(LISTKEYS),       do_listkeys },
-    { str(GET),            do_get_key },
-    { str(PUT),            do_put_key },
-    { str(REMOVE),         do_remove_key },
-    { str(RESET),          do_reset_keystore },
-};
-
-static  struct ucred cr;
-
-static int check_get_perm(int uid)
-{
-    if (uid == AID_WIFI || uid == AID_VPN) return 0;
-    return -1;
-}
-
-static int check_reset_perm(int uid)
-{
-    if (uid == AID_SYSTEM) return 0;
-    return -1;
-}
-
-static int parse_keyname(char *name, uint32_t len,
-                         char *namespace, char *keyname)
-{
-    int count = 0;
-    char *c = namespace, *p = namespace, *t = name;
-
-    if (!name || !namespace || !keyname) return -1;
-    while (t < name + len && (*t != 0)) {
-        if (*t == ' ') {
-            if (c == keyname) return -1;
-            *p = count = 0;
-            c = p = keyname;
-            t++;
-        } else {
-            if (!isalnum(*t)) return -1;
-            *p++ = *t++;
-            // also check if the keyname/namespace is too long.
-            if (count++ == MAX_KEY_NAME_LENGTH) return -1;
-        }
-    }
-    *p = 0;
-    return 0;
-}
-
-// args of passwd():
-// firstPassword - for the first time
-// oldPassword newPassword - for changing the password
-static void do_passwd(LPC_MARSHAL *cmd, LPC_MARSHAL *reply)
-{
-    reply->retcode = passwd((char*)cmd->data);
-}
-
-// args of lock():
-// no argument
-static void do_lock(LPC_MARSHAL *cmd, LPC_MARSHAL *reply)
-{
-    reply->retcode = lock();
-}
-
-// args of unlock():
-// password
-static void do_unlock(LPC_MARSHAL *cmd, LPC_MARSHAL *reply)
-{
-    reply->retcode = unlock((char*)cmd->data);
-}
-
-// args of get_state():
-// no argument
-static void do_get_state(LPC_MARSHAL *cmd, LPC_MARSHAL *reply)
-{
-    reply->retcode = get_state();
-}
-
-// args of listkeys():
-// namespace
-static void do_listkeys(LPC_MARSHAL *cmd, LPC_MARSHAL *reply)
-{
-    reply->retcode = list_keys((const char*)cmd->data, (char*)reply->data);
-    if (!reply->retcode) reply->len = strlen((char*)reply->data);
-}
-
-// args of get():
-// namespace keyname
-static void do_get_key(LPC_MARSHAL *cmd, LPC_MARSHAL *reply)
-{
-    char namespace[MAX_KEY_NAME_LENGTH];
-    char keyname[MAX_KEY_NAME_LENGTH];
-
-    if (check_get_perm(cr.uid)) {
-        LOGE("uid %d doesn't have the permission to get key value\n", cr.uid);
-        reply->retcode = -1;
-        return;
-    }
-
-    if (parse_keyname((char*)cmd->data, cmd->len, namespace, keyname)) {
-        reply->retcode = -1;
-    } else {
-        reply->retcode = get_key(namespace, keyname, reply->data,
-                                 (int*)&reply->len);
-    }
-}
-
-static int get_value_index(LPC_MARSHAL *cmd)
-{
-    uint32_t count = 0, i;
-    for (i = 0 ; i < cmd->len ; ++i) {
-        if (cmd->data[i] == ' ') {
-            if (++count == 2) return ++i;
-        }
-    }
-    return -1;
-}
-
-// args of put():
-// namespace keyname keyvalue
-static void do_put_key(LPC_MARSHAL *cmd, LPC_MARSHAL *reply)
-{
-    char namespace[MAX_KEY_NAME_LENGTH];
-    char keyname[MAX_KEY_NAME_LENGTH];
-
-    int p = get_value_index(cmd);
-    if (p == -1) {
-        reply->retcode = -1;
-    } else {
-        unsigned char *value;
-        if (parse_keyname((char*)cmd->data, p - 1, namespace, keyname)) {
-            reply->retcode = -1;
-            return;
-        }
-        value = &cmd->data[p];
-        int len = cmd->len - p;
-        reply->retcode = put_key(namespace, keyname, value, len);
-    }
-}
-
-// args of remove_key():
-// namespace keyname
-static void do_remove_key(LPC_MARSHAL *cmd, LPC_MARSHAL *reply)
-{
-    char namespace[MAX_KEY_NAME_LENGTH];
-    char keyname[MAX_KEY_NAME_LENGTH];
-    if (parse_keyname((char*)cmd->data, cmd->len, namespace, keyname)) {
-        reply->retcode = -1;
-        return;
-    }
-    reply->retcode = remove_key(namespace, keyname);
-}
-
-// args of reset_keystore():
-// no argument
-static void do_reset_keystore(LPC_MARSHAL *cmd, LPC_MARSHAL *reply)
-{
-    if (check_reset_perm(cr.uid)) {
-        LOGE("uid %d doesn't have the permission to reset the keystore\n",
-             cr.uid);
-        reply->retcode = -1;
-        return;
-    }
-    reply->retcode = reset_keystore();
-}
-
-static void execute(LPC_MARSHAL *cmd, LPC_MARSHAL *reply)
-{
-    uint32_t cmd_max = sizeof(cmds)/sizeof(struct cmdinfo);
-
-    if (cmd->opcode >= cmd_max) {
-        LOGE("the opcode (%d) is not valid", cmd->opcode);
-        reply->retcode = -1;
-        return;
-    }
-    cmds[cmd->opcode].func(cmd, reply);
-}
-
-static int set_read_timeout(int socket)
-{
-    struct timeval tv;
-    tv.tv_sec = READ_TIMEOUT;
-    if (setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv,  sizeof tv))
-    {
-        LOGE("setsockopt failed");
-        return -1;
-    }
-    return 0;
-}
-
-static int append_input_from_file(const char *filename, LPC_MARSHAL *cmd)
-{
-    int fd, len, ret = 0;
-
-    // get opcode of the function put()
-    if ((fd = open(filename, O_RDONLY)) == -1) {
-        fprintf(stderr, "Can not open file %s\n", filename);
-        return -1;
-    }
-    cmd->data[cmd->len] = ' ';
-    cmd->len++;
-    len = read(fd, cmd->data + cmd->len, BUFFER_MAX - cmd->len);
-    if (len < 0 || (len == (int)(BUFFER_MAX - cmd->len))) {
-        ret = -1;
-    } else {
-        cmd->len += len;
-    }
-    close(fd);
-    return ret;
-}
-
-static int flatten_str_args(int argc, const char **argv, LPC_MARSHAL *cmd)
-{
-    int i, len = 0;
-    char *buf = (char*)cmd->data;
-    buf[0] = 0;
-    for (i = 0 ; i < argc ; ++i) {
-        if (i == 0) {
-            len = strlcpy(buf, argv[i], BUFFER_MAX);
-        } else {
-            len += snprintf(buf + len, BUFFER_MAX - len, " %s", argv[i]);
-        }
-        if (len >= BUFFER_MAX) return -1;
-    }
-    if (len) cmd->len = len;
-    return 0;
-}
-
-static int parse_cmd(int argc, const char **argv, LPC_MARSHAL *cmd)
-{
-    uint32_t i, len = 0;
-    uint32_t cmd_max = sizeof(cmds)/sizeof(cmds[0]);
-
-    for (i = 0 ; i < cmd_max ; ++i) {
-        if (!strcasecmp(argv[0], cmds[i].name)) break;
-    }
-
-    if (i == cmd_max) {
-        // check if this is a command to put the key value with a file.
-        if (strcmp(argv[0], CMD_PUT_WITH_FILE) != 0) return -1;
-        cmd->opcode = PUT;
-        if (argc != 4) {
-            fprintf(stderr, "%s args\n\tnamespace keyname filename\n",
-                    argv[0]);
-            return -1;
-        }
-        if (flatten_str_args(argc - 2, argv + 1, cmd)) return -1;
-        return append_input_from_file(argv[3], cmd);
-    } else {
-        cmd->opcode = i;
-        return flatten_str_args(argc - 1, argv + 1, cmd);
-    }
-}
-
-static int shell_command(const int argc, const char **argv)
-{
-    int fd, i;
-    LPC_MARSHAL  cmd;
-
-    if (parse_cmd(argc, argv , &cmd)) {
-        fprintf(stderr, "Incorrect command or command line is too long.\n");
-        exit(1);
-    }
-    fd = socket_local_client(SOCKET_PATH,
-                             ANDROID_SOCKET_NAMESPACE_RESERVED,
-                             SOCK_STREAM);
-    if (fd == -1) {
-        fprintf(stderr, "Keystore service is not up and running.\n");
-        exit(1);
-    }
-
-    if (write_marshal(fd, &cmd)) {
-        fprintf(stderr, "Incorrect command or command line is too long.\n");
-        exit(1);
-    }
-    if (read_marshal(fd, &cmd)) {
-        fprintf(stderr, "Failed to read the result.\n");
-        exit(1);
-    }
-    cmd.data[cmd.len] = 0;
-    fprintf(stdout, "%s\n", (cmd.retcode == 0) ? "Succeeded!" : "Failed!");
-    if (cmd.len) fprintf(stdout, "\t%s\n", (char*)cmd.data);
-    close(fd);
-    return 0;
-}
-
-int main(const int argc, const char *argv[])
-{
-    struct sockaddr addr;
-    socklen_t alen;
-    int lsocket, s;
-    LPC_MARSHAL  cmd, reply;
-
-    if (argc > 1) {
-        return shell_command(argc - 1, argv + 1);
-    }
-
-    if (init_keystore(KEYSTORE_DIR)) {
-        LOGE("Can not initialize the keystore, the directory exist?\n");
-        exit(1);
-    }
-
-    lsocket = android_get_control_socket(SOCKET_PATH);
-    if (lsocket < 0) {
-        LOGE("Failed to get socket from environment: %s\n", strerror(errno));
-        exit(1);
-    }
-    if (listen(lsocket, 5)) {
-        LOGE("Listen on socket failed: %s\n", strerror(errno));
-        exit(1);
-    }
-    fcntl(lsocket, F_SETFD, FD_CLOEXEC);
-    memset(&reply, 0, sizeof(LPC_MARSHAL));
-
-    for (;;) {
-        socklen_t cr_size = sizeof(cr);
-        alen = sizeof(addr);
-        s = accept(lsocket, &addr, &alen);
-
-        /* retrieve the caller info here */
-        if (getsockopt(s, SOL_SOCKET, SO_PEERCRED, &cr, &cr_size) < 0) {
-            close(s);
-            LOGE("Unable to recieve socket options\n");
-            continue;
-        }
-
-        if (s < 0) {
-            LOGE("Accept failed: %s\n", strerror(errno));
-            continue;
-        }
-        fcntl(s, F_SETFD, FD_CLOEXEC);
-        if (set_read_timeout(s)) {
-            close(s);
-            continue;
-        }
-
-        // read the command, execute and send the result back.
-        if(read_marshal(s, &cmd)) goto err;
-        if (DBG) LOGD("new connection\n");
-        execute(&cmd, &reply);
-        write_marshal(s, &reply);
-err:
-        memset(&reply, 0, sizeof(LPC_MARSHAL));
-        if (DBG) LOGD("closing connection\n");
-        close(s);
-    }
-
-    return 0;
-}
diff --git a/cmds/keystore/netkeystore.h b/cmds/keystore/netkeystore.h
deleted file mode 100644
index a87a667..0000000
--- a/cmds/keystore/netkeystore.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
-**
-** Copyright 2009, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#ifndef __NETKEYSTORE_H__
-#define __NETKEYSTORE_H__
-
-#include <stdio.h>
-#include <cutils/sockets.h>
-#include <cutils/log.h>
-
-#include "common.h"
-
-static inline int readx(int s, void *_buf, int count)
-{
-    char *buf = _buf;
-    int n = 0, r;
-    if (count < 0) return -1;
-    while (n < count) {
-        r = read(s, buf + n, count - n);
-        if (r < 0) {
-            if (errno == EINTR) continue;
-            LOGE("read error: %s\n", strerror(errno));
-            return -1;
-        }
-        if (r == 0) {
-            LOGE("eof\n");
-            return -1; /* EOF */
-        }
-        n += r;
-    }
-    return 0;
-}
-
-static inline int writex(int s, const void *_buf, int count)
-{
-    const char *buf = _buf;
-    int n = 0, r;
-    if (count < 0) return -1;
-    while (n < count) {
-        r = write(s, buf + n, count - n);
-        if (r < 0) {
-            if (errno == EINTR) continue;
-            LOGE("write error: %s\n", strerror(errno));
-            return -1;
-        }
-        n += r;
-    }
-    return 0;
-}
-
-static inline int read_marshal(int s, LPC_MARSHAL *cmd)
-{
-    if (readx(s, cmd, 2 * sizeof(uint32_t))) {
-        LOGE("failed to read header\n");
-        return -1;
-    }
-    if (cmd->len > BUFFER_MAX) {
-        LOGE("invalid size %d\n", cmd->len);
-        return -1;
-    }
-    if (readx(s, cmd->data, cmd->len)) {
-        LOGE("failed to read data\n");
-        return -1;
-    }
-    cmd->data[cmd->len] = 0;
-    return 0;
-}
-
-static inline int write_marshal(int s, LPC_MARSHAL *cmd)
-{
-    if (writex(s, cmd, 2 * sizeof(uint32_t))) {
-        LOGE("failed to write marshal header\n");
-        return -1;
-    }
-    if (writex(s, cmd->data, cmd->len)) {
-        LOGE("failed to write marshal data\n");
-        return -1;
-    }
-    return 0;
-}
-
-#endif
diff --git a/cmds/keystore/tests/Android.mk b/cmds/keystore/tests/Android.mk
deleted file mode 100644
index 33541cc..0000000
--- a/cmds/keystore/tests/Android.mk
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright (C) 2009 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 the KEYSTORE_TESTS environment variable to build the test programs
-ifdef KEYSTORE_TESTS
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES:= netkeystore_test.c ../keymgmt.c
-LOCAL_SHARED_LIBRARIES := libcutils libssl
-LOCAL_MODULE:= netkeystore_test
-LOCAL_MODULE_TAGS := optional
-LOCAL_C_INCLUDES := external/openssl/include \
-								frameworks/base/cmds/keystore
-EXTRA_CFLAGS := -g -O0 -DGTEST_OS_LINUX -DGTEST_HAS_STD_STRING
-include $(BUILD_EXECUTABLE)
-
-endif  #KEYSTORE_TESTS
diff --git a/cmds/keystore/tests/netkeystore_test.c b/cmds/keystore/tests/netkeystore_test.c
deleted file mode 100644
index e7e686b..0000000
--- a/cmds/keystore/tests/netkeystore_test.c
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include "common.h"
-#include "keymgmt.h"
-
-typedef int FUNC_PTR();
-typedef struct {
-    const char *name;
-    FUNC_PTR *func;
-} TESTFUNC;
-
-#define FUNC_NAME(x) { #x, test_##x }
-#define FUNC_BODY(x) int test_##x()
-
-#define TEST_PASSWD        "12345678"
-#define TEST_NPASSWD    "11111111"
-#define TEST_DIR        "/data/local/tmp/keystore"
-#define READONLY_DIR    "/proc/keystore"
-#define TEST_NAMESPACE    "test"
-#define TEST_KEYNAME    "key"
-#define TEST_KEYNAME2    "key2"
-#define TEST_KEYVALUE    "ANDROID"
-
-void setup()
-{
-    if (init_keystore(TEST_DIR) != 0) {
-        fprintf(stderr, "Can not create the test directory %s\n", TEST_DIR);
-        exit(-1);
-    }
-}
-
-void teardown()
-{
-    reset_keystore();
-    rmdir(TEST_DIR);
-}
-
-FUNC_BODY(init_keystore)
-{
-    if (init_keystore(READONLY_DIR) == 0) return -1;
-
-    return EXIT_SUCCESS;
-}
-
-FUNC_BODY(reset_keystore)
-{
-    chdir("/procx");
-    if (reset_keystore() == 0) return -1;
-    chdir(TEST_DIR);
-    return EXIT_SUCCESS;
-}
-
-FUNC_BODY(get_state)
-{
-    if (get_state() != UNINITIALIZED) return -1;
-    passwd(TEST_PASSWD);
-    if (get_state() != UNLOCKED) return -1;
-    lock();
-    if (get_state() != LOCKED) return -1;
-    reset_keystore();
-    if (get_state() != UNINITIALIZED) return -1;
-    return EXIT_SUCCESS;
-}
-
-FUNC_BODY(passwd)
-{
-    char buf[512];
-
-    if (passwd(" 23432dsfsdf") == 0) return -1;
-    if (passwd("dsfsdf") == 0) return -1;
-    passwd(TEST_PASSWD);
-    lock();
-    if (unlock("55555555") == 0) return -1;
-    if (unlock(TEST_PASSWD) != 0) return -1;
-
-    // change the password
-    sprintf(buf, "%s %s", "klfdjdsklfjg", "abcdefghi");
-    if (passwd(buf) == 0) return -1;
-
-    sprintf(buf, "%s %s", TEST_PASSWD, TEST_NPASSWD);
-    if (passwd(buf) != 0) return -1;
-    lock();
-
-    if (unlock(TEST_PASSWD) == 0) return -1;
-    if (unlock(TEST_NPASSWD) != 0) return -1;
-
-    return EXIT_SUCCESS;
-}
-
-FUNC_BODY(lock)
-{
-    if (lock() == 0) return -1;
-    passwd(TEST_PASSWD);
-    if (lock() != 0) return -1;
-    if (lock() != 0) return -1;
-    return EXIT_SUCCESS;
-}
-
-FUNC_BODY(unlock)
-{
-    int i = MAX_RETRY_COUNT;
-    passwd(TEST_PASSWD);
-    lock();
-    while (i > 1) {
-        if (unlock(TEST_NPASSWD) != --i) return -1;
-    }
-    if (unlock(TEST_NPASSWD) != -1) return -1;
-    return EXIT_SUCCESS;
-}
-
-FUNC_BODY(put_key)
-{
-    int i = 0;
-    char keyname[512];
-
-    if (put_key(TEST_NAMESPACE, TEST_KEYNAME, (unsigned char *)TEST_KEYVALUE,
-                strlen(TEST_KEYVALUE)) == 0) return -1;
-    passwd(TEST_PASSWD);
-    if (put_key(TEST_NAMESPACE, TEST_KEYNAME, (unsigned char *)TEST_KEYVALUE,
-                strlen(TEST_KEYVALUE)) != 0) return -1;
-
-    for(i = 0; i < 500; i++) keyname[i] = 'K';
-    keyname[i] = 0;
-    if (put_key(TEST_NAMESPACE, keyname, (unsigned char *)TEST_KEYVALUE,
-                strlen(TEST_KEYVALUE)) == 0) return -1;
-    if (put_key(TEST_NAMESPACE, TEST_KEYNAME, (unsigned char *)TEST_KEYVALUE,
-                MAX_KEY_VALUE_LENGTH + 1) == 0) return -1;
-    return EXIT_SUCCESS;
-}
-
-FUNC_BODY(get_key)
-{
-    int size;
-    unsigned char data[MAX_KEY_VALUE_LENGTH];
-
-    if (get_key(TEST_NAMESPACE, TEST_KEYNAME, data, &size) == 0) return -1;
-
-    passwd(TEST_PASSWD);
-    put_key(TEST_NAMESPACE, TEST_KEYNAME, (unsigned char *)TEST_KEYVALUE,
-            strlen(TEST_KEYVALUE));
-    if (get_key(TEST_NAMESPACE, TEST_KEYNAME, data, &size) != 0) return -1;
-    if (memcmp(data, TEST_KEYVALUE, size) != 0) return -1;
-
-    return EXIT_SUCCESS;
-}
-
-FUNC_BODY(remove_key)
-{
-    if (remove_key(TEST_NAMESPACE, TEST_KEYNAME) == 0) return -1;
-
-    passwd(TEST_PASSWD);
-    if (remove_key(TEST_NAMESPACE, TEST_KEYNAME) == 0) return -1;
-
-    put_key(TEST_NAMESPACE, TEST_KEYNAME, (unsigned char *)TEST_KEYVALUE,
-            strlen(TEST_KEYVALUE));
-    if (remove_key(TEST_NAMESPACE, TEST_KEYNAME) != 0) return -1;
-
-    return EXIT_SUCCESS;
-}
-
-FUNC_BODY(list_keys)
-{
-    int i;
-    char buf[128];
-    char reply[BUFFER_MAX];
-
-    for(i = 0; i < 100; i++) buf[i] = 'K';
-    buf[i] = 0;
-
-    if (list_keys(TEST_NAMESPACE, reply) == 0) return -1;
-
-    passwd(TEST_PASSWD);
-    if (list_keys(buf, reply) == 0) return -1;
-
-    if (list_keys(TEST_NAMESPACE, reply) != 0) return -1;
-    if (strcmp(reply, "") != 0) return -1;
-
-    put_key(TEST_NAMESPACE, TEST_KEYNAME, (unsigned char *)TEST_KEYVALUE,
-            strlen(TEST_KEYVALUE));
-    if (list_keys(TEST_NAMESPACE, reply) != 0) return -1;
-    if (strcmp(reply, TEST_KEYNAME) != 0) return -1;
-
-    put_key(TEST_NAMESPACE, TEST_KEYNAME2, (unsigned char *)TEST_KEYVALUE,
-            strlen(TEST_KEYVALUE));
-
-    if (list_keys(TEST_NAMESPACE, reply) != 0) return -1;
-    sprintf(buf, "%s %s", TEST_KEYNAME2, TEST_KEYNAME);
-    if (strcmp(reply, buf) != 0) return -1;
-
-    return EXIT_SUCCESS;
-}
-
-TESTFUNC all_tests[] = {
-    FUNC_NAME(init_keystore),
-    FUNC_NAME(reset_keystore),
-    FUNC_NAME(get_state),
-    FUNC_NAME(passwd),
-    FUNC_NAME(lock),
-    FUNC_NAME(unlock),
-    FUNC_NAME(put_key),
-    FUNC_NAME(get_key),
-    FUNC_NAME(remove_key),
-    FUNC_NAME(list_keys),
-};
-
-int main(int argc, char **argv) {
-    int i, ret;
-    for (i = 0 ; i < (int)(sizeof(all_tests)/sizeof(TESTFUNC)) ; ++i) {
-        setup();
-        if ((ret = all_tests[i].func()) != EXIT_SUCCESS) {
-            fprintf(stderr, "ERROR in function %s\n", all_tests[i].name);
-            return ret;
-        } else {
-            fprintf(stderr, "function %s PASSED!\n", all_tests[i].name);
-        }
-        teardown();
-    }
-    return EXIT_SUCCESS;
-}
diff --git a/cmds/runtime/Android.mk b/cmds/runtime/Android.mk
index 521eb2b..6a72d10 100644
--- a/cmds/runtime/Android.mk
+++ b/cmds/runtime/Android.mk
@@ -10,6 +10,7 @@
 
 LOCAL_SHARED_LIBRARIES := \
 	libutils \
+	libbinder \
 	libandroid_runtime \
 	libcutils \
 	libui \
diff --git a/cmds/runtime/ServiceManager.cpp b/cmds/runtime/ServiceManager.cpp
index 758a95c..b2bef07 100644
--- a/cmds/runtime/ServiceManager.cpp
+++ b/cmds/runtime/ServiceManager.cpp
@@ -9,9 +9,9 @@
 
 #include <utils/Debug.h>
 #include <utils/Log.h>
-#include <utils/Parcel.h>
+#include <binder/Parcel.h>
 #include <utils/String8.h>
-#include <utils/ProcessState.h>
+#include <binder/ProcessState.h>
 
 #include <private/utils/Static.h>
 
diff --git a/cmds/runtime/ServiceManager.h b/cmds/runtime/ServiceManager.h
index d09cec8..090ca6d 100644
--- a/cmds/runtime/ServiceManager.h
+++ b/cmds/runtime/ServiceManager.h
@@ -4,7 +4,7 @@
 #ifndef ANDROID_SERVICE_MANAGER_H
 #define ANDROID_SERVICE_MANAGER_H
 
-#include <utils/IServiceManager.h>
+#include <binder/IServiceManager.h>
 #include <utils/KeyedVector.h>
 #include <utils/threads.h>
 
diff --git a/cmds/runtime/main_runtime.cpp b/cmds/runtime/main_runtime.cpp
index 476f38a..21e0e4d 100644
--- a/cmds/runtime/main_runtime.cpp
+++ b/cmds/runtime/main_runtime.cpp
@@ -7,9 +7,11 @@
 #include "ServiceManager.h"
 #include "SignalHandler.h"
 
-#include <utils.h>
-#include <utils/IPCThreadState.h>
-#include <utils/ProcessState.h>
+#include <utils/threads.h>
+#include <utils/Errors.h>
+
+#include <binder/IPCThreadState.h>
+#include <binder/ProcessState.h>
 #include <utils/Log.h>  
 #include <cutils/zygote.h>
 
diff --git a/cmds/surfaceflinger/Android.mk b/cmds/surfaceflinger/Android.mk
index 37c3d94..bfa58a1 100644
--- a/cmds/surfaceflinger/Android.mk
+++ b/cmds/surfaceflinger/Android.mk
@@ -6,6 +6,7 @@
 
 LOCAL_SHARED_LIBRARIES := \
 	libsurfaceflinger \
+	libbinder \
 	libutils
 
 LOCAL_C_INCLUDES := \
diff --git a/cmds/surfaceflinger/main_surfaceflinger.cpp b/cmds/surfaceflinger/main_surfaceflinger.cpp
index 7c89578..d650721 100644
--- a/cmds/surfaceflinger/main_surfaceflinger.cpp
+++ b/cmds/surfaceflinger/main_surfaceflinger.cpp
@@ -1,6 +1,6 @@
-#include <utils/IPCThreadState.h>
-#include <utils/ProcessState.h>
-#include <utils/IServiceManager.h>
+#include <binder/IPCThreadState.h>
+#include <binder/ProcessState.h>
+#include <binder/IServiceManager.h>
 #include <utils/Log.h>
 
 #include <SurfaceFlinger.h>
diff --git a/im/java/android/im/BrandingResourceIDs.java b/im/java/android/im/BrandingResourceIDs.java
deleted file mode 100644
index 9960722..0000000
--- a/im/java/android/im/BrandingResourceIDs.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * 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.
- */
-package android.im;
-
-/**
- * @hide
- * Defines the IDs of branding resources.
- */
-public interface BrandingResourceIDs {
-    /**
-     * The logo icon of the provider which is displayed in the landing page.
-     */
-    public static final int DRAWABLE_LOGO                = 100;
-    /**
-     * The icon of online presence status.
-     */
-    public static final int DRAWABLE_PRESENCE_ONLINE     = 102;
-    /**
-     * The icon of busy presence status.
-     */
-    public static final int DRAWABLE_PRESENCE_BUSY       = 103;
-    /**
-     * The icon of away presence status.
-     */
-    public static final int DRAWABLE_PRESENCE_AWAY       = 104;
-    /**
-     * The icon of invisible presence status.
-     */
-    public static final int DRAWABLE_PRESENCE_INVISIBLE  = 105;
-    /**
-     * The icon of offline presence status.
-     */
-    public static final int DRAWABLE_PRESENCE_OFFLINE    = 106;
-    /**
-     * The label of the menu to go to the contact list screen.
-     */
-    public static final int STRING_MENU_CONTACT_LIST     = 107;
-
-}
diff --git a/im/java/android/im/IImPlugin.aidl b/im/java/android/im/IImPlugin.aidl
deleted file mode 100644
index 229cd0e..0000000
--- a/im/java/android/im/IImPlugin.aidl
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * 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.
- */
-package android.im;
-
-/**
- * @hide
- */
-interface IImPlugin {
-    /**
-     * Notify the plugin the front door activity is created. This gives the plugin a chance to
-     * start its own servics, etc.
-     */
-    void onStart();
-    
-    /**
-     * Notify the plugin the front door activity is stopping.
-     */
-    void onStop();
-
-    /**
-     * Sign in to the service for the account passed in.
-     *
-     * @param account the account id for the accont to be signed into.
-     */
-    void signIn(long account);
-
-    /**
-     * Sign out of the service for the account passed in.
-     *
-     * @param account the account id for the accont to be signed out of.
-     */
-    void signOut(long account);
-
-    /**
-     * Returns the package name used to load the resources for the given provider name.
-     *
-     * @return The package name to load the resourcs for the given provider.
-     */
-    String getResourcePackageNameForProvider(String providerName);
-
-    /**
-     * Returns a map of branding resources for the given provider. The keys are defined
-     * in {@link android.im.BrandingResourceIDs}. The values are the resource identifiers generated
-     * by the aapt tool.
-     *
-     * @return The map of branding resources for the given provider.
-     */
-    Map getResourceMapForProvider(String providerName);
-
-    /*
-     * Returns a list of supported IM providers.
-     *
-     * @return a List of supported providers.
-     */
-    List getSupportedProviders();
-}
diff --git a/include/utils/Binder.h b/include/binder/Binder.h
similarity index 96%
rename from include/utils/Binder.h
rename to include/binder/Binder.h
index b5b8d98..47b2bb9 100644
--- a/include/utils/Binder.h
+++ b/include/binder/Binder.h
@@ -17,7 +17,7 @@
 #ifndef ANDROID_BINDER_H
 #define ANDROID_BINDER_H
 
-#include <utils/IBinder.h>
+#include <binder/IBinder.h>
 
 // ---------------------------------------------------------------------------
 namespace android {
@@ -27,7 +27,7 @@
 public:
                         BBinder();
 
-    virtual String16    getInterfaceDescriptor() const;
+    virtual const String16& getInterfaceDescriptor() const;
     virtual bool        isBinderAlive() const;
     virtual status_t    pingBinder();
     virtual status_t    dump(int fd, const Vector<String16>& args);
@@ -71,6 +71,7 @@
 
             Extras*     mExtras;
             void*       mReserved0;
+    static  String16    sEmptyDescriptor;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/include/utils/BpBinder.h b/include/binder/BpBinder.h
similarity index 94%
rename from include/utils/BpBinder.h
rename to include/binder/BpBinder.h
index 7b96e29..7ef93aa 100644
--- a/include/utils/BpBinder.h
+++ b/include/binder/BpBinder.h
@@ -17,7 +17,7 @@
 #ifndef ANDROID_BPBINDER_H
 #define ANDROID_BPBINDER_H
 
-#include <utils/IBinder.h>
+#include <binder/IBinder.h>
 #include <utils/KeyedVector.h>
 #include <utils/threads.h>
 
@@ -31,7 +31,7 @@
 
     inline  int32_t     handle() const { return mHandle; }
 
-    virtual String16    getInterfaceDescriptor() const;
+    virtual const String16&    getInterfaceDescriptor() const;
     virtual bool        isBinderAlive() const;
     virtual status_t    pingBinder();
     virtual status_t    dump(int fd, const Vector<String16>& args);
@@ -106,6 +106,7 @@
     };
 
             void                reportOneDeath(const Obituary& obit);
+            bool                isDescriptorCached() const;
 
     mutable Mutex               mLock;
             volatile int32_t    mAlive;
@@ -113,6 +114,7 @@
             Vector<Obituary>*   mObituaries;
             ObjectManager       mObjects;
             Parcel*             mConstantData;
+    mutable String16            mDescriptorCache;
 };
 
 }; // namespace android
diff --git a/include/utils/IBinder.h b/include/binder/IBinder.h
similarity index 97%
rename from include/utils/IBinder.h
rename to include/binder/IBinder.h
index 7370330..884b5c1 100644
--- a/include/utils/IBinder.h
+++ b/include/binder/IBinder.h
@@ -56,7 +56,7 @@
         FLAG_ONEWAY             = 0x00000001
     };
 
-    inline                  IBinder() { }
+                          IBinder();
 
     /**
      * Check if this IBinder implements the interface named by
@@ -69,7 +69,7 @@
      * Return the canonical name of the interface provided by this IBinder
      * object.
      */
-    virtual String16        getInterfaceDescriptor() const = 0;
+    virtual const String16& getInterfaceDescriptor() const = 0;
 
     virtual bool            isBinderAlive() const = 0;
     virtual status_t        pingBinder() = 0;
@@ -147,7 +147,7 @@
     virtual BpBinder*       remoteBinder();
 
 protected:
-    inline virtual          ~IBinder() { }
+    virtual          ~IBinder();
 
 private:
 };
diff --git a/include/utils/IInterface.h b/include/binder/IInterface.h
similarity index 82%
rename from include/utils/IInterface.h
rename to include/binder/IInterface.h
index 959722a..273d922 100644
--- a/include/utils/IInterface.h
+++ b/include/binder/IInterface.h
@@ -18,7 +18,7 @@
 #ifndef ANDROID_IINTERFACE_H
 #define ANDROID_IINTERFACE_H
 
-#include <utils/Binder.h>
+#include <binder/Binder.h>
 
 namespace android {
 
@@ -27,10 +27,12 @@
 class IInterface : public virtual RefBase
 {
 public:
+            IInterface();
             sp<IBinder>         asBinder();
             sp<const IBinder>   asBinder() const;
-
+            
 protected:
+    virtual                     ~IInterface();
     virtual IBinder*            onAsBinder() = 0;
 };
 
@@ -49,7 +51,7 @@
 {
 public:
     virtual sp<IInterface>      queryLocalInterface(const String16& _descriptor);
-    virtual String16            getInterfaceDescriptor() const;
+    virtual const String16&     getInterfaceDescriptor() const;
 
 protected:
     virtual IBinder*            onAsBinder();
@@ -72,11 +74,14 @@
 #define DECLARE_META_INTERFACE(INTERFACE)                               \
     static const String16 descriptor;                                   \
     static sp<I##INTERFACE> asInterface(const sp<IBinder>& obj);        \
-    virtual String16 getInterfaceDescriptor() const;                    \
+    virtual const String16& getInterfaceDescriptor() const;             \
+    I##INTERFACE();                                                     \
+    virtual ~I##INTERFACE();                                            \
+
 
 #define IMPLEMENT_META_INTERFACE(INTERFACE, NAME)                       \
     const String16 I##INTERFACE::descriptor(NAME);                      \
-    String16 I##INTERFACE::getInterfaceDescriptor() const {             \
+    const String16& I##INTERFACE::getInterfaceDescriptor() const {      \
         return I##INTERFACE::descriptor;                                \
     }                                                                   \
     sp<I##INTERFACE> I##INTERFACE::asInterface(const sp<IBinder>& obj)  \
@@ -92,9 +97,16 @@
         }                                                               \
         return intr;                                                    \
     }                                                                   \
+    I##INTERFACE::I##INTERFACE() { }                                    \
+    I##INTERFACE::~I##INTERFACE() { }                                   \
+
+
+#define CHECK_INTERFACE(interface, data, reply)                         \
+    if (!data.checkInterface(this)) { return PERMISSION_DENIED; }       \
+
 
 // ----------------------------------------------------------------------
-// No user-servicable parts after this...
+// No user-serviceable parts after this...
 
 template<typename INTERFACE>
 inline sp<IInterface> BnInterface<INTERFACE>::queryLocalInterface(
@@ -105,7 +117,7 @@
 }
 
 template<typename INTERFACE>
-inline String16 BnInterface<INTERFACE>::getInterfaceDescriptor() const
+inline const String16& BnInterface<INTERFACE>::getInterfaceDescriptor() const
 {
     return INTERFACE::getInterfaceDescriptor();
 }
diff --git a/include/utils/IMemory.h b/include/binder/IMemory.h
similarity index 94%
rename from include/utils/IMemory.h
rename to include/binder/IMemory.h
index 35a3fd7..ae042cb 100644
--- a/include/utils/IMemory.h
+++ b/include/binder/IMemory.h
@@ -23,7 +23,7 @@
 
 #include <utils/RefBase.h>
 #include <utils/Errors.h>
-#include <utils/IInterface.h>
+#include <binder/IInterface.h>
 
 namespace android {
 
@@ -59,6 +59,10 @@
             const Parcel& data,
             Parcel* reply,
             uint32_t flags = 0);
+    
+    BnMemoryHeap();
+protected:
+    virtual ~BnMemoryHeap();
 };
 
 // ----------------------------------------------------------------------------
@@ -85,6 +89,10 @@
             const Parcel& data,
             Parcel* reply,
             uint32_t flags = 0);
+
+    BnMemory();
+protected:
+    virtual ~BnMemory();
 };
 
 // ----------------------------------------------------------------------------
diff --git a/include/utils/IPCThreadState.h b/include/binder/IPCThreadState.h
similarity index 98%
rename from include/utils/IPCThreadState.h
rename to include/binder/IPCThreadState.h
index 0490fd3..78306b2 100644
--- a/include/utils/IPCThreadState.h
+++ b/include/binder/IPCThreadState.h
@@ -18,8 +18,8 @@
 #define ANDROID_IPC_THREAD_STATE_H
 
 #include <utils/Errors.h>
-#include <utils/Parcel.h>
-#include <utils/ProcessState.h>
+#include <binder/Parcel.h>
+#include <binder/ProcessState.h>
 #include <utils/Vector.h>
 
 #ifdef HAVE_WIN32_PROC
diff --git a/include/utils/IPermissionController.h b/include/binder/IPermissionController.h
similarity index 97%
rename from include/utils/IPermissionController.h
rename to include/binder/IPermissionController.h
index cb1dd34..f9d371b 100644
--- a/include/utils/IPermissionController.h
+++ b/include/binder/IPermissionController.h
@@ -18,7 +18,7 @@
 #ifndef ANDROID_IPERMISSION_CONTROLLER_H
 #define ANDROID_IPERMISSION_CONTROLLER_H
 
-#include <utils/IInterface.h>
+#include <binder/IInterface.h>
 
 namespace android {
 
diff --git a/include/utils/IServiceManager.h b/include/binder/IServiceManager.h
similarity index 94%
rename from include/utils/IServiceManager.h
rename to include/binder/IServiceManager.h
index e3d99fe..24e9e99 100644
--- a/include/utils/IServiceManager.h
+++ b/include/binder/IServiceManager.h
@@ -18,8 +18,8 @@
 #ifndef ANDROID_ISERVICE_MANAGER_H
 #define ANDROID_ISERVICE_MANAGER_H
 
-#include <utils/IInterface.h>
-#include <utils/IPermissionController.h>
+#include <binder/IInterface.h>
+#include <binder/IPermissionController.h>
 #include <utils/Vector.h>
 #include <utils/String16.h>
 
@@ -78,6 +78,8 @@
 bool checkCallingPermission(const String16& permission);
 bool checkCallingPermission(const String16& permission,
                             int32_t* outPid, int32_t* outUid);
+bool checkPermission(const String16& permission, pid_t pid, uid_t uid);
+
 
 // ----------------------------------------------------------------------
 
diff --git a/include/utils/MemoryBase.h b/include/binder/MemoryBase.h
similarity index 97%
rename from include/utils/MemoryBase.h
rename to include/binder/MemoryBase.h
index eb5a9d2..463e26d 100644
--- a/include/utils/MemoryBase.h
+++ b/include/binder/MemoryBase.h
@@ -20,7 +20,7 @@
 #include <stdlib.h>
 #include <stdint.h>
 
-#include <utils/IMemory.h>
+#include <binder/IMemory.h>
 
 
 namespace android {
diff --git a/include/utils/MemoryDealer.h b/include/binder/MemoryDealer.h
similarity index 91%
rename from include/utils/MemoryDealer.h
rename to include/binder/MemoryDealer.h
index 454b627..03ac70a 100644
--- a/include/utils/MemoryDealer.h
+++ b/include/binder/MemoryDealer.h
@@ -21,9 +21,9 @@
 #include <stdint.h>
 #include <sys/types.h>
 
-#include <utils/IMemory.h>
+#include <binder/IMemory.h>
 #include <utils/threads.h>
-#include <utils/MemoryHeapBase.h>
+#include <binder/MemoryHeapBase.h>
 
 namespace android {
 // ----------------------------------------------------------------------------
@@ -39,6 +39,10 @@
 public:
     // all values must be page-aligned
     virtual sp<IMemory> mapMemory(size_t offset, size_t size) = 0;
+
+    HeapInterface();
+protected:
+    virtual ~HeapInterface();
 };
 
 // ----------------------------------------------------------------------------
@@ -61,6 +65,10 @@
     virtual void        dump(const char* what, uint32_t flags = 0) const = 0;
     virtual void        dump(String8& res,
             const char* what, uint32_t flags = 0) const = 0;
+
+    AllocatorInterface();
+protected:
+    virtual ~AllocatorInterface();
 };
 
 // ----------------------------------------------------------------------------
@@ -71,6 +79,7 @@
 class SharedHeap : public HeapInterface, public MemoryHeapBase
 {
 public:
+                        SharedHeap();
                         SharedHeap(size_t size, uint32_t flags = 0, char const * name = NULL);
     virtual             ~SharedHeap();
     virtual sp<IMemory> mapMemory(size_t offset, size_t size);
@@ -117,13 +126,22 @@
             mFirst = mLast = newNode;
             newNode->prev = newNode->next = 0;
         } else {
-            insertBefore(mFirst, newNode);
+            newNode->prev = 0;
+            newNode->next = mFirst;
+            mFirst->prev = newNode;
+            mFirst = newNode;
         }
     }
     
     void insertTail(NODE* newNode) {
-        if (mLast == 0) insertBeginning(newNode);
-        else            insertAfter(mLast, newNode);
+        if (mLast == 0) {
+            insertHead(newNode);
+        } else {
+            newNode->prev = mLast;
+            newNode->next = 0;
+            mLast->next = newNode;
+            mLast = newNode;
+        }
     }
 
     NODE* remove(NODE* node) {
@@ -200,8 +218,6 @@
             const sp<HeapInterface>& heap,
             const sp<AllocatorInterface>& allocator);
 
-    virtual ~MemoryDealer();
-
     virtual sp<IMemory> allocate(size_t size, uint32_t flags = 0);
     virtual void        deallocate(size_t offset);
     virtual void        dump(const char* what, uint32_t flags = 0) const;
@@ -210,6 +226,9 @@
     sp<IMemoryHeap> getMemoryHeap() const { return heap(); }
     sp<AllocatorInterface> getAllocator() const { return allocator(); }
 
+protected:
+    virtual ~MemoryDealer();
+
 private:    
     const sp<HeapInterface>&        heap() const;
     const sp<AllocatorInterface>&   allocator() const;
diff --git a/include/utils/MemoryHeapBase.h b/include/binder/MemoryHeapBase.h
similarity index 91%
rename from include/utils/MemoryHeapBase.h
rename to include/binder/MemoryHeapBase.h
index 574acf4..d793c24 100644
--- a/include/utils/MemoryHeapBase.h
+++ b/include/binder/MemoryHeapBase.h
@@ -20,7 +20,7 @@
 #include <stdlib.h>
 #include <stdint.h>
 
-#include <utils/IMemory.h>
+#include <binder/IMemory.h>
 
 
 namespace android {
@@ -35,14 +35,15 @@
         MAP_ONCE = IMemoryHeap::MAP_ONCE,
         // memory won't be mapped locally, but will be mapped in the remote
         // process.
-        DONT_MAP_LOCALLY = 0x00000100
+        DONT_MAP_LOCALLY = 0x00000100,
+        NO_CACHING = 0x00000200
     };
 
     /* 
      * maps the memory referenced by fd. but DOESN'T take ownership
      * of the filedescriptor (it makes a copy with dup()
      */
-    MemoryHeapBase(int fd, size_t size, uint32_t flags = 0);
+    MemoryHeapBase(int fd, size_t size, uint32_t flags = 0, uint32_t offset = 0);
     
     /*
      * maps memory from the given device
@@ -82,7 +83,7 @@
             int flags = 0, const char* device = NULL);    
 
 private:
-    status_t mapfd(int fd, size_t size);
+    status_t mapfd(int fd, size_t size, uint32_t offset = 0);
 
     int         mFD;
     size_t      mSize;
diff --git a/include/utils/MemoryHeapPmem.h b/include/binder/MemoryHeapPmem.h
similarity index 95%
rename from include/utils/MemoryHeapPmem.h
rename to include/binder/MemoryHeapPmem.h
index 60335ad..dbf26ff 100644
--- a/include/utils/MemoryHeapPmem.h
+++ b/include/binder/MemoryHeapPmem.h
@@ -20,9 +20,9 @@
 #include <stdlib.h>
 #include <stdint.h>
 
-#include <utils/MemoryDealer.h>
-#include <utils/MemoryHeapBase.h>
-#include <utils/IMemory.h>
+#include <binder/MemoryDealer.h>
+#include <binder/MemoryHeapBase.h>
+#include <binder/IMemory.h>
 #include <utils/SortedVector.h>
 
 namespace android {
diff --git a/include/utils/Parcel.h b/include/binder/Parcel.h
similarity index 94%
rename from include/utils/Parcel.h
rename to include/binder/Parcel.h
index af1490a..ba6c711 100644
--- a/include/utils/Parcel.h
+++ b/include/binder/Parcel.h
@@ -57,7 +57,8 @@
 
     status_t            writeInterfaceToken(const String16& interface);
     bool                enforceInterface(const String16& interface) const;
-            
+    bool                checkInterface(IBinder*) const;    
+
     void                freeData();
 
     const size_t*       objects() const;
@@ -73,6 +74,7 @@
     status_t            writeInt64(int64_t val);
     status_t            writeFloat(float val);
     status_t            writeDouble(double val);
+    status_t            writeIntPtr(intptr_t val);
     status_t            writeCString(const char* str);
     status_t            writeString8(const String8& str);
     status_t            writeString16(const String16& str);
@@ -108,6 +110,8 @@
     status_t            readFloat(float *pArg) const;
     double              readDouble() const;
     status_t            readDouble(double *pArg) const;
+    intptr_t            readIntPtr() const;
+    status_t            readIntPtr(intptr_t *pArg) const;
 
     const char*         readCString() const;
     String8             readString8() const;
@@ -147,7 +151,7 @@
                                             release_func relFunc, void* relCookie);
     
     void                print(TextOutput& to, uint32_t flags = 0) const;
-    
+        
 private:
                         Parcel(const Parcel& o);
     Parcel&             operator=(const Parcel& o);
@@ -162,6 +166,14 @@
     void                initState();
     void                scanForFds() const;
                         
+    template<class T>
+    status_t            readAligned(T *pArg) const;
+
+    template<class T>   T readAligned() const;
+
+    template<class T>
+    status_t            writeAligned(T val);
+
     status_t            mError;
     uint8_t*            mData;
     size_t              mDataSize;
diff --git a/include/binder/Permission.h b/include/binder/Permission.h
new file mode 100644
index 0000000..9542d50
--- /dev/null
+++ b/include/binder/Permission.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef BINDER_PERMISSION_H
+#define BINDER_PERMISSION_H
+
+#include <stdint.h>
+#include <unistd.h>
+
+#include <utils/SortedVector.h>
+#include <utils/String16.h>
+#include <utils/threads.h>
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+/*
+ * Permission caches the result of the permission check for the given
+ * permission name and the provided uid/pid. It also handles a few
+ * known cases efficiently (caller is in the same process or is root).
+ * The package manager does something similar but lives in dalvik world
+ * and is therefore extremely slow to access.
+ */
+
+class Permission
+{
+public:
+            Permission(char const* name);
+            Permission(const String16& name);
+            Permission(const Permission& rhs);
+    virtual ~Permission();
+
+    bool operator < (const Permission& rhs) const;
+
+    // checks the current binder call's caller has access to this permission
+    bool checkCalling() const;
+    
+    // checks the specified pid/uid has access to this permission
+    bool check(pid_t pid, uid_t uid) const;
+    
+protected:
+    virtual bool doCheckPermission(pid_t pid, uid_t uid) const;
+
+private:
+    Permission& operator = (const Permission& rhs) const;
+    const String16 mPermissionName;
+    mutable SortedVector<uid_t> mGranted;
+    const pid_t mPid;
+    mutable Mutex mLock;
+};
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
+#endif /* BINDER_PERMISSION_H */
diff --git a/include/utils/ProcessState.h b/include/binder/ProcessState.h
similarity index 98%
rename from include/utils/ProcessState.h
rename to include/binder/ProcessState.h
index 39584f4..feeb3c3 100644
--- a/include/utils/ProcessState.h
+++ b/include/binder/ProcessState.h
@@ -17,7 +17,7 @@
 #ifndef ANDROID_PROCESS_STATE_H
 #define ANDROID_PROCESS_STATE_H
 
-#include <utils/IBinder.h>
+#include <binder/IBinder.h>
 #include <utils/KeyedVector.h>
 #include <utils/String8.h>
 #include <utils/String16.h>
diff --git a/include/private/binder/Static.h b/include/private/binder/Static.h
new file mode 100644
index 0000000..5b0f9fc
--- /dev/null
+++ b/include/private/binder/Static.h
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+
+// All static variables go here, to control initialization and
+// destruction order in the library.
+
+#include <utils/threads.h>
+
+#include <binder/IBinder.h>
+#include <binder/IMemory.h>
+#include <binder/ProcessState.h>
+#include <binder/IPermissionController.h>
+#include <binder/IServiceManager.h>
+
+namespace android {
+
+// For ProcessState.cpp
+extern Mutex gProcessMutex;
+extern sp<ProcessState> gProcess;
+
+// For ServiceManager.cpp
+extern Mutex gDefaultServiceManagerLock;
+extern sp<IServiceManager> gDefaultServiceManager;
+extern sp<IPermissionController> gPermissionController;
+
+}   // namespace android
diff --git a/include/private/utils/binder_module.h b/include/private/binder/binder_module.h
similarity index 100%
rename from include/private/utils/binder_module.h
rename to include/private/binder/binder_module.h
diff --git a/include/private/opengles/gl_context.h b/include/private/opengles/gl_context.h
index a85f275..26cde38 100644
--- a/include/private/opengles/gl_context.h
+++ b/include/private/opengles/gl_context.h
@@ -26,10 +26,14 @@
 #endif
 
 #include <private/pixelflinger/ggl_context.h>
+#include <hardware/copybit.h>
+#include <hardware/gralloc.h>
 
 #include <GLES/gl.h>
 #include <GLES/glext.h>
 
+struct android_native_buffer_t;
+
 namespace android {
 
 const unsigned int OGLES_NUM_COMPRESSED_TEXTURE_FORMATS = 10;
@@ -39,7 +43,7 @@
 class EGLBufferObjectManager;
 
 namespace gl {
- 
+
 struct ogles_context_t;
 struct matrixx_t;
 struct transform_t;
@@ -96,7 +100,7 @@
 
 struct vertex_t {
     enum {
-        // these constant matter for our clipping 
+        // these constant matter for our clipping
         CLIP_L          = 0x0001,   // clipping flags
         CLIP_R          = 0x0002,
         CLIP_B          = 0x0004,
@@ -106,7 +110,7 @@
 
         EYE             = 0x0040,
         RESERVED        = 0x0080,
-        
+
         USER_CLIP_0     = 0x0100,   // user clipping flags
         USER_CLIP_1     = 0x0200,
         USER_CLIP_2     = 0x0400,
@@ -121,7 +125,7 @@
         USER_CLIP_ALL   = 0x3F00,
         CLIP_ALL        = 0x3F3F,
     };
-    
+
     // the fields below are arranged to minimize d-cache usage
     // we group together, by cache-line, the fields most likely to be used
 
@@ -130,7 +134,7 @@
     vec4_t          eye;
     };
     vec4_t          clip;
-    
+
     uint32_t        flags;
     size_t          index;  // cache tag, and vertex index
     GLfixed         fog;
@@ -142,7 +146,7 @@
     vec4_t          color;
     vec4_t          texture[GGL_TEXTURE_UNIT_COUNT];
     uint32_t        reserved1[4];
-    
+
     inline void clear() {
         flags = index = locked = mru = 0;
     }
@@ -199,7 +203,7 @@
     GLenum          indicesType;
     buffer_t const* array_buffer;
     buffer_t const* element_array_buffer;
-    
+
     void (*compileElements)(ogles_context_t*, vertex_t*, GLint, GLsizei);
     void (*compileElement)(ogles_context_t*, vertex_t*, GLint);
 
@@ -285,6 +289,7 @@
     vec4_t      normalizedObjPosition;
     vec4_t      spotDir;
     vec4_t      normalizedSpotDir;
+    vec4_t      objViewer;
     GLfixed     spotExp;
     GLfixed     spotCutoff;
     GLfixed     spotCutoffCosine;
@@ -410,7 +415,7 @@
     matrixx_t       matrix;
     uint32_t        flags;
     uint32_t        ops;
-    
+
     union {
         struct {
             void (*point2)(transform_t const* t, vec4_t*, vec4_t const*);
@@ -509,17 +514,17 @@
     GLint       x;
     GLint       y;
     GLsizei     w;
-    GLsizei     h; 
+    GLsizei     h;
     struct {
         GLint       x;
         GLint       y;
-    } surfaceport;  
+    } surfaceport;
     struct {
         GLint       x;
         GLint       y;
         GLsizei     w;
-        GLsizei     h; 
-    } scissor;  
+        GLsizei     h;
+    } scissor;
 };
 
 // ----------------------------------------------------------------------------
@@ -594,6 +599,14 @@
     void (*renderTriangle)(GL, vertex_t*, vertex_t*, vertex_t*);
 };
 
+struct copybits_context_t {
+    // A handle to the blit engine, if it exists, else NULL.
+    copybit_device_t*       blitEngine;
+    int32_t                 minScale;
+    int32_t                 maxScale;
+    android_native_buffer_t* drawSurfaceBuffer;
+};
+
 struct ogles_context_t {
     context_t               rasterizer;
     array_machine_t         arrays         __attribute__((aligned(32)));
@@ -617,6 +630,14 @@
     uint32_t                transformTextures : 1;
     EGLSurfaceManager*      surfaceManager;
     EGLBufferObjectManager* bufferObjectManager;
+
+    // copybits is only used if LIBAGL_USE_GRALLOC_COPYBITS is
+    // defined, but it is always present because ogles_context_t is a public
+    // struct that is used by clients of libagl. We want the size and offsets
+    // to stay the same, whether or not LIBAGL_USE_GRALLOC_COPYBITS is defined.
+
+    copybits_context_t      copybits;
+
     GLenum                  error;
 
     static inline ogles_context_t* get() {
diff --git a/include/private/ui/LayerState.h b/include/private/ui/LayerState.h
index b6fcd80..f1a2618 100644
--- a/include/private/ui/LayerState.h
+++ b/include/private/ui/LayerState.h
@@ -25,8 +25,6 @@
 #include <ui/ISurfaceFlingerClient.h>
 #include <ui/Region.h>
 
-#include <private/ui/SharedState.h>
-
 namespace android {
 
 class Parcel;
diff --git a/include/private/ui/RegionHelper.h b/include/private/ui/RegionHelper.h
new file mode 100644
index 0000000..8d76533
--- /dev/null
+++ b/include/private/ui/RegionHelper.h
@@ -0,0 +1,284 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_UI_PRIVATE_REGION_HELPER_H
+#define ANDROID_UI_PRIVATE_REGION_HELPER_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+namespace android {
+// ----------------------------------------------------------------------------
+
+template<typename RECT>
+class region_operator
+{
+    typedef typename RECT::value_type TYPE;    
+    static const TYPE max_value = 0x7FFFFFF;
+
+public:
+    /* 
+     * Common boolean operations:
+     * value is computed as 0b101 op 0b110
+     *    other boolean operation are possible, simply compute
+     *    their corresponding value with the above formulae and use
+     *    it when instantiating a region_operator.
+     */
+    static const uint32_t LHS = 0x5;  // 0b101
+    static const uint32_t RHS = 0x6;  // 0b110
+    enum {
+        op_nand = LHS & ~RHS,
+        op_and  = LHS &  RHS,
+        op_or   = LHS |  RHS,
+        op_xor  = LHS ^  RHS
+    };
+
+    struct region {
+        RECT const* rects;
+        size_t count;
+        TYPE dx;
+        TYPE dy;
+        inline region(const region& rhs) 
+            : rects(rhs.rects), count(rhs.count), dx(rhs.dx), dy(rhs.dy) { }
+        inline region(RECT const* r, size_t c) 
+            : rects(r), count(c), dx(), dy() { }
+        inline region(RECT const* r, size_t c, TYPE dx, TYPE dy) 
+            : rects(r), count(c), dx(dx), dy(dy) { }
+    };
+
+    class region_rasterizer {
+        friend class region_operator;
+        virtual void operator()(const RECT& rect) = 0;
+    public:
+        virtual ~region_rasterizer() { };
+    };
+    
+    inline region_operator(int op, const region& lhs, const region& rhs) 
+        : op_mask(op), spanner(lhs, rhs) 
+    {
+    }
+
+    void operator()(region_rasterizer& rasterizer) {
+        RECT current;
+        do {
+            SpannerInner spannerInner(spanner.lhs, spanner.rhs);
+            int inside = spanner.next(current.top, current.bottom);
+            spannerInner.prepare(inside);
+            do {
+                TYPE left, right;
+                int inside = spannerInner.next(current.left, current.right);
+                if ((op_mask >> inside) & 1) {
+                    if (current.left < current.right && 
+                            current.top < current.bottom) {
+                        rasterizer(current);
+                    }
+                }
+            } while(!spannerInner.isDone());
+        } while(!spanner.isDone());
+    }
+
+private:    
+    uint32_t op_mask;
+
+    class SpannerBase
+    {
+    public:
+        enum {
+            lhs_before_rhs   = 0,
+            lhs_after_rhs    = 1,
+            lhs_coincide_rhs = 2
+        };
+
+    protected:
+        TYPE lhs_head;
+        TYPE lhs_tail;
+        TYPE rhs_head;
+        TYPE rhs_tail;
+
+        inline int next(TYPE& head, TYPE& tail,
+                bool& more_lhs, bool& more_rhs) 
+        {
+            int inside;
+            more_lhs = false;
+            more_rhs = false;
+            if (lhs_head < rhs_head) {
+                inside = lhs_before_rhs;
+                head = lhs_head;
+                if (lhs_tail <= rhs_head) {
+                    tail = lhs_tail;
+                    more_lhs = true;
+                } else {
+                    lhs_head = rhs_head;
+                    tail = rhs_head;
+                }
+            } else if (rhs_head < lhs_head) {
+                inside = lhs_after_rhs;
+                head = rhs_head;
+                if (rhs_tail <= lhs_head) {
+                    tail = rhs_tail;
+                    more_rhs = true;
+                } else {
+                    rhs_head = lhs_head;
+                    tail = lhs_head;
+                }
+            } else {
+                inside = lhs_coincide_rhs;
+                head = lhs_head;
+                if (lhs_tail <= rhs_tail) {
+                    tail = rhs_head = lhs_tail;
+                    more_lhs = true;
+                }
+                if (rhs_tail <= lhs_tail) {
+                    tail = lhs_head = rhs_tail;
+                    more_rhs = true;
+                }
+            }
+            return inside;
+        }
+    };
+
+    class Spanner : protected SpannerBase 
+    {
+        friend class region_operator;
+        region lhs;
+        region rhs;
+
+    public:
+        inline Spanner(const region& lhs, const region& rhs)
+            : lhs(lhs), rhs(rhs) 
+        {
+            SpannerBase::lhs_head = lhs.rects->top      + lhs.dy;
+            SpannerBase::lhs_tail = lhs.rects->bottom   + lhs.dy;
+            SpannerBase::rhs_head = rhs.rects->top      + rhs.dy;
+            SpannerBase::rhs_tail = rhs.rects->bottom   + rhs.dy;
+        }
+
+        inline bool isDone() const {
+            return !rhs.count && !lhs.count;
+        }
+
+        inline int next(TYPE& top, TYPE& bottom) 
+        {
+            bool more_lhs = false;
+            bool more_rhs = false;
+            int inside = SpannerBase::next(top, bottom, more_lhs, more_rhs);
+            if (more_lhs) {
+                advance(lhs, SpannerBase::lhs_head, SpannerBase::lhs_tail);
+            }
+            if (more_rhs) {
+                advance(rhs, SpannerBase::rhs_head, SpannerBase::rhs_tail);
+            }
+            return inside;
+        }
+
+    private:
+        static inline 
+        void advance(region& reg, TYPE& aTop, TYPE& aBottom) {
+            // got to next span
+            size_t count = reg.count;
+            RECT const * rects = reg.rects;
+            RECT const * const end = rects + count;
+            const int top = rects->top;
+            while (rects != end && rects->top == top) {
+                rects++;
+                count--;
+            }
+            if (rects != end) {
+                aTop    = rects->top    + reg.dy;
+                aBottom = rects->bottom + reg.dy;
+            } else {
+                aTop    = max_value;
+                aBottom = max_value;
+            }
+            reg.rects = rects;
+            reg.count = count;
+        }
+    };
+
+    class SpannerInner : protected SpannerBase 
+    {
+        region lhs;
+        region rhs;
+        
+    public:
+        inline SpannerInner(const region& lhs, const region& rhs)
+            : lhs(lhs), rhs(rhs) 
+        {
+        }
+
+        inline void prepare(int inside) {
+            if (inside == SpannerBase::lhs_before_rhs) {
+                SpannerBase::lhs_head = lhs.rects->left  + lhs.dx;
+                SpannerBase::lhs_tail = lhs.rects->right + lhs.dx;
+                SpannerBase::rhs_head = max_value;
+                SpannerBase::rhs_tail = max_value;
+            } else if (inside == SpannerBase::lhs_after_rhs) {
+                SpannerBase::lhs_head = max_value;
+                SpannerBase::lhs_tail = max_value;
+                SpannerBase::rhs_head = rhs.rects->left  + rhs.dx;
+                SpannerBase::rhs_tail = rhs.rects->right + rhs.dx;
+            } else {
+                SpannerBase::lhs_head = lhs.rects->left  + lhs.dx;
+                SpannerBase::lhs_tail = lhs.rects->right + lhs.dx;
+                SpannerBase::rhs_head = rhs.rects->left  + rhs.dx;
+                SpannerBase::rhs_tail = rhs.rects->right + rhs.dx;
+            }
+        }
+
+        inline bool isDone() const {
+            return SpannerBase::lhs_head == max_value && 
+                   SpannerBase::rhs_head == max_value;
+        }
+
+        inline int next(TYPE& left, TYPE& right) 
+        {
+            bool more_lhs = false;
+            bool more_rhs = false;
+            int inside = SpannerBase::next(left, right, more_lhs, more_rhs);
+            if (more_lhs) {
+                advance(lhs, SpannerBase::lhs_head, SpannerBase::lhs_tail);
+            }
+            if (more_rhs) {
+                advance(rhs, SpannerBase::rhs_head, SpannerBase::rhs_tail);
+            }
+            return inside;
+        }
+
+    private:
+        static inline 
+        void advance(region& reg, TYPE& left, TYPE& right) {
+            if (reg.rects && reg.count) {
+                const int cur_span_top = reg.rects->top;
+                reg.rects++;
+                reg.count--;
+                if (!reg.count || reg.rects->top != cur_span_top) {
+                    left  = max_value;
+                    right = max_value;
+                } else {
+                    left  = reg.rects->left  + reg.dx;
+                    right = reg.rects->right + reg.dx;
+                }
+            }
+        }
+    };
+
+    Spanner spanner;
+};
+
+// ----------------------------------------------------------------------------
+};
+
+#endif /* ANDROID_UI_PRIVATE_REGION_HELPER_H */
diff --git a/include/private/ui/SharedBufferStack.h b/include/private/ui/SharedBufferStack.h
new file mode 100644
index 0000000..bbc1822
--- /dev/null
+++ b/include/private/ui/SharedBufferStack.h
@@ -0,0 +1,359 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_UI_SHARED_BUFFER_STACK_H
+#define ANDROID_UI_SHARED_BUFFER_STACK_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <cutils/compiler.h>
+
+#include <utils/Debug.h>
+#include <utils/threads.h>
+#include <utils/String8.h>
+
+#include <ui/Rect.h>
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+/*
+ * These classes manage a stack of buffers in shared memory.
+ * 
+ * SharedClient: represents a client with several stacks
+ * SharedBufferStack: represents a stack of buffers
+ * SharedBufferClient: manipulates the SharedBufferStack from the client side 
+ * SharedBufferServer: manipulates the SharedBufferStack from the server side 
+ *
+ * Buffers can be dequeued until there are none available, they can be locked
+ * unless they are in use by the server, which is only the case for the last 
+ * dequeue-able buffer. When these various conditions are not met, the caller
+ * waits until the condition is met.
+ *
+ * 
+ * CAVEATS:
+ * 
+ * In the current implementation there are several limitations:
+ * - buffers must be locked in the same order they've been dequeued
+ * - buffers must be enqueued in the same order they've been locked
+ * - dequeue() is not reentrant
+ * - no error checks are done on the condition above
+ * 
+ */
+
+// When changing these values, the COMPILE_TIME_ASSERT at the end of this
+// file need to be updated.
+const unsigned int NUM_LAYERS_MAX  = 31;
+const unsigned int NUM_BUFFER_MAX  = 4;
+const unsigned int NUM_DISPLAY_MAX = 4;
+
+// ----------------------------------------------------------------------------
+
+class Region;
+class SharedBufferStack;
+class SharedClient;
+
+// ----------------------------------------------------------------------------
+
+// should be 128 bytes (32 longs)
+class SharedBufferStack
+{
+    friend class SharedClient;
+    friend class SharedBufferBase;
+    friend class SharedBufferClient;
+    friend class SharedBufferServer;
+
+public:
+    struct FlatRegion { // 12 bytes
+        static const unsigned int NUM_RECT_MAX = 1;
+        uint32_t    count;
+        uint16_t    rects[4*NUM_RECT_MAX];
+    };
+    
+    struct Statistics { // 4 longs
+        typedef int32_t usecs_t;
+        usecs_t  totalTime;
+        usecs_t  reserved[3];
+    };
+    
+    SharedBufferStack();
+    void init(int32_t identity);
+    status_t setDirtyRegion(int buffer, const Region& reg);
+    Region getDirtyRegion(int buffer) const;
+
+    // these attributes are part of the conditions/updates
+    volatile int32_t head;      // server's current front buffer
+    volatile int32_t available; // number of dequeue-able buffers
+    volatile int32_t queued;    // number of buffers waiting for post
+    volatile int32_t inUse;     // buffer currently in use by SF
+    volatile status_t status;   // surface's status code
+
+    // not part of the conditions
+    volatile int32_t reallocMask;
+
+    int32_t     identity;       // surface's identity (const)
+    int32_t     reserved32[9];
+    Statistics  stats;
+    FlatRegion  dirtyRegion[NUM_BUFFER_MAX];    // 12*4=48 bytes
+};
+
+// ----------------------------------------------------------------------------
+
+// 4 KB max
+class SharedClient
+{
+public:
+    SharedClient();
+    ~SharedClient();
+
+    status_t validate(size_t token) const;
+    uint32_t getIdentity(size_t token) const;
+
+private:
+    friend class SharedBufferBase;
+    friend class SharedBufferClient;
+    friend class SharedBufferServer;
+
+    // FIXME: this should be replaced by a lock-less primitive
+    Mutex lock;
+    Condition cv;
+    SharedBufferStack surfaces[ NUM_LAYERS_MAX ];
+};
+
+// ============================================================================
+
+class SharedBufferBase
+{
+public:
+    SharedBufferBase(SharedClient* sharedClient, int surface, int num,
+            int32_t identity);
+    ~SharedBufferBase();
+    uint32_t getIdentity();
+    status_t getStatus() const;
+    size_t getFrontBuffer() const;
+    String8 dump(char const* prefix) const;
+
+protected:
+    SharedClient* const mSharedClient;
+    SharedBufferStack* const mSharedStack;
+    const int mNumBuffers;
+    const int mIdentity;
+
+    friend struct Update;
+    friend struct QueueUpdate;
+
+    struct ConditionBase {
+        SharedBufferStack& stack;
+        inline ConditionBase(SharedBufferBase* sbc) 
+            : stack(*sbc->mSharedStack) { }
+    };
+
+    struct UpdateBase {
+        SharedBufferStack& stack;
+        inline UpdateBase(SharedBufferBase* sbb) 
+            : stack(*sbb->mSharedStack) { }
+    };
+
+    template <typename T>
+    status_t waitForCondition(T condition);
+
+    template <typename T>
+    status_t updateCondition(T update);
+};
+
+template <typename T>
+status_t SharedBufferBase::waitForCondition(T condition) 
+{
+    const SharedBufferStack& stack( *mSharedStack );
+    SharedClient& client( *mSharedClient );
+    const nsecs_t TIMEOUT = s2ns(1);
+    Mutex::Autolock _l(client.lock);
+    while ((condition()==false) &&
+            (stack.identity == mIdentity) &&
+            (stack.status == NO_ERROR))
+    {
+        status_t err = client.cv.waitRelative(client.lock, TIMEOUT);
+        
+        // handle errors and timeouts
+        if (CC_UNLIKELY(err != NO_ERROR)) {
+            if (err == TIMED_OUT) {
+                if (condition()) {
+                    LOGE("waitForCondition(%s) timed out (identity=%d), "
+                        "but condition is true! We recovered but it "
+                        "shouldn't happen." , T::name(),
+                        stack.identity);
+                    break;
+                } else {
+                    LOGW("waitForCondition(%s) timed out "
+                        "(identity=%d, status=%d). "
+                        "CPU may be pegged. trying again.", T::name(),
+                        stack.identity, stack.status);
+                }
+            } else {
+                LOGE("waitForCondition(%s) error (%s) ",
+                        T::name(), strerror(-err));
+                return err;
+            }
+        }
+    }
+    return (stack.identity != mIdentity) ? status_t(BAD_INDEX) : stack.status;
+}
+
+
+template <typename T>
+status_t SharedBufferBase::updateCondition(T update) {
+    SharedClient& client( *mSharedClient );
+    Mutex::Autolock _l(client.lock);
+    ssize_t result = update();
+    client.cv.broadcast();    
+    return result;
+}
+
+// ----------------------------------------------------------------------------
+
+class SharedBufferClient : public SharedBufferBase
+{
+public:
+    SharedBufferClient(SharedClient* sharedClient, int surface, int num,
+            int32_t identity);
+
+    ssize_t dequeue();
+    status_t undoDequeue(int buf);
+    
+    status_t lock(int buf);
+    status_t queue(int buf);
+    bool needNewBuffer(int buffer) const;
+    status_t setDirtyRegion(int buffer, const Region& reg);
+    
+private:
+    friend struct Condition;
+    friend struct DequeueCondition;
+    friend struct LockCondition;
+    
+    int32_t computeTail() const;
+
+    struct QueueUpdate : public UpdateBase {
+        inline QueueUpdate(SharedBufferBase* sbb);
+        inline ssize_t operator()();
+    };
+
+    struct UndoDequeueUpdate : public UpdateBase {
+        inline UndoDequeueUpdate(SharedBufferBase* sbb);
+        inline ssize_t operator()();
+    };
+
+    // --
+
+    struct DequeueCondition : public ConditionBase {
+        inline DequeueCondition(SharedBufferClient* sbc);
+        inline bool operator()();
+        static inline const char* name() { return "DequeueCondition"; }
+    };
+
+    struct LockCondition : public ConditionBase {
+        int buf;
+        inline LockCondition(SharedBufferClient* sbc, int buf);
+        inline bool operator()();
+        static inline const char* name() { return "LockCondition"; }
+    };
+
+    int32_t tail;
+    // statistics...
+    nsecs_t mDequeueTime[NUM_BUFFER_MAX];
+};
+
+// ----------------------------------------------------------------------------
+
+class SharedBufferServer : public SharedBufferBase
+{
+public:
+    SharedBufferServer(SharedClient* sharedClient, int surface, int num,
+            int32_t identity);
+
+    ssize_t retireAndLock();
+    status_t unlock(int buffer);
+    void setStatus(status_t status);
+    status_t reallocate();
+    status_t assertReallocate(int buffer);
+    int32_t getQueuedCount() const;
+    
+    Region getDirtyRegion(int buffer) const;
+
+    SharedBufferStack::Statistics getStats() const;
+    
+
+private:
+    struct UnlockUpdate : public UpdateBase {
+        const int lockedBuffer;
+        inline UnlockUpdate(SharedBufferBase* sbb, int lockedBuffer);
+        inline ssize_t operator()();
+    };
+
+    struct RetireUpdate : public UpdateBase {
+        const int numBuffers;
+        inline RetireUpdate(SharedBufferBase* sbb, int numBuffers);
+        inline ssize_t operator()();
+    };
+
+    struct StatusUpdate : public UpdateBase {
+        const status_t status;
+        inline StatusUpdate(SharedBufferBase* sbb, status_t status);
+        inline ssize_t operator()();
+    };
+
+    struct ReallocateCondition : public ConditionBase {
+        int buf;
+        inline ReallocateCondition(SharedBufferBase* sbb, int buf);
+        inline bool operator()();
+        static inline const char* name() { return "ReallocateCondition"; }
+    };
+};
+
+// ===========================================================================
+
+struct display_cblk_t
+{
+    uint16_t    w;
+    uint16_t    h;
+    uint8_t     format;
+    uint8_t     orientation;
+    uint8_t     reserved[2];
+    float       fps;
+    float       density;
+    float       xdpi;
+    float       ydpi;
+    uint32_t    pad[2];
+};
+
+struct surface_flinger_cblk_t   // 4KB max
+{
+    uint8_t         connected;
+    uint8_t         reserved[3];
+    uint32_t        pad[7];
+    display_cblk_t  displays[NUM_DISPLAY_MAX];
+};
+
+// ---------------------------------------------------------------------------
+
+COMPILE_TIME_ASSERT(sizeof(SharedClient) <= 4096)
+COMPILE_TIME_ASSERT(sizeof(SharedBufferStack) == 128)
+COMPILE_TIME_ASSERT(sizeof(surface_flinger_cblk_t) <= 4096)
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
+#endif /* ANDROID_UI_SHARED_BUFFER_STACK_H */
diff --git a/include/private/ui/SharedState.h b/include/private/ui/SharedState.h
deleted file mode 100644
index 546d0ad..0000000
--- a/include/private/ui/SharedState.h
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_UI_SHARED_STATE_H
-#define ANDROID_UI_SHARED_STATE_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <utils/threads.h>
-
-namespace android {
-
-/*
- * These structures are shared between the composer process and its clients
- */
-
-// ---------------------------------------------------------------------------
-
-struct surface_info_t { // 4 longs, 16 bytes
-    enum {
-        eBufferDirty    = 0x01
-    };
-    uint16_t    w;
-    uint16_t    h;
-    uint16_t    stride;
-    uint16_t    bpr;
-    uint16_t    reserved;
-    uint8_t     format;
-    uint8_t     flags;
-    ssize_t     bits_offset;
-};
-
-// ---------------------------------------------------------------------------
-
-const uint32_t NUM_LAYERS_MAX = 31;
-
-enum { // layer_cblk_t swapState
-    eIndex              = 0x00000001,
-    eFlipRequested      = 0x00000002,
-    
-    eResizeBuffer0      = 0x00000004,
-    eResizeBuffer1      = 0x00000008,    
-    eResizeRequested    = eResizeBuffer0 | eResizeBuffer1,
-    
-    eBusy               = 0x00000010,
-    eLocked             = 0x00000020,
-    eNextFlipPending    = 0x00000040,    
-    eInvalidSurface     = 0x00000080
-};
-
-enum { // layer_cblk_t flags
-    eLayerNotPosted     = 0x00000001,
-    eNoCopyBack         = 0x00000002,
-    eReserved           = 0x0000007C,
-    eBufferIndexShift   = 7,
-    eBufferIndex        = 1<<eBufferIndexShift,
-};
-
-struct flat_region_t    // 40 bytes
-{
-    int32_t     count;
-    int16_t     l;
-    int16_t     t;
-    int16_t     r;
-    int16_t     b;
-    uint16_t    runs[14];
-};
-
-struct layer_cblk_t     // (128 bytes)
-{
-    volatile    int32_t             swapState;      //  4
-    volatile    int32_t             flags;          //  4
-    volatile    int32_t             identity;       //  4
-                int32_t             reserved;       //  4
-                surface_info_t      surface[2];     // 32
-                flat_region_t       region[2];      // 80
-
-    static inline int backBuffer(uint32_t state) {
-        return ((state & eIndex) ^ ((state & eFlipRequested)>>1));
-    }
-    static inline int frontBuffer(uint32_t state) {
-        return 1 - backBuffer(state);
-    }
-};
-
-// ---------------------------------------------------------------------------
-
-struct per_client_cblk_t   // 4KB max
-{
-                Mutex           lock;
-                Condition       cv;
-                layer_cblk_t    layers[NUM_LAYERS_MAX] __attribute__((aligned(32)));
-
-    enum {
-        BLOCKING = 0x00000001,
-        INSPECT  = 0x00000002
-    };
-
-    per_client_cblk_t();
-
-    // these functions are used by the clients
-    status_t validate(size_t i) const;
-    int32_t lock_layer(size_t i, uint32_t flags);
-    uint32_t unlock_layer_and_post(size_t i);
-    void unlock_layer(size_t i);
-};
-// ---------------------------------------------------------------------------
-
-const uint32_t NUM_DISPLAY_MAX = 4;
-
-struct display_cblk_t
-{
-    uint16_t    w;
-    uint16_t    h;
-    uint8_t     format;
-    uint8_t     orientation;
-    uint8_t     reserved[2];
-    float       fps;
-    float       density;
-    float       xdpi;
-    float       ydpi;
-    uint32_t    pad[2];
-};
-
-struct surface_flinger_cblk_t   // 4KB max
-{
-    surface_flinger_cblk_t();
-    
-    uint8_t         connected;
-    uint8_t         reserved[3];
-    uint32_t        pad[7];
- 
-    display_cblk_t  displays[NUM_DISPLAY_MAX];
-};
-
-// ---------------------------------------------------------------------------
-
-template<bool> struct CTA;
-template<> struct CTA<true> { };
-
-// compile-time assertions. just to avoid catastrophes.
-inline void compile_time_asserts() {
-    CTA<sizeof(layer_cblk_t) == 128> sizeof__layer_cblk_t__eq_128;
-    (void)sizeof__layer_cblk_t__eq_128; // we don't want a warning
-    CTA<sizeof(per_client_cblk_t) <= 4096> sizeof__per_client_cblk_t__le_4096;
-    (void)sizeof__per_client_cblk_t__le_4096;  // we don't want a warning
-    CTA<sizeof(surface_flinger_cblk_t) <= 4096> sizeof__surface_flinger_cblk_t__le_4096;
-    (void)sizeof__surface_flinger_cblk_t__le_4096;  // we don't want a warning
-}
-
-}; // namespace android
-
-#endif // ANDROID_UI_SHARED_STATE_H
-
diff --git a/include/private/ui/SurfaceFlingerSynchro.h b/include/private/ui/SurfaceFlingerSynchro.h
deleted file mode 100644
index ff91b61..0000000
--- a/include/private/ui/SurfaceFlingerSynchro.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * 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.
- */
-
-
-#ifndef ANDROID_SURFACE_FLINGER_SYNCHRO_H
-#define ANDROID_SURFACE_FLINGER_SYNCHRO_H
-
-#include <stdint.h>
-#include <sys/types.h>
-#include <utils/Errors.h>
-#include <utils/threads.h>
-#include <ui/ISurfaceComposer.h>
-
-namespace android {
-
-class SurfaceFlinger;
-
-class SurfaceFlingerSynchro
-{
-public:
-
-                // client constructor
-                SurfaceFlingerSynchro(const sp<ISurfaceComposer>& flinger);
-                ~SurfaceFlingerSynchro();
-    
-                // signal surfaceflinger for some work
-    status_t    signal();
-    
-private:
-    class Barrier {
-    public:
-        Barrier();
-        ~Barrier();
-        void open();
-        void close();
-        void waitAndClose();
-        status_t waitAndClose(nsecs_t timeout);
-    private:
-        enum { OPENED, CLOSED };
-        mutable     Mutex       lock;
-        mutable     Condition   cv;
-        volatile    int         state;
-    };
-
-    friend class SurfaceFlinger;
-
-                // server constructor
-                SurfaceFlingerSynchro();
-                
-    void        open();
-    
-                // wait until there is some work to do
-    status_t    wait();
-    status_t    wait(nsecs_t timeout);
-    
-    sp<ISurfaceComposer> mSurfaceComposer;
-    Barrier              mBarrier;
-};
-
-}; // namespace android
-
-#endif // ANDROID_SURFACE_FLINGER_SYNCHRO_H
-
diff --git a/im/java/android/im/ImPluginConsts.java b/include/private/ui/android_natives_priv.h
similarity index 67%
rename from im/java/android/im/ImPluginConsts.java
rename to include/private/ui/android_natives_priv.h
index 416493f..6b9f524 100644
--- a/im/java/android/im/ImPluginConsts.java
+++ b/include/private/ui/android_natives_priv.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2009 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.
@@ -14,14 +14,4 @@
  * limitations under the License.
  */
 
-package android.im;
-
-/**
- * @hide
- */
-public class ImPluginConsts {
-    /**
-     * The intent action name for the plugin service.
-     */
-    public static final String PLUGIN_ACTION_NAME = "android.im.plugin";
-}
\ No newline at end of file
+#include <ui/android_native_buffer.h>
diff --git a/include/private/ui/sw_gralloc_handle.h b/include/private/ui/sw_gralloc_handle.h
new file mode 100644
index 0000000..b3d333e
--- /dev/null
+++ b/include/private/ui/sw_gralloc_handle.h
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_UI_PRIVATE_SW_GRALLOC_HANDLE_H
+#define ANDROID_UI_PRIVATE_SW_GRALLOC_HANDLE_H
+
+#include <stdint.h>
+#include <limits.h>
+#include <sys/cdefs.h>
+#include <hardware/gralloc.h>
+#include <errno.h>
+
+#include <cutils/native_handle.h>
+
+namespace android {
+
+/*****************************************************************************/
+
+struct sw_gralloc_handle_t : public native_handle 
+{
+    // file-descriptors
+    int     fd;
+    // ints
+    int     magic;
+    int     size;
+    int     base;
+    int     prot;
+    int     pid;
+
+    static const int sNumInts = 5;
+    static const int sNumFds = 1;
+    static const int sMagic = '_sgh';
+
+    sw_gralloc_handle_t() :
+        fd(-1), magic(sMagic), size(0), base(0), prot(0), pid(getpid())
+    {
+        version = sizeof(native_handle);
+        numInts = sNumInts;
+        numFds = sNumFds;
+    }
+    ~sw_gralloc_handle_t() {
+        magic = 0;
+    }
+
+    static int validate(const native_handle* h) {
+        const sw_gralloc_handle_t* hnd = (const sw_gralloc_handle_t*)h;
+        if (!h || h->version != sizeof(native_handle) ||
+                h->numInts != sNumInts || h->numFds != sNumFds ||
+                hnd->magic != sMagic) 
+        {
+            return -EINVAL;
+        }
+        return 0;
+    }
+
+    static status_t alloc(uint32_t w, uint32_t h, int format,
+            int usage, buffer_handle_t* handle, int32_t* stride);
+    static status_t free(sw_gralloc_handle_t* hnd);
+    static status_t registerBuffer(sw_gralloc_handle_t* hnd);
+    static status_t unregisterBuffer(sw_gralloc_handle_t* hnd);
+    static status_t lock(sw_gralloc_handle_t* hnd, int usage,
+            int l, int t, int w, int h, void** vaddr);
+    static status_t unlock(sw_gralloc_handle_t* hnd);
+};
+
+/*****************************************************************************/
+
+}; // namespace android
+
+#endif /* ANDROID_UI_PRIVATE_SW_GRALLOC_HANDLE_H */
diff --git a/include/private/utils/Static.h b/include/private/utils/Static.h
index f1439b7..d95ae0d 100644
--- a/include/private/utils/Static.h
+++ b/include/private/utils/Static.h
@@ -20,14 +20,6 @@
 #include <utils/threads.h>
 #include <utils/KeyedVector.h>
 
-#ifndef LIBUTILS_NATIVE
-#include <utils/IBinder.h>
-#include <utils/IMemory.h>
-#include <utils/ProcessState.h>
-#include <utils/IPermissionController.h>
-#include <utils/IServiceManager.h>
-#endif
-
 namespace android {
 // For TextStream.cpp
 extern Vector<int32_t> gTextBuffers;
@@ -40,19 +32,4 @@
 extern void initialize_string16();
 extern void terminate_string16();
 
-
-
-#ifndef LIBUTILS_NATIVE
-
-// For ProcessState.cpp
-extern Mutex gProcessMutex;
-extern sp<ProcessState> gProcess;
-
-// For ServiceManager.cpp
-extern Mutex gDefaultServiceManagerLock;
-extern sp<IServiceManager> gDefaultServiceManager;
-extern sp<IPermissionController> gPermissionController;
-
-#endif
-
 }   // namespace android
diff --git a/include/private/utils/futex_synchro.h b/include/private/utils/futex_synchro.h
deleted file mode 100644
index ac2ab1995..0000000
--- a/include/private/utils/futex_synchro.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef _FUTEX_SYNCHRO_H
-#define _FUTEX_SYNCHRO_H
-
-#ifndef HAVE_FUTEX
-#error "HAVE_FUTEX not defined"
-#endif
-
-#define FUTEX_WAIT_INFINITE (0)
-
-typedef struct futex_mutex_t futex_mutex_t;
-
-struct futex_mutex_t 
-{
-    volatile int value;
-};
-
-typedef struct futex_cond_t futex_cond_t;
-
-struct futex_cond_t 
-{
-    volatile int value;
-};
-
-
-#if __cplusplus
-extern "C" {
-#endif
-
-void futex_mutex_init(futex_mutex_t *m);
-int futex_mutex_lock(futex_mutex_t *m, unsigned msec);
-void futex_mutex_unlock(futex_mutex_t *m);
-int futex_mutex_trylock(futex_mutex_t *m);
-
-void futex_cond_init(futex_cond_t *c);
-int futex_cond_wait(futex_cond_t *c, futex_mutex_t *m, unsigned msec);
-void futex_cond_signal(futex_cond_t *c);
-void futex_cond_broadcast(futex_cond_t *c);
-
-#if __cplusplus
-} // extern "C"
-#endif
-
-#endif // _FUTEX_SYNCHRO_H
-
diff --git a/include/tts/TtsEngine.h b/include/tts/TtsEngine.h
index 21cb73b..28b0d2f 100644
--- a/include/tts/TtsEngine.h
+++ b/include/tts/TtsEngine.h
@@ -43,7 +43,7 @@
 // @param [inout] void *&       - The userdata pointer set in the original
 //                                 synth call
 // @param [in]    uint32_t      - Track sampling rate in Hz
-// @param [in]    audio_format  - The AudioSystem::audio_format enum
+// @param [in]    uint32_t      - The audio format
 // @param [in]    int           - The number of channels
 // @param [inout] int8_t *&     - A buffer of audio data only valid during the
 //                                execution of the callback
@@ -54,7 +54,7 @@
 //         TTS_CALLBACK_CONTINUE to indicate the synthesis must continue if
 //            there is more data to produce.
 typedef tts_callback_status (synthDoneCB_t)(void *&, uint32_t,
-        AudioSystem::audio_format, int, int8_t *&, size_t&, tts_synth_status);
+        uint32_t, int, int8_t *&, size_t&, tts_synth_status);
 
 class TtsEngine;
 extern "C" TtsEngine* getTtsEngine();
@@ -80,6 +80,8 @@
 class TtsEngine
 {
 public:
+    virtual ~TtsEngine() {}
+
     // Initialize the TTS engine and returns whether initialization succeeded.
     // @param synthDoneCBPtr synthesis callback function pointer
     // @return TTS_SUCCESS, or TTS_FAILURE
diff --git a/include/ui/Camera.h b/include/ui/Camera.h
index afb07b5..5219772 100644
--- a/include/ui/Camera.h
+++ b/include/ui/Camera.h
@@ -66,15 +66,22 @@
 
 // msgType in notifyCallback and dataCallback functions
 enum {
-    CAMERA_MSG_ERROR = 0,
-    CAMERA_MSG_SHUTTER,
-    CAMERA_MSG_FOCUS,
-    CAMERA_MSG_ZOOM,
-    CAMERA_MSG_PREVIEW_FRAME,
-    CAMERA_MSG_VIDEO_FRAME,
-    CAMERA_MSG_POSTVIEW_FRAME,
-    CAMERA_MSG_RAW_IMAGE,
-    CAMERA_MSG_COMPRESSED_IMAGE
+    CAMERA_MSG_ERROR            = 0x001,
+    CAMERA_MSG_SHUTTER          = 0x002,
+    CAMERA_MSG_FOCUS            = 0x004,
+    CAMERA_MSG_ZOOM             = 0x008,
+    CAMERA_MSG_PREVIEW_FRAME    = 0x010,
+    CAMERA_MSG_VIDEO_FRAME      = 0x020,
+    CAMERA_MSG_POSTVIEW_FRAME   = 0x040,
+    CAMERA_MSG_RAW_IMAGE        = 0x080,
+    CAMERA_MSG_COMPRESSED_IMAGE = 0x100,
+    CAMERA_MSG_ALL_MSGS         = 0x1FF
+};
+
+// cmdType in sendCommand functions
+enum {
+    CAMERA_CMD_START_SMOOTH_ZOOM     = 1,
+    CAMERA_CMD_STOP_SMOOTH_ZOOM      = 2,
 };
 
 // camera fatal errors
@@ -142,6 +149,9 @@
             // autoFocus - status returned from callback
             status_t    autoFocus();
 
+            // cancel auto focus
+            status_t    cancelAutoFocus();
+
             // take a picture - picture returned from callback
             status_t    takePicture();
 
@@ -151,6 +161,9 @@
             // get preview/capture parameters - key/value pairs
             String8     getParameters() const;
 
+            // send command to camera driver
+            status_t    sendCommand(int32_t cmd, int32_t arg1, int32_t arg2);
+
             void        setListener(const sp<CameraListener>& listener);
             void        setPreviewCallbackFlags(int preview_callback_flag);
 
diff --git a/include/ui/CameraHardwareInterface.h b/include/ui/CameraHardwareInterface.h
index 822b4a8..240c134 100644
--- a/include/ui/CameraHardwareInterface.h
+++ b/include/ui/CameraHardwareInterface.h
@@ -17,30 +17,37 @@
 #ifndef ANDROID_HARDWARE_CAMERA_HARDWARE_INTERFACE_H
 #define ANDROID_HARDWARE_CAMERA_HARDWARE_INTERFACE_H
 
-#include <utils/IMemory.h>
+#include <binder/IMemory.h>
 #include <utils/RefBase.h>
+#include <ui/ISurface.h>
+#include <ui/Camera.h>
 #include <ui/CameraParameters.h>
 #include <ui/Overlay.h>
 
 namespace android {
+/**
+ *  The size of image for display.
+ */
+typedef struct image_rect_struct
+{
+  uint32_t width;      /* Image width */
+  uint32_t height;     /* Image height */
+} image_rect_type;
 
-/** Callback for startPreview() */
-typedef void (*preview_callback)(const sp<IMemory>& mem, void* user);
 
-/** Callback for startRecord() */
-typedef void (*recording_callback)(nsecs_t timestamp, const sp<IMemory>& mem, void* user);
+typedef void (*notify_callback)(int32_t msgType,
+                                int32_t ext1,
+                                int32_t ext2,
+                                void* user);
 
-/** Callback for takePicture() */
-typedef void (*shutter_callback)(void* user);
+typedef void (*data_callback)(int32_t msgType,
+                              const sp<IMemory>& dataPtr,
+                              void* user);
 
-/** Callback for takePicture() */
-typedef void (*raw_callback)(const sp<IMemory>& mem, void* user);
-
-/** Callback for takePicture() */
-typedef void (*jpeg_callback)(const sp<IMemory>& mem, void* user);
-
-/** Callback for autoFocus() */
-typedef void (*autofocus_callback)(bool focused, void* user);
+typedef void (*data_callback_timestamp)(nsecs_t timestamp,
+                                        int32_t msgType,
+                                        const sp<IMemory>& dataPtr,
+                                        void* user);
 
 /**
  * CameraHardwareInterface.h defines the interface to the
@@ -57,28 +64,21 @@
  *      CameraService calls getPreviewHeap() to establish access to the
  *      preview heap so it can be registered with SurfaceFlinger for
  *      efficient display updating while in preview mode.
- *   -# startPreview() is called, which is passed a preview_callback()
- *      function and a user parameter. The camera instance then periodically
- *      calls preview_callback() each time a new preview frame is available.
- *      The callback routine has two parameters: the first is a pointer to
- *      the IMemory containing the frame and the second a user parameter. If
- *      the preview_callback code needs to use this memory after returning,
- *      it must copy the data.
+ *   -# startPreview() is called.  The camera instance then periodically
+ *      sends the message CAMERA_MSG_PREVIEW_FRAME (if enabled) each time
+ *      a new preview frame is available.  If data callback code needs to use
+ *      this memory after returning, it must copy the data.
  *
- * Prior to taking a picture, CameraService calls autofocus() with
- * autofocus_callback() and a user parameter. When auto focusing has
- * completed, the camera instance calls autofocus_callback(), which informs
- * the application whether focusing was successful. The camera instance
- * only calls autofocus_callback() once and it is up to the application to
- * call autoFocus() again if refocusing is desired.
+ * Prior to taking a picture, CameraService calls autofocus(). When auto
+ * focusing has completed, the camera instance sends a CAMERA_MSG_FOCUS notification,
+ * which informs the application whether focusing was successful. The camera instance
+ * only sends this message once and it is up  to the application to call autoFocus()
+ * again if refocusing is desired.
  *
  * CameraService calls takePicture() to request the camera instance take a
- * picture. This method has two callbacks: raw_callback() and jpeg_callback().
- * When the raw image is available, raw_callback() is called with a pointer
- * to the IMemory containing the raw image. When the jpeg image is available,
- * jpeg_callback() is called with a pointer to the IMemory containing the
- * jpeg image. As with preview_callback(), the memory must be copied if it's
- * needed after returning.
+ * picture. At this point, if a shutter, postview, raw, and/or compressed callback
+ * is desired, the corresponding message must be enabled. As with CAMERA_MSG_PREVIEW_FRAME,
+ * any memory provided in a data callback must be copied if it's needed after returning.
  */
 class CameraHardwareInterface : public virtual RefBase {
 public:
@@ -90,17 +90,45 @@
     /** Return the IMemoryHeap for the raw image heap */
     virtual sp<IMemoryHeap>         getRawHeap() const = 0;
 
+    /** Set the notification and data callbacks */
+    virtual void setCallbacks(notify_callback notify_cb,
+                              data_callback data_cb,
+                              data_callback_timestamp data_cb_timestamp,
+                              void* user) = 0;
+
     /**
-     * Start preview mode. When a preview image is available
-     * preview_callback is called with the user parameter. The
-     * call back parameter may be null.
+     * The following three functions all take a msgtype,
+     * which is a bitmask of the messages defined in
+     * include/ui/Camera.h
      */
-    virtual status_t    startPreview(preview_callback cb, void* user) = 0;
+
+    /**
+     * Enable a message, or set of messages.
+     */
+    virtual void        enableMsgType(int32_t msgType) = 0;
+
+    /**
+     * Disable a message, or a set of messages.
+     */
+    virtual void        disableMsgType(int32_t msgType) = 0;
+
+    /**
+     * Query whether a message, or a set of messages, is enabled.
+     * Note that this is operates as an AND, if any of the messages
+     * queried are off, this will return false.
+     */
+    virtual bool        msgTypeEnabled(int32_t msgType) = 0;
+
+    /**
+     * Start preview mode.
+     */
+    virtual status_t    startPreview() = 0;
+
     /**
      * Only used if overlays are used for camera preview.
      */
-    virtual bool useOverlay() {return false;}
-    virtual status_t setOverlay(const sp<Overlay> &overlay) {return BAD_VALUE;}
+    virtual bool         useOverlay() {return false;}
+    virtual status_t     setOverlay(const sp<Overlay> &overlay) {return BAD_VALUE;}
 
     /**
      * Stop a previously started preview.
@@ -113,11 +141,11 @@
     virtual bool        previewEnabled() = 0;
 
     /**
-     * Start record mode. When a record image is available recording_callback()
-     * is called with the user parameter.  Every record frame must be released
+     * Start record mode. When a record image is available a CAMERA_MSG_VIDEO_FRAME
+     * message is sent with the corresponding frame. Every record frame must be released
      * by calling releaseRecordingFrame().
      */
-    virtual status_t    startRecording(recording_callback cb, void* user) = 0;
+    virtual status_t    startRecording() = 0;
 
     /**
      * Stop a previously started recording.
@@ -128,41 +156,37 @@
      * Returns true if recording is enabled.
      */
     virtual bool        recordingEnabled() = 0;
-    
+
     /**
-     * Release a record frame previously returned by the recording_callback()
-     * passed to startRecord().
+     * Release a record frame previously returned by CAMERA_MSG_VIDEO_FRAME.
      */
     virtual void        releaseRecordingFrame(const sp<IMemory>& mem) = 0;
 
     /**
-     * Start auto focus, the callback routine is called
-     * once when focusing is complete. autoFocus() will
-     * be called again if another auto focus is needed.
+     * Start auto focus, the notification callback routine is called
+     * with CAMERA_MSG_FOCUS once when focusing is complete. autoFocus()
+     * will be called again if another auto focus is needed.
      */
-    virtual status_t    autoFocus(autofocus_callback,
-                                  void* user) = 0;
+    virtual status_t    autoFocus() = 0;
 
     /**
-     * Take a picture. The raw_callback is called when
-     * the uncompressed image is available. The jpeg_callback
-     * is called when the compressed image is available. These
-     * call backs may be null. The user parameter is passed
-     * to each of the call back routines.
+     * Cancels auto-focus function. If the auto-focus is still in progress,
+     * this function will cancel it. Whether the auto-focus is in progress
+     * or not, this function will return the focus position to the default.
+     * If the camera does not support auto-focus, this is a no-op.
      */
-    virtual status_t    takePicture(shutter_callback,
-                                    raw_callback,
-                                    jpeg_callback,
-                                    void* user) = 0;
+    virtual status_t    cancelAutoFocus() = 0;
 
     /**
-     * Cancel a picture that was started with takePicture.  You may cancel any
-     * of the shutter, raw, or jpeg callbacks.  Calling this method when no
-     * picture is being taken is a no-op.
+     * Take a picture.
      */
-    virtual status_t    cancelPicture(bool cancel_shutter,
-                                      bool cancel_raw,
-                                      bool cancel_jpeg) = 0;
+    virtual status_t    takePicture() = 0;
+
+    /**
+     * Cancel a picture that was started with takePicture.  Calling this
+     * method when no picture is being taken is a no-op.
+     */
+    virtual status_t    cancelPicture() = 0;
 
     /** Set the camera parameters. */
     virtual status_t    setParameters(const CameraParameters& params) = 0;
@@ -171,11 +195,16 @@
     virtual CameraParameters  getParameters() const = 0;
 
     /**
+     * Send command to camera driver.
+     */
+    virtual status_t sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) = 0;
+
+    /**
      * Release the hardware resources owned by this object.  Note that this is
      * *not* done in the destructor.
      */
     virtual void release() = 0;
-    
+
     /**
      * Dump state of the camera hardware
      */
diff --git a/include/ui/CameraParameters.h b/include/ui/CameraParameters.h
index 9ca1806..9e4e140 100644
--- a/include/ui/CameraParameters.h
+++ b/include/ui/CameraParameters.h
@@ -69,11 +69,205 @@
     void dump() const;
     status_t dump(int fd, const Vector<String16>& args) const;
 
+    // Parameter keys to communicate between camera application and driver.
+    // The access (read/write, read only, or write only) is viewed from the
+    // perspective of applications, not driver.
+
+    // Preview frame size in pixels (width x height).
+    // Example value: "480x320". Read/Write.
+    static const char KEY_PREVIEW_SIZE[];
+    // Supported preview frame sizes in pixels.
+    // Example value: "800x600,480x320". Read only.
+    static const char KEY_SUPPORTED_PREVIEW_SIZES[];
+    // The image format for preview frames.
+    // Example value: "yuv420sp" or PIXEL_FORMAT_XXX constants. Read/write.
+    static const char KEY_PREVIEW_FORMAT[];
+    // Supported image formats for preview frames.
+    // Example value: "yuv420sp,yuv422i-yuyv". Read only.
+    static const char KEY_SUPPORTED_PREVIEW_FORMATS[];
+    // Number of preview frames per second.
+    // Example value: "15". Read/write.
+    static const char KEY_PREVIEW_FRAME_RATE[];
+    // Supported number of preview frames per second.
+    // Example value: "24,15,10". Read.
+    static const char KEY_SUPPORTED_PREVIEW_FRAME_RATES[];
+    // The dimensions for captured pictures in pixels (width x height).
+    // Example value: "1024x768". Read/write.
+    static const char KEY_PICTURE_SIZE[];
+    // Supported dimensions for captured pictures in pixels.
+    // Example value: "2048x1536,1024x768". Read only.
+    static const char KEY_SUPPORTED_PICTURE_SIZES[];
+    // The image format for captured pictures.
+    // Example value: "jpeg" or PIXEL_FORMAT_XXX constants. Read/write.
+    static const char KEY_PICTURE_FORMAT[];
+    // Supported image formats for captured pictures.
+    // Example value: "jpeg,rgb565". Read only.
+    static const char KEY_SUPPORTED_PICTURE_FORMATS[];
+    // The width (in pixels) of EXIF thumbnail in Jpeg picture.
+    // Example value: "512". Read/write.
+    static const char KEY_JPEG_THUMBNAIL_WIDTH[];
+    // The height (in pixels) of EXIF thumbnail in Jpeg picture.
+    // Example value: "384". Read/write.
+    static const char KEY_JPEG_THUMBNAIL_HEIGHT[];
+    // Supported EXIF thumbnail sizes (width x height).
+    // Example value: "512x384,320x240". Read only.
+    static const char KEY_SUPPORTED_THUMBNAIL_SIZES[];
+    // The quality of the EXIF thumbnail in Jpeg picture. The range is 1 to 100,
+    // with 100 being the best.
+    // Example value: "90". Read/write.
+    static const char KEY_JPEG_THUMBNAIL_QUALITY[];
+    // Jpeg quality of captured picture. The range is 1 to 100, with 100 being
+    // the best.
+    // Example value: "90". Read/write.
+    static const char KEY_JPEG_QUALITY[];
+    // The orientation of the device in degrees. For example, suppose the
+    // natural position of the device is landscape. If the user takes a picture
+    // in landscape mode in 2048x1536 resolution, the rotation will be set to
+    // "0". If the user rotates the phone 90 degrees clockwise, the rotation
+    // should be set to "90".
+    // The camera driver can set orientation in the EXIF header without rotating
+    // the picture. Or the driver can rotate the picture and the EXIF thumbnail.
+    // If the Jpeg picture is rotated, the orientation in the EXIF header should
+    // be missing or 1 (row #0 is top and column #0 is left side). The driver
+    // should not set default value for this parameter.
+    // Example value: "0" or "90" or "180" or "270". Write only.
+    static const char KEY_ROTATION[];
+    // GPS latitude coordinate. This will be stored in JPEG EXIF header.
+    // Example value: "25.032146". Write only.
+    static const char KEY_GPS_LATITUDE[];
+    // GPS longitude coordinate. This will be stored in JPEG EXIF header.
+    // Example value: "121.564448". Write only.
+    static const char KEY_GPS_LONGITUDE[];
+    // GPS altitude. This will be stored in JPEG EXIF header.
+    // Example value: "21.0". Write only.
+    static const char KEY_GPS_ALTITUDE[];
+    // GPS timestamp (UTC in seconds since January 1, 1970). This should be
+    // stored in JPEG EXIF header.
+    // Example value: "1251192757". Write only.
+    static const char KEY_GPS_TIMESTAMP[];
+    // Current white balance setting.
+    // Example value: "auto" or WHITE_BALANCE_XXX constants. Read/write.
+    static const char KEY_WHITE_BALANCE[];
+    // Supported white balance settings.
+    // Example value: "auto,incandescent,daylight". Read only.
+    static const char KEY_SUPPORTED_WHITE_BALANCE[];
+    // Current color effect setting.
+    // Example value: "none" or EFFECT_XXX constants. Read/write.
+    static const char KEY_EFFECT[];
+    // Supported color effect settings.
+    // Example value: "none,mono,sepia". Read only.
+    static const char KEY_SUPPORTED_EFFECTS[];
+    // Current antibanding setting.
+    // Example value: "auto" or ANTIBANDING_XXX constants. Read/write.
+    static const char KEY_ANTIBANDING[];
+    // Supported antibanding settings.
+    // Example value: "auto,50hz,60hz,off". Read only.
+    static const char KEY_SUPPORTED_ANTIBANDING[];
+    // Current scene mode.
+    // Example value: "auto" or SCENE_MODE_XXX constants. Read/write.
+    static const char KEY_SCENE_MODE[];
+    // Supported scene mode settings.
+    // Example value: "auto,night,fireworks". Read only.
+    static const char KEY_SUPPORTED_SCENE_MODES[];
+    // Current flash mode.
+    // Example value: "auto" or FLASH_MODE_XXX constants. Read/write.
+    static const char KEY_FLASH_MODE[];
+    // Supported flash modes.
+    // Example value: "auto,on,off". Read only.
+    static const char KEY_SUPPORTED_FLASH_MODES[];
+    // Current focus mode. If the camera does not support auto-focus, the value
+    // should be FOCUS_MODE_FIXED. If the focus mode is not FOCUS_MODE_FIXED or
+    // or FOCUS_MODE_INFINITY, applications should call
+    // CameraHardwareInterface.autoFocus to start the focus.
+    // Example value: "auto" or FOCUS_MODE_XXX constants. Read/write.
+    static const char KEY_FOCUS_MODE[];
+    // Supported focus modes.
+    // Example value: "auto,macro,fixed". Read only.
+    static const char KEY_SUPPORTED_FOCUS_MODES[];
+
+        // Values for white balance settings.
+    static const char WHITE_BALANCE_AUTO[];
+    static const char WHITE_BALANCE_INCANDESCENT[];
+    static const char WHITE_BALANCE_FLUORESCENT[];
+    static const char WHITE_BALANCE_WARM_FLUORESCENT[];
+    static const char WHITE_BALANCE_DAYLIGHT[];
+    static const char WHITE_BALANCE_CLOUDY_DAYLIGHT[];
+    static const char WHITE_BALANCE_TWILIGHT[];
+    static const char WHITE_BALANCE_SHADE[];
+
+    // Values for effect settings.
+    static const char EFFECT_NONE[];
+    static const char EFFECT_MONO[];
+    static const char EFFECT_NEGATIVE[];
+    static const char EFFECT_SOLARIZE[];
+    static const char EFFECT_SEPIA[];
+    static const char EFFECT_POSTERIZE[];
+    static const char EFFECT_WHITEBOARD[];
+    static const char EFFECT_BLACKBOARD[];
+    static const char EFFECT_AQUA[];
+
+    // Values for antibanding settings.
+    static const char ANTIBANDING_AUTO[];
+    static const char ANTIBANDING_50HZ[];
+    static const char ANTIBANDING_60HZ[];
+    static const char ANTIBANDING_OFF[];
+
+    // Values for flash mode settings.
+    // Flash will not be fired.
+    static const char FLASH_MODE_OFF[];
+    // Flash will be fired automatically when required. The flash may be fired
+    // during preview, auto-focus, or snapshot depending on the driver.
+    static const char FLASH_MODE_AUTO[];
+    // Flash will always be fired during snapshot. The flash may also be
+    // fired during preview or auto-focus depending on the driver.
+    static const char FLASH_MODE_ON[];
+    // Flash will be fired in red-eye reduction mode.
+    static const char FLASH_MODE_RED_EYE[];
+    // Constant emission of light during preview, auto-focus and snapshot.
+    // This can also be used for video recording.
+    static const char FLASH_MODE_TORCH[];
+
+    // Values for scene mode settings.
+    static const char SCENE_MODE_AUTO[];
+    static const char SCENE_MODE_ACTION[];
+    static const char SCENE_MODE_PORTRAIT[];
+    static const char SCENE_MODE_LANDSCAPE[];
+    static const char SCENE_MODE_NIGHT[];
+    static const char SCENE_MODE_NIGHT_PORTRAIT[];
+    static const char SCENE_MODE_THEATRE[];
+    static const char SCENE_MODE_BEACH[];
+    static const char SCENE_MODE_SNOW[];
+    static const char SCENE_MODE_SUNSET[];
+    static const char SCENE_MODE_STEADYPHOTO[];
+    static const char SCENE_MODE_FIREWORKS[];
+    static const char SCENE_MODE_SPORTS[];
+    static const char SCENE_MODE_PARTY[];
+    static const char SCENE_MODE_CANDLELIGHT[];
+
+    // Formats for setPreviewFormat and setPictureFormat.
+    static const char PIXEL_FORMAT_YUV422SP[];
+    static const char PIXEL_FORMAT_YUV420SP[]; // NV21
+    static const char PIXEL_FORMAT_YUV422I[]; // YUY2
+    static const char PIXEL_FORMAT_RGB565[];
+    static const char PIXEL_FORMAT_JPEG[];
+
+    // Values for focus mode settings.
+    // Auto-focus mode.
+    static const char FOCUS_MODE_AUTO[];
+    // Focus is set at infinity. Applications should not call
+    // CameraHardwareInterface.autoFocus in this mode.
+    static const char FOCUS_MODE_INFINITY[];
+    static const char FOCUS_MODE_MACRO[];
+    // Focus is fixed. The camera is always in this mode if the focus is not
+    // adjustable. If the camera has auto-focus, this mode can fix the
+    // focus, which is usually at hyperfocal distance. Applications should
+    // not call CameraHardwareInterface.autoFocus in this mode.
+    static const char FOCUS_MODE_FIXED[];
+
 private:
     DefaultKeyedVector<String8,String8>    mMap;
 };
 
-
 }; // namespace android
 
 #endif
diff --git a/include/ui/EGLDisplaySurface.h b/include/ui/EGLDisplaySurface.h
deleted file mode 100644
index a8b5853..0000000
--- a/include/ui/EGLDisplaySurface.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_EGL_DISPLAY_SURFACE_H
-#define ANDROID_EGL_DISPLAY_SURFACE_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <utils/Timers.h>
-
-#include <ui/EGLNativeSurface.h>
-
-#include <pixelflinger/pixelflinger.h>
-#include <linux/fb.h>
-
-#include <EGL/egl.h>
-
-struct copybit_device_t;
-struct copybit_image_t;
-
-// ---------------------------------------------------------------------------
-namespace android {
-// ---------------------------------------------------------------------------
-
-class Region;
-class Rect;
-
-class EGLDisplaySurface : public EGLNativeSurface<EGLDisplaySurface>
-{
-public:
-    EGLDisplaySurface();
-    ~EGLDisplaySurface();
-    
-    int32_t getPageFlipCount() const;
-    void    copyFrontToBack(const Region& copyback);
-    void    copyFrontToImage(const copybit_image_t& dst);
-    void    copyBackToImage(const copybit_image_t& dst);
-    
-    void        setSwapRectangle(int l, int t, int w, int h);
-
-private:
-    static void         hook_incRef(NativeWindowType window);
-    static void         hook_decRef(NativeWindowType window);
-    static uint32_t     hook_swapBuffers(NativeWindowType window);
-     
-            uint32_t    swapBuffers();
-
-            status_t    mapFrameBuffer();
-
-            enum {
-                PAGE_FLIP = 0x00000001
-            };
-    GGLSurface          mFb[2];
-    int                 mIndex;
-    uint32_t            mFlags;
-    size_t              mSize;
-    fb_var_screeninfo   mInfo;
-    fb_fix_screeninfo   mFinfo;
-    int32_t             mPageFlipCount;
-    nsecs_t             mTime;
-    int32_t             mSwapCount;
-    nsecs_t             mSleep;
-    uint32_t            mFeatureFlags;
-    copybit_device_t*   mBlitEngine;
-};
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-// ---------------------------------------------------------------------------
-
-#endif // ANDROID_EGL_DISPLAY_SURFACE_H
-
diff --git a/include/ui/EGLNativeWindowSurface.h b/include/ui/EGLNativeWindowSurface.h
deleted file mode 100644
index 3494234..0000000
--- a/include/ui/EGLNativeWindowSurface.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_EGL_NATIVE_WINDOW_SURFACE_H
-#define ANDROID_EGL_NATIVE_WINDOW_SURFACE_H
-
-#include <stdint.h>
-#include <sys/types.h>
-#include <ui/EGLNativeSurface.h>
-#include <EGL/egl.h>
-
-// ---------------------------------------------------------------------------
-namespace android {
-// ---------------------------------------------------------------------------
-
-class Surface;
-
-class EGLNativeWindowSurface : public EGLNativeSurface<EGLNativeWindowSurface>
-{
-public:
-    EGLNativeWindowSurface(const sp<Surface>& surface);
-    ~EGLNativeWindowSurface();
-
-    void        setSwapRectangle(int l, int t, int w, int h);
-
-private:
-    static void         hook_incRef(NativeWindowType window);
-    static void         hook_decRef(NativeWindowType window);
-    static uint32_t     hook_swapBuffers(NativeWindowType window);
-    static void         hook_connect(NativeWindowType window);
-    static void         hook_disconnect(NativeWindowType window);
-
-            uint32_t    swapBuffers();
-            void        connect();
-            void        disconnect();
-            
-            sp<Surface> mSurface;
-            bool        mConnected;
-};
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-// ---------------------------------------------------------------------------
-
-#endif // ANDROID_EGL_NATIVE_WINDOW_SURFACE_H
-
diff --git a/include/ui/EGLUtils.h b/include/ui/EGLUtils.h
new file mode 100644
index 0000000..a5bff81
--- /dev/null
+++ b/include/ui/EGLUtils.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifndef ANDROID_UI_EGLUTILS_H
+#define ANDROID_UI_EGLUTILS_H
+
+#include <utils/Errors.h>
+#include <ui/PixelFormat.h>
+#include <EGL/egl.h>
+
+
+// ----------------------------------------------------------------------------
+namespace android {
+// ----------------------------------------------------------------------------
+
+class EGLUtils
+{
+public:
+
+    static const char *strerror(EGLint err);
+
+    static status_t selectConfigForPixelFormat(
+            EGLDisplay dpy,
+            EGLint const* attrs,
+            PixelFormat format,
+            EGLConfig* outConfig);
+
+    static status_t selectConfigForNativeWindow(
+            EGLDisplay dpy,
+            EGLint const* attrs,
+            EGLNativeWindowType window,
+            EGLConfig* outConfig);
+};
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+// ----------------------------------------------------------------------------
+
+#endif /* ANDROID_UI_EGLUTILS_H */
diff --git a/include/ui/EventHub.h b/include/ui/EventHub.h
index 3848d8c..3b18c77 100644
--- a/include/ui/EventHub.h
+++ b/include/ui/EventHub.h
@@ -20,7 +20,10 @@
 
 #include <utils/String8.h>
 #include <utils/threads.h>
-#include <utils.h>
+#include <utils/Log.h>
+#include <utils/threads.h>
+#include <utils/List.h>
+#include <utils/Errors.h>
 
 #include <linux/input.h>
 
@@ -52,7 +55,9 @@
         CLASS_KEYBOARD      = 0x00000001,
         CLASS_ALPHAKEY      = 0x00000002,
         CLASS_TOUCHSCREEN   = 0x00000004,
-        CLASS_TRACKBALL     = 0x00000008
+        CLASS_TRACKBALL     = 0x00000008,
+        CLASS_TOUCHSCREEN_MT= 0x00000010,
+        CLASS_DPAD          = 0x00000020
     };
     uint32_t getDeviceClasses(int32_t deviceId) const;
     
@@ -70,6 +75,13 @@
     int getKeycodeState(int key) const;
     int getKeycodeState(int32_t deviceId, int key) const;
     
+    status_t scancodeToKeycode(int32_t deviceId, int scancode,
+            int32_t* outKeycode, uint32_t* outFlags) const;
+
+    // exclude a particular device from opening
+    // this can be used to ignore input devices for sensors
+    void addExcludedDevice(const char* deviceName);
+
     // special type codes when devices are added/removed.
     enum {
         DEVICE_ADDED = 0x10000000,
@@ -82,10 +94,9 @@
     virtual bool getEvent(int32_t* outDeviceId, int32_t* outType,
             int32_t* outScancode, int32_t* outKeycode, uint32_t *outFlags,
             int32_t* outValue, nsecs_t* outWhen);
-    
+
 protected:
     virtual ~EventHub();
-    virtual void onFirstRef();
     
 private:
     bool openPlatformInput(void);
@@ -108,17 +119,18 @@
         String8         keylayoutFilename;
         device_t*       next;
         
-        device_t(int32_t _id, const char* _path);
+        device_t(int32_t _id, const char* _path, const char* name);
         ~device_t();
     };
 
     device_t* getDevice(int32_t deviceId) const;
+    bool hasKeycode(device_t* device, int keycode) const;
     
     // Protect all internal state.
     mutable Mutex   mLock;
     
     bool            mHaveFirstKeyboard;
-    int32_t         mFirstKeyboardId; // the API is that the build in keyboard is id 0, so map it
+    int32_t         mFirstKeyboardId; // the API is that the built-in keyboard is id 0, so map it
     
     struct device_ent {
         device_t* device;
@@ -133,7 +145,10 @@
     device_t        **mDevices;
     struct pollfd   *mFDs;
     int             mFDCount;
-    
+
+    bool            mOpened;
+    List<String8>   mExcludedDevices;
+
     // device ids that report particular switches.
 #ifdef EV_SW
     int32_t         mSwitches[SW_MAX+1];
diff --git a/include/ui/FramebufferNativeWindow.h b/include/ui/FramebufferNativeWindow.h
new file mode 100644
index 0000000..8ea3ab9
--- /dev/null
+++ b/include/ui/FramebufferNativeWindow.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_FRAMEBUFFER_NATIVE_WINDOW_H
+#define ANDROID_FRAMEBUFFER_NATIVE_WINDOW_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <EGL/egl.h>
+
+#include <utils/threads.h>
+#include <ui/Rect.h>
+
+#include <pixelflinger/pixelflinger.h>
+
+#include <ui/egl/android_natives.h>
+
+
+extern "C" EGLNativeWindowType android_createDisplaySurface(void);
+
+// ---------------------------------------------------------------------------
+namespace android {
+// ---------------------------------------------------------------------------
+
+class Surface;
+class NativeBuffer;
+
+// ---------------------------------------------------------------------------
+
+class FramebufferNativeWindow 
+    : public EGLNativeBase<
+        android_native_window_t, 
+        FramebufferNativeWindow, 
+        LightRefBase<FramebufferNativeWindow> >
+{
+public:
+    FramebufferNativeWindow(); 
+
+    framebuffer_device_t const * getDevice() const { return fbDev; } 
+
+    bool isUpdateOnDemand() const { return mUpdateOnDemand; }
+    status_t setUpdateRectangle(const Rect& updateRect);
+    status_t compositionComplete();
+    
+private:
+    friend class LightRefBase<FramebufferNativeWindow>;    
+    ~FramebufferNativeWindow(); // this class cannot be overloaded
+    static int setSwapInterval(android_native_window_t* window, int interval);
+    static int dequeueBuffer(android_native_window_t* window, android_native_buffer_t** buffer);
+    static int lockBuffer(android_native_window_t* window, android_native_buffer_t* buffer);
+    static int queueBuffer(android_native_window_t* window, android_native_buffer_t* buffer);
+    static int query(android_native_window_t* window, int what, int* value);
+    static int perform(android_native_window_t* window, int operation, ...);
+    
+    framebuffer_device_t* fbDev;
+    alloc_device_t* grDev;
+
+    sp<NativeBuffer> buffers[2];
+    sp<NativeBuffer> front;
+    
+    mutable Mutex mutex;
+    Condition mCondition;
+    int32_t mNumBuffers;
+    int32_t mNumFreeBuffers;
+    int32_t mBufferHead;
+    bool mUpdateOnDemand;
+};
+    
+// ---------------------------------------------------------------------------
+}; // namespace android
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_FRAMEBUFFER_NATIVE_WINDOW_H
+
diff --git a/include/ui/GraphicBuffer.h b/include/ui/GraphicBuffer.h
new file mode 100644
index 0000000..b9c491b
--- /dev/null
+++ b/include/ui/GraphicBuffer.h
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_GRAPHIC_BUFFER_H
+#define ANDROID_GRAPHIC_BUFFER_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <ui/android_native_buffer.h>
+#include <ui/PixelFormat.h>
+#include <ui/Rect.h>
+#include <pixelflinger/pixelflinger.h>
+
+struct android_native_buffer_t;
+
+namespace android {
+
+class GraphicBufferMapper;
+class Parcel;
+
+// ===========================================================================
+// GraphicBuffer
+// ===========================================================================
+
+class GraphicBuffer
+    : public EGLNativeBase<
+        android_native_buffer_t, 
+        GraphicBuffer, 
+        LightRefBase<GraphicBuffer> >
+{
+public:
+
+    enum {
+        USAGE_SW_READ_NEVER     = GRALLOC_USAGE_SW_READ_NEVER,
+        USAGE_SW_READ_RARELY    = GRALLOC_USAGE_SW_READ_RARELY,
+        USAGE_SW_READ_OFTEN     = GRALLOC_USAGE_SW_READ_OFTEN,
+        USAGE_SW_READ_MASK      = GRALLOC_USAGE_SW_READ_MASK,
+        
+        USAGE_SW_WRITE_NEVER    = GRALLOC_USAGE_SW_WRITE_NEVER,
+        USAGE_SW_WRITE_RARELY   = GRALLOC_USAGE_SW_WRITE_RARELY,
+        USAGE_SW_WRITE_OFTEN    = GRALLOC_USAGE_SW_WRITE_OFTEN,
+        USAGE_SW_WRITE_MASK     = GRALLOC_USAGE_SW_WRITE_MASK,
+        
+        USAGE_SOFTWARE_MASK     = USAGE_SW_READ_MASK|USAGE_SW_WRITE_MASK,
+        
+        USAGE_HW_TEXTURE        = GRALLOC_USAGE_HW_TEXTURE,
+        USAGE_HW_RENDER         = GRALLOC_USAGE_HW_RENDER,
+        USAGE_HW_2D             = GRALLOC_USAGE_HW_2D,
+        USAGE_HW_MASK           = GRALLOC_USAGE_HW_MASK
+    };
+
+    GraphicBuffer();
+
+    // creates w * h buffer
+    GraphicBuffer(uint32_t w, uint32_t h, PixelFormat format, uint32_t usage);
+
+    // create a buffer from an existing handle
+    GraphicBuffer(uint32_t w, uint32_t h, PixelFormat format, uint32_t usage,
+            uint32_t stride, native_handle_t* handle, bool keepOwnership);
+
+    // return status
+    status_t initCheck() const;
+
+    uint32_t getWidth() const           { return width; }
+    uint32_t getHeight() const          { return height; }
+    uint32_t getStride() const          { return stride; }
+    uint32_t getUsage() const           { return usage; }
+    PixelFormat getPixelFormat() const  { return format; }
+    Rect getBounds() const              { return Rect(width, height); }
+    
+    status_t reallocate(uint32_t w, uint32_t h, PixelFormat f, uint32_t usage);
+
+    status_t lock(uint32_t usage, void** vaddr);
+    status_t lock(uint32_t usage, const Rect& rect, void** vaddr);
+    status_t lock(GGLSurface* surface, uint32_t usage);
+    status_t unlock();
+    
+    android_native_buffer_t* getNativeBuffer() const;
+    
+    void setIndex(int index);
+    int getIndex() const;
+    void setVerticalStride(uint32_t vstride);
+    uint32_t getVerticalStride() const;
+
+protected:
+    GraphicBuffer(const Parcel& reply);
+    virtual ~GraphicBuffer();
+
+    enum {
+        ownNone   = 0,
+        ownHandle = 1,
+        ownData   = 2,
+    };
+
+    inline const GraphicBufferMapper& getBufferMapper() const { return mBufferMapper; }
+    inline GraphicBufferMapper& getBufferMapper() { return mBufferMapper; }
+    uint8_t mOwner;
+
+private:
+    friend class Surface;
+    friend class BpSurface;
+    friend class BnSurface;
+    friend class LightRefBase<GraphicBuffer>;
+    GraphicBuffer(const GraphicBuffer& rhs);
+    GraphicBuffer& operator = (const GraphicBuffer& rhs);
+    const GraphicBuffer& operator = (const GraphicBuffer& rhs) const;
+
+    status_t initSize(uint32_t w, uint32_t h, PixelFormat format, 
+            uint32_t usage);
+
+    static status_t writeToParcel(Parcel* reply, 
+            android_native_buffer_t const* buffer);
+
+    GraphicBufferMapper& mBufferMapper;
+    ssize_t mInitCheck;
+    uint32_t mVStride;
+    int mIndex;
+};
+
+}; // namespace android
+
+#endif // ANDROID_GRAPHIC_BUFFER_H
diff --git a/include/ui/GraphicBufferAllocator.h b/include/ui/GraphicBufferAllocator.h
new file mode 100644
index 0000000..be9c79b
--- /dev/null
+++ b/include/ui/GraphicBufferAllocator.h
@@ -0,0 +1,96 @@
+/* 
+**
+** Copyright 2009, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License"); 
+** you may not use this file except in compliance with the License. 
+** You may obtain a copy of the License at 
+**
+**     http://www.apache.org/licenses/LICENSE-2.0 
+**
+** Unless required by applicable law or agreed to in writing, software 
+** distributed under the License is distributed on an "AS IS" BASIS, 
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+** See the License for the specific language governing permissions and 
+** limitations under the License.
+*/
+
+#ifndef ANDROID_BUFFER_ALLOCATOR_H
+#define ANDROID_BUFFER_ALLOCATOR_H
+
+#include <stdint.h>
+
+#include <cutils/native_handle.h>
+
+#include <utils/Errors.h>
+#include <utils/KeyedVector.h>
+#include <utils/threads.h>
+#include <utils/Singleton.h>
+
+#include <ui/PixelFormat.h>
+
+#include <hardware/gralloc.h>
+
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+class String8;
+
+class GraphicBufferAllocator : public Singleton<GraphicBufferAllocator>
+{
+public:
+    enum {
+        USAGE_SW_READ_NEVER     = GRALLOC_USAGE_SW_READ_NEVER,
+        USAGE_SW_READ_RARELY    = GRALLOC_USAGE_SW_READ_RARELY,
+        USAGE_SW_READ_OFTEN     = GRALLOC_USAGE_SW_READ_OFTEN,
+        USAGE_SW_READ_MASK      = GRALLOC_USAGE_SW_READ_MASK,
+        
+        USAGE_SW_WRITE_NEVER    = GRALLOC_USAGE_SW_WRITE_NEVER,
+        USAGE_SW_WRITE_RARELY   = GRALLOC_USAGE_SW_WRITE_RARELY,
+        USAGE_SW_WRITE_OFTEN    = GRALLOC_USAGE_SW_WRITE_OFTEN,
+        USAGE_SW_WRITE_MASK     = GRALLOC_USAGE_SW_WRITE_MASK,
+        
+        USAGE_SOFTWARE_MASK     = USAGE_SW_READ_MASK|USAGE_SW_WRITE_MASK,
+        
+        USAGE_HW_TEXTURE        = GRALLOC_USAGE_HW_TEXTURE,
+        USAGE_HW_RENDER         = GRALLOC_USAGE_HW_RENDER,
+        USAGE_HW_2D             = GRALLOC_USAGE_HW_2D,
+        USAGE_HW_MASK           = GRALLOC_USAGE_HW_MASK
+    };
+
+    static inline GraphicBufferAllocator& get() { return getInstance(); }
+    
+
+    status_t alloc(uint32_t w, uint32_t h, PixelFormat format, int usage,
+            buffer_handle_t* handle, int32_t* stride);
+
+    status_t free(buffer_handle_t handle);
+
+    void dump(String8& res) const;
+
+private:
+    struct alloc_rec_t {
+        uint32_t w;
+        uint32_t h;
+        PixelFormat format;
+        uint32_t usage;
+        void* vaddr;
+        size_t size;
+    };
+    
+    static Mutex sLock;
+    static KeyedVector<buffer_handle_t, alloc_rec_t> sAllocList;
+    
+    friend class Singleton<GraphicBufferAllocator>;
+    GraphicBufferAllocator();
+    ~GraphicBufferAllocator();
+    
+    mutable Mutex mLock;
+    alloc_device_t  *mAllocDev;
+};
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_BUFFER_ALLOCATOR_H
diff --git a/include/ui/GraphicBufferMapper.h b/include/ui/GraphicBufferMapper.h
new file mode 100644
index 0000000..697a02a
--- /dev/null
+++ b/include/ui/GraphicBufferMapper.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_UI_BUFFER_MAPPER_H
+#define ANDROID_UI_BUFFER_MAPPER_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Singleton.h>
+
+#include <hardware/gralloc.h>
+
+
+struct gralloc_module_t;
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+class Rect;
+
+class GraphicBufferMapper : public Singleton<GraphicBufferMapper>
+{
+public:
+    static inline GraphicBufferMapper& get() { return getInstance(); }
+
+    status_t registerBuffer(buffer_handle_t handle);
+
+    status_t unregisterBuffer(buffer_handle_t handle);
+    
+    status_t lock(buffer_handle_t handle,
+            int usage, const Rect& bounds, void** vaddr);
+
+    status_t unlock(buffer_handle_t handle);
+    
+    // dumps information about the mapping of this handle
+    void dump(buffer_handle_t handle);
+
+private:
+    friend class Singleton<GraphicBufferMapper>;
+    GraphicBufferMapper();
+    gralloc_module_t const *mAllocMod;
+};
+
+// ---------------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_UI_BUFFER_MAPPER_H
+
diff --git a/include/ui/ICamera.h b/include/ui/ICamera.h
index 241fb63..5642691 100644
--- a/include/ui/ICamera.h
+++ b/include/ui/ICamera.h
@@ -18,10 +18,10 @@
 #define ANDROID_HARDWARE_ICAMERA_H
 
 #include <utils/RefBase.h>
-#include <utils/IInterface.h>
-#include <utils/Parcel.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
 #include <ui/ISurface.h>
-#include <utils/IMemory.h>
+#include <binder/IMemory.h>
 #include <utils/String8.h>
 #include <ui/Camera.h>
 
@@ -76,6 +76,9 @@
     // auto focus
     virtual status_t        autoFocus() = 0;
 
+    // cancel auto focus
+    virtual status_t        cancelAutoFocus() = 0;
+
     // take a picture
     virtual status_t        takePicture() = 0;
 
@@ -84,6 +87,9 @@
 
     // get preview/capture parameters - key/value pairs
     virtual String8         getParameters() const = 0;
+
+    // send command to camera driver
+    virtual status_t        sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/include/ui/ICameraClient.h b/include/ui/ICameraClient.h
index 1001c71..236d0f6 100644
--- a/include/ui/ICameraClient.h
+++ b/include/ui/ICameraClient.h
@@ -18,9 +18,9 @@
 #define ANDROID_HARDWARE_ICAMERA_APP_H
 
 #include <utils/RefBase.h>
-#include <utils/IInterface.h>
-#include <utils/Parcel.h>
-#include <utils/IMemory.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+#include <binder/IMemory.h>
 #include <utils/Timers.h>
 
 namespace android {
diff --git a/include/ui/ICameraService.h b/include/ui/ICameraService.h
index c652c51..061681a 100644
--- a/include/ui/ICameraService.h
+++ b/include/ui/ICameraService.h
@@ -18,8 +18,8 @@
 #define ANDROID_HARDWARE_ICAMERASERVICE_H
 
 #include <utils/RefBase.h>
-#include <utils/IInterface.h>
-#include <utils/Parcel.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
 
 #include <ui/ICameraClient.h>
 #include <ui/ICamera.h>
diff --git a/include/ui/IOverlay.h b/include/ui/IOverlay.h
index 699b1b0..af3add1 100644
--- a/include/ui/IOverlay.h
+++ b/include/ui/IOverlay.h
@@ -21,7 +21,7 @@
 #include <sys/types.h>
 
 #include <utils/Errors.h>
-#include <utils/IInterface.h>
+#include <binder/IInterface.h>
 #include <utils/RefBase.h>
 #include <ui/PixelFormat.h>
 
diff --git a/include/ui/ISurface.h b/include/ui/ISurface.h
index 87b320f..2ca0026 100644
--- a/include/ui/ISurface.h
+++ b/include/ui/ISurface.h
@@ -21,11 +21,12 @@
 #include <sys/types.h>
 
 #include <utils/Errors.h>
-#include <utils/IInterface.h>
+#include <binder/IInterface.h>
 #include <utils/RefBase.h>
 #include <ui/PixelFormat.h>
 
 #include <hardware/hardware.h>
+#include <hardware/gralloc.h>
 
 namespace android {
 
@@ -33,6 +34,7 @@
 
 class IMemoryHeap;
 class OverlayRef;
+class GraphicBuffer;
 
 class ISurface : public IInterface
 {
@@ -42,11 +44,13 @@
         UNREGISTER_BUFFERS,
         POST_BUFFER, // one-way transaction
         CREATE_OVERLAY,
+        REQUEST_BUFFER,
     };
 
 public: 
     DECLARE_META_INTERFACE(Surface);
 
+    virtual sp<GraphicBuffer> requestBuffer(int bufferIdx, int usage) = 0; 
     
     class BufferHeap {
     public:
@@ -78,9 +82,7 @@
     };
     
     virtual status_t registerBuffers(const BufferHeap& buffers) = 0;
-
     virtual void postBuffer(ssize_t offset) = 0; // one-way
-
     virtual void unregisterBuffers() = 0;
     
     virtual sp<OverlayRef> createOverlay(
diff --git a/include/ui/ISurfaceComposer.h b/include/ui/ISurfaceComposer.h
index 5c64b22..25d954c 100644
--- a/include/ui/ISurfaceComposer.h
+++ b/include/ui/ISurfaceComposer.h
@@ -22,7 +22,7 @@
 
 #include <utils/RefBase.h>
 #include <utils/Errors.h>
-#include <utils/IInterface.h>
+#include <binder/IInterface.h>
 
 #include <ui/PixelFormat.h>
 #include <ui/ISurfaceFlingerClient.h>
@@ -32,7 +32,6 @@
 // ----------------------------------------------------------------------------
 
 class DisplayInfo;
-class IGPUCallback;
 
 class ISurfaceComposer : public IInterface
 {
@@ -41,8 +40,6 @@
 
     enum { // (keep in sync with Surface.java)
         eHidden             = 0x00000004,
-        eGPU                = 0x00000008,
-        eHardware           = 0x00000010,
         eDestroyBackbuffer  = 0x00000020,
         eSecure             = 0x00000080,
         eNonPremultiplied   = 0x00000100,
@@ -63,7 +60,6 @@
         eTransparentRegionChanged   = 0x00000020,
         eVisibilityChanged          = 0x00000040,
         eFreezeTintChanged          = 0x00000080,
-        eDestroyed                  = 0x00000100
     };
 
     enum {
@@ -94,7 +90,7 @@
     virtual sp<ISurfaceFlingerClient> createConnection() = 0;
 
     /* retrieve the control block */
-    virtual sp<IMemory> getCblk() const = 0;
+    virtual sp<IMemoryHeap> getCblk() const = 0;
 
     /* open/close transactions. recquires ACCESS_SURFACE_FLINGER permission */
     virtual void openGlobalTransaction() = 0;
@@ -112,37 +108,12 @@
      */
     virtual void bootFinished() = 0;
 
-    /* get access to the GPU. Access is relinquished when releasing regs */
-    struct gpu_info_t {
-        struct gpu_region_t {
-            sp<IMemory> region;
-            size_t reserved;
-        };
-        sp<IMemory>             regs;
-        size_t                  count;
-        gpu_region_t            regions[2];
-    };
-    virtual status_t requestGPU(
-            const sp<IGPUCallback>& callback,
-            gpu_info_t* gpu) = 0;
-
-    /* take the gpu back from any apps using it. They'll get a
-     * EGL_CONTEXT_LOST error */
-    virtual status_t revokeGPU() = 0;
-
     /* Signal surfaceflinger that there might be some work to do
      * This is an ASYNCHRONOUS call.
      */
     virtual void signal() const = 0;
 };
 
-class IGPUCallback : public IInterface
-{
-public:
-    DECLARE_META_INTERFACE(GPUCallback);
-    virtual void gpuLost() = 0; //one-way
-};
-
 // ----------------------------------------------------------------------------
 
 class BnSurfaceComposer : public BnInterface<ISurfaceComposer>
@@ -159,8 +130,6 @@
         SET_ORIENTATION,
         FREEZE_DISPLAY,
         UNFREEZE_DISPLAY,
-        REQUEST_GPU,
-        REVOKE_GPU,
         SIGNAL
     };
 
@@ -170,15 +139,6 @@
                                     uint32_t flags = 0);
 };
 
-class BnGPUCallback : public BnInterface<IGPUCallback>
-{
-public:
-    virtual status_t    onTransact( uint32_t code,
-                                    const Parcel& data,
-                                    Parcel* reply,
-                                    uint32_t flags = 0);
-};
-
 // ----------------------------------------------------------------------------
 
 }; // namespace android
diff --git a/include/ui/ISurfaceFlingerClient.h b/include/ui/ISurfaceFlingerClient.h
index 5b9361d..5d231e6 100644
--- a/include/ui/ISurfaceFlingerClient.h
+++ b/include/ui/ISurfaceFlingerClient.h
@@ -21,7 +21,7 @@
 #include <sys/types.h>
 
 #include <utils/Errors.h>
-#include <utils/IInterface.h>
+#include <binder/IInterface.h>
 #include <utils/RefBase.h>
 
 #include <ui/ISurface.h>
@@ -52,12 +52,14 @@
     struct surface_data_t {
         int32_t             token;
         int32_t             identity;
-        sp<IMemoryHeap>     heap[2];
+        uint32_t            width;
+        uint32_t            height;
+        uint32_t            format;
         status_t readFromParcel(const Parcel& parcel);
         status_t writeToParcel(Parcel* parcel) const;
     };
     
-    virtual void getControlBlocks(sp<IMemory>* ctl) const = 0;
+    virtual sp<IMemoryHeap> getControlBlock() const = 0;
 
     virtual sp<ISurface> createSurface( surface_data_t* data,
                                         int pid, 
diff --git a/include/ui/Overlay.h b/include/ui/Overlay.h
index 66514b4..a9ae1c4 100644
--- a/include/ui/Overlay.h
+++ b/include/ui/Overlay.h
@@ -21,7 +21,7 @@
 #include <sys/types.h>
 
 #include <utils/Errors.h>
-#include <utils/IInterface.h>
+#include <binder/IInterface.h>
 #include <utils/RefBase.h>
 #include <utils/threads.h>
 
@@ -82,6 +82,16 @@
     /* release the overlay buffer and post it */
     status_t queueBuffer(overlay_buffer_t buffer);
 
+    /* change the width and height of the overlay */
+    status_t resizeInput(uint32_t width, uint32_t height);
+
+    status_t setCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h) ;
+
+    status_t getCrop(uint32_t* x, uint32_t* y, uint32_t* w, uint32_t* h) ;
+
+    /* set the buffer attributes */
+    status_t setParameter(int param, int value);
+
     /* returns the address of a given buffer if supported, NULL otherwise. */
     void* getBufferAddress(overlay_buffer_t buffer);
 
diff --git a/include/ui/PixelFormat.h b/include/ui/PixelFormat.h
index 14af823..6d87321b 100644
--- a/include/ui/PixelFormat.h
+++ b/include/ui/PixelFormat.h
@@ -84,6 +84,13 @@
 
 struct PixelFormatInfo
 {
+    enum {
+        INDEX_ALPHA   = 0,
+        INDEX_RED     = 1,
+        INDEX_GREEN   = 2,
+        INDEX_BLUE    = 3
+    };
+    
     enum { // components
         ALPHA               = 1,
         RGB                 = 2,
@@ -95,20 +102,33 @@
         Y_CB_CR_I           = 8,
     };
 
+    struct szinfo {
+        uint8_t h;
+        uint8_t l;
+    };
+    
     inline PixelFormatInfo() : version(sizeof(PixelFormatInfo)) { }
     size_t getScanlineSize(unsigned int width) const;
+    size_t getSize(size_t ci) const { 
+        return (ci <= 3) ? (cinfo[ci].h - cinfo[ci].l) : 0;
+    }
     size_t      version;
     PixelFormat format;
     size_t      bytesPerPixel;
     size_t      bitsPerPixel;
-    uint8_t     h_alpha;
-    uint8_t     l_alpha;
-    uint8_t     h_red;
-    uint8_t     l_red;
-    uint8_t     h_green;
-    uint8_t     l_green;
-    uint8_t     h_blue;
-    uint8_t     l_blue;
+    union {
+        szinfo      cinfo[4];
+        struct {
+            uint8_t     h_alpha;
+            uint8_t     l_alpha;    
+            uint8_t     h_red;
+            uint8_t     l_red;
+            uint8_t     h_green;
+            uint8_t     l_green;
+            uint8_t     h_blue;
+            uint8_t     l_blue;
+        };
+    };
     uint8_t     components;
     uint8_t     reserved0[3];
     uint32_t    reserved1;
diff --git a/include/ui/Rect.h b/include/ui/Rect.h
index da72944..a213c09 100644
--- a/include/ui/Rect.h
+++ b/include/ui/Rect.h
@@ -30,6 +30,8 @@
     int right;
     int bottom;
 
+    typedef int value_type;
+
     // we don't provide copy-ctor and operator= on purpose
     // because we want the compiler generated versions
 
@@ -46,7 +48,11 @@
     }
 
     void makeInvalid();
-    
+
+    inline void clear() {
+        left = top = right = bottom = 0;
+    }
+
     // a valid rectangle has a non negative width and height
     inline bool isValid() const {
         return (width()>=0) && (height()>=0);
diff --git a/include/ui/Region.h b/include/ui/Region.h
index 7689673..2bcad5b 100644
--- a/include/ui/Region.h
+++ b/include/ui/Region.h
@@ -21,14 +21,12 @@
 #include <sys/types.h>
 
 #include <utils/Vector.h>
-#include <utils/Parcel.h>
+#include <binder/Parcel.h>
 
 #include <ui/Rect.h>
 
 #include <hardware/copybit.h>
 
-#include <core/SkRegion.h>
-
 namespace android {
 // ---------------------------------------------------------------------------
 
@@ -40,7 +38,6 @@
 public:
                         Region();
                         Region(const Region& rhs);
-    explicit            Region(const SkRegion& rhs);
     explicit            Region(const Rect& rhs);
     explicit            Region(const Parcel& parcel);
     explicit            Region(const void* buffer);
@@ -48,65 +45,78 @@
                         
         Region& operator = (const Region& rhs);
 
-    inline  bool        isEmpty() const     { return mRegion.isEmpty(); }
-    inline  bool        isRect() const      { return mRegion.isRect(); }
+    inline  bool        isEmpty() const     { return mBounds.isEmpty();  }
+    inline  bool        isRect() const      { return mStorage.isEmpty(); }
 
-            Rect        bounds() const;
+    inline  Rect        getBounds() const   { return mBounds; }
+    inline  Rect        bounds() const      { return getBounds(); }
 
-            const SkRegion& toSkRegion() const;
-
+            // the region becomes its bounds
+            Region&     makeBoundsSelf();
+    
             void        clear();
             void        set(const Rect& r);
+            void        set(uint32_t w, uint32_t h);
         
             Region&     orSelf(const Rect& rhs);
             Region&     andSelf(const Rect& rhs);
+            Region&     subtractSelf(const Rect& rhs);
 
             // boolean operators, applied on this
             Region&     orSelf(const Region& rhs);
             Region&     andSelf(const Region& rhs);
             Region&     subtractSelf(const Region& rhs);
 
+            // boolean operators
+    const   Region      merge(const Rect& rhs) const;
+    const   Region      intersect(const Rect& rhs) const;
+    const   Region      subtract(const Rect& rhs) const;
+
+            // boolean operators
+    const   Region      merge(const Region& rhs) const;
+    const   Region      intersect(const Region& rhs) const;
+    const   Region      subtract(const Region& rhs) const;
+
             // these translate rhs first
             Region&     translateSelf(int dx, int dy);
             Region&     orSelf(const Region& rhs, int dx, int dy);
             Region&     andSelf(const Region& rhs, int dx, int dy);
             Region&     subtractSelf(const Region& rhs, int dx, int dy);
 
-            // boolean operators
-            Region      merge(const Region& rhs) const;
-            Region      intersect(const Region& rhs) const;
-            Region      subtract(const Region& rhs) const;
-
             // these translate rhs first
-            Region      translate(int dx, int dy) const;
-            Region      merge(const Region& rhs, int dx, int dy) const;
-            Region      intersect(const Region& rhs, int dx, int dy) const;
-            Region      subtract(const Region& rhs, int dx, int dy) const;
+    const   Region      translate(int dx, int dy) const;
+    const   Region      merge(const Region& rhs, int dx, int dy) const;
+    const   Region      intersect(const Region& rhs, int dx, int dy) const;
+    const   Region      subtract(const Region& rhs, int dx, int dy) const;
 
     // convenience operators overloads
-    inline  Region      operator | (const Region& rhs) const;
-    inline  Region      operator & (const Region& rhs) const;
-    inline  Region      operator - (const Region& rhs) const;
-    inline  Region      operator + (const Point& pt) const;
+    inline  const Region      operator | (const Region& rhs) const;
+    inline  const Region      operator & (const Region& rhs) const;
+    inline  const Region      operator - (const Region& rhs) const;
+    inline  const Region      operator + (const Point& pt) const;
 
     inline  Region&     operator |= (const Region& rhs);
     inline  Region&     operator &= (const Region& rhs);
     inline  Region&     operator -= (const Region& rhs);
     inline  Region&     operator += (const Point& pt);
 
-    class iterator {
-        SkRegion::Iterator  mIt;
-    public:
-        iterator(const Region& r);
-        inline operator bool () const { return !done(); }
-        int iterate(Rect* rect);
-    private:
-        inline bool done() const {
-            return const_cast<SkRegion::Iterator&>(mIt).done();
-        }
-    };
+    
+    /* various ways to access the rectangle list */
+    
+    typedef Rect const* const_iterator;
+    
+            const_iterator begin() const;
+            const_iterator end() const;
 
-            size_t      rects(Vector<Rect>& rectList) const;
+    /* no user serviceable parts here... */
+            
+            size_t      getRects(Vector<Rect>& rectList) const;
+            Rect const* getArray(size_t* count) const;
+
+            
+            // add a rectangle to the internal list. This rectangle must
+            // be sorted in Y and X and must not make the region invalid.
+            void        addRectUnchecked(int l, int t, int r, int b);
 
             // flatten/unflatten a region to/from a Parcel
             status_t    write(Parcel& parcel) const;
@@ -123,20 +133,46 @@
     void        dump(const char* what, uint32_t flags=0) const;
 
 private:
-    SkRegion    mRegion;
+    class rasterizer;
+    friend class rasterizer;
+    
+    Region& operationSelf(const Rect& r, int op);
+    Region& operationSelf(const Region& r, int op);
+    Region& operationSelf(const Region& r, int dx, int dy, int op);
+    const Region operation(const Rect& rhs, int op) const;
+    const Region operation(const Region& rhs, int op) const;
+    const Region operation(const Region& rhs, int dx, int dy, int op) const;
+
+    static void boolean_operation(int op, Region& dst,
+            const Region& lhs, const Region& rhs, int dx, int dy);
+    static void boolean_operation(int op, Region& dst,
+            const Region& lhs, const Rect& rhs, int dx, int dy);
+
+    static void boolean_operation(int op, Region& dst,
+            const Region& lhs, const Region& rhs);
+    static void boolean_operation(int op, Region& dst,
+            const Region& lhs, const Rect& rhs);
+
+    static void translate(Region& reg, int dx, int dy);
+    static void translate(Region& dst, const Region& reg, int dx, int dy);
+
+    static bool validate(const Region& reg, const char* name);
+    
+    Rect            mBounds;
+    Vector<Rect>    mStorage;
 };
 
 
-Region Region::operator | (const Region& rhs) const {
+const Region Region::operator | (const Region& rhs) const {
     return merge(rhs);
 }
-Region Region::operator & (const Region& rhs) const {
+const Region Region::operator & (const Region& rhs) const {
     return intersect(rhs);
 }
-Region Region::operator - (const Region& rhs) const {
+const Region Region::operator - (const Region& rhs) const {
     return subtract(rhs);
 }
-Region Region::operator + (const Point& pt) const {
+const Region Region::operator + (const Point& pt) const {
     return translate(pt.x, pt.y);
 }
 
@@ -157,16 +193,23 @@
 // ---------------------------------------------------------------------------
 
 struct region_iterator : public copybit_region_t {
-    region_iterator(const Region& region) : i(region) {
+    region_iterator(const Region& region)
+        : b(region.begin()), e(region.end()) {
         this->next = iterate;
     }
 private:
     static int iterate(copybit_region_t const * self, copybit_rect_t* rect) {
-        return static_cast<const region_iterator*>(self)
-        ->i.iterate(reinterpret_cast<Rect*>(rect));
+        region_iterator const* me = static_cast<region_iterator const*>(self);
+        if (me->b != me->e) {
+            *reinterpret_cast<Rect*>(rect) = *me->b++;
+            return 1;
+        }
+        return 0;
     }
-    mutable Region::iterator i;
+    mutable Region::const_iterator b;
+    Region::const_iterator const e;
 };
+
 // ---------------------------------------------------------------------------
 }; // namespace android
 
diff --git a/include/ui/Surface.h b/include/ui/Surface.h
index 33953a9..70303cd 100644
--- a/include/ui/Surface.h
+++ b/include/ui/Surface.h
@@ -28,48 +28,41 @@
 #include <ui/Region.h>
 #include <ui/ISurfaceFlingerClient.h>
 
+#include <ui/egl/android_natives.h>
+
 namespace android {
 
 // ---------------------------------------------------------------------------
 
+class GraphicBufferMapper;
+class IOMX;
 class Rect;
+class Surface;
 class SurfaceComposerClient;
+class SharedClient;
+class SharedBufferClient;
 
-class Surface : public RefBase
+// ---------------------------------------------------------------------------
+
+class SurfaceControl : public RefBase
 {
-
 public:
-    struct SurfaceInfo {
-        uint32_t    w;
-        uint32_t    h;
-        uint32_t    bpr;
-        PixelFormat format;
-        void*       bits;
-        void*       base;
-        uint32_t    reserved[2];
-    };
-
-    bool        isValid() const { return this && mToken>=0 && mClient!=0; }
+    static bool isValid(const sp<SurfaceControl>& surface) {
+        return (surface != 0) && surface->isValid();
+    }
+    bool isValid() {
+        return mToken>=0 && mClient!=0;
+    }
+    static bool isSameSurface(
+            const sp<SurfaceControl>& lhs, const sp<SurfaceControl>& rhs);
+        
     SurfaceID   ID() const      { return mToken; }
-
-    status_t    lock(SurfaceInfo* info, bool blocking = true);
-    status_t    lock(SurfaceInfo* info, Region* dirty, bool blocking = true);
-    status_t    unlockAndPost();
-    status_t    unlock();
-
-    void*       heapBase(int i) const;
     uint32_t    getFlags() const { return mFlags; }
+    uint32_t    getIdentity() const { return mIdentity; }
 
-    // setSwapRectangle() is mainly used by EGL
-    void        setSwapRectangle(const Rect& r);
-    const Rect& swapRectangle() const;
-    status_t    nextBuffer(SurfaceInfo* info);
-
-    sp<Surface>         dup() const;
-    static sp<Surface>  readFromParcel(Parcel* parcel);
-    static status_t     writeToParcel(const sp<Surface>& surface, Parcel* parcel);
-    static bool         isSameSurface(const sp<Surface>& lhs, const sp<Surface>& rhs);
-
+    // release surface data from java
+    void        clear();
+    
     status_t    setLayer(int32_t layer);
     status_t    setPosition(int32_t x, int32_t y);
     status_t    setSize(uint32_t w, uint32_t h);
@@ -83,8 +76,17 @@
     status_t    setMatrix(float dsdx, float dtdx, float dsdy, float dtdy);
     status_t    setFreezeTint(uint32_t tint);
 
-    uint32_t    getIdentity() const { return mIdentity; }
+    static status_t writeSurfaceToParcel(
+            const sp<SurfaceControl>& control, Parcel* parcel);
+
+    sp<Surface> getSurface() const;
+
 private:
+    // can't be copied
+    SurfaceControl& operator = (SurfaceControl& rhs);
+    SurfaceControl(const SurfaceControl& rhs);
+
+    
     friend class SurfaceComposerClient;
 
     // camera and camcorder need access to the ISurface binder interface for preview
@@ -92,43 +94,158 @@
     friend class MediaRecorder;
     // mediaplayer needs access to ISurface for display
     friend class MediaPlayer;
+    // for testing
     friend class Test;
     const sp<ISurface>& getISurface() const { return mSurface; }
+    
 
+    friend class Surface;
+
+    SurfaceControl(
+            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);
+
+    ~SurfaceControl();
+
+    status_t validate(SharedClient const* cblk) const;
+    void destroy();
+    
+    sp<SurfaceComposerClient>   mClient;
+    sp<ISurface>                mSurface;
+    SurfaceID                   mToken;
+    uint32_t                    mIdentity;
+    uint32_t                    mWidth;
+    uint32_t                    mHeight;
+    PixelFormat                 mFormat;
+    uint32_t                    mFlags;
+    mutable Mutex               mLock;
+    
+    mutable sp<Surface>         mSurfaceData;
+};
+    
+// ---------------------------------------------------------------------------
+
+class Surface 
+    : public EGLNativeBase<android_native_window_t, Surface, RefBase>
+{
+public:
+    struct SurfaceInfo {
+        uint32_t    w;
+        uint32_t    h;
+        uint32_t    s;
+        uint32_t    usage;
+        PixelFormat format;
+        void*       bits;
+        uint32_t    reserved[2];
+    };
+
+    Surface(const Parcel& data);
+
+    static bool isValid(const sp<Surface>& surface) {
+        return (surface != 0) && surface->isValid();
+    }
+
+    static bool isSameSurface(
+            const sp<Surface>& lhs, const sp<Surface>& rhs);
+
+    bool        isValid();
+    SurfaceID   ID() const          { return mToken; }
+    uint32_t    getFlags() const    { return mFlags; }
+    uint32_t    getIdentity() const { return mIdentity; }
+
+    // the lock/unlock APIs must be used from the same thread
+    status_t    lock(SurfaceInfo* info, bool blocking = true);
+    status_t    lock(SurfaceInfo* info, Region* dirty, bool blocking = true);
+    status_t    unlockAndPost();
+
+    // setSwapRectangle() is intended to be used by GL ES clients
+    void        setSwapRectangle(const Rect& r);
+
+private:
     // can't be copied
     Surface& operator = (Surface& rhs);
     Surface(const Surface& rhs);
 
-    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 = true);
+    Surface(const sp<SurfaceControl>& control);
+    void init();
+     ~Surface();
+  
+    friend class SurfaceComposerClient;
+    friend class SurfaceControl;
 
-    Surface(Surface const* rhs);
+    
+    // camera and camcorder need access to the ISurface binder interface for preview
+    friend class Camera;
+    friend class MediaRecorder;
+    // mediaplayer needs access to ISurface for display
+    friend class MediaPlayer;
+    friend class IOMX;
+    // this is just to be able to write some unit tests
+    friend class Test;
 
-    ~Surface();
+    sp<SurfaceComposerClient> getClient() const;
+    sp<ISurface> getISurface() const;
 
-    Region dirtyRegion() const;
-    void setDirtyRegion(const Region& region) const;
+    status_t getBufferLocked(int index, int usage);
+   
+           status_t validate(SharedClient const* cblk) const;
 
-    // this locks protects calls to lockSurface() / unlockSurface()
-    // and is called by SurfaceComposerClient.
-    Mutex& getLock() const { return mSurfaceLock; }
+    inline const GraphicBufferMapper& getBufferMapper() const { return mBufferMapper; }
+    inline GraphicBufferMapper& getBufferMapper() { return mBufferMapper; }
+    
+    static int setSwapInterval(android_native_window_t* window, int interval);
+    static int dequeueBuffer(android_native_window_t* window, android_native_buffer_t** buffer);
+    static int lockBuffer(android_native_window_t* window, android_native_buffer_t* buffer);
+    static int queueBuffer(android_native_window_t* window, android_native_buffer_t* buffer);
+    static int query(android_native_window_t* window, int what, int* value);
+    static int perform(android_native_window_t* window, int operation, ...);
 
+    int dequeueBuffer(android_native_buffer_t** buffer);
+    int lockBuffer(android_native_buffer_t* buffer);
+    int queueBuffer(android_native_buffer_t* buffer);
+    int query(int what, int* value);
+    int perform(int operation, va_list args);
+
+    status_t dequeueBuffer(sp<GraphicBuffer>* buffer);
+
+    
+    void setUsage(uint32_t reqUsage);
+    uint32_t getUsage() const;
+    
+    // constants
     sp<SurfaceComposerClient>   mClient;
     sp<ISurface>                mSurface;
-    sp<IMemoryHeap>             mHeap[2];
     SurfaceID                   mToken;
     uint32_t                    mIdentity;
     PixelFormat                 mFormat;
     uint32_t                    mFlags;
-    const bool                  mOwner;
-    mutable void*               mSurfaceHeapBase[2];
+    GraphicBufferMapper&        mBufferMapper;
+    SharedBufferClient*         mSharedBufferClient;
+
+    // protected by mSurfaceLock
+    Rect                        mSwapRectangle;
+    uint32_t                    mUsage;
+    
+    // protected by mSurfaceLock. These are also used from lock/unlock
+    // but in that case, they must be called form the same thread.
+    sp<GraphicBuffer>           mBuffers[2];
     mutable Region              mDirtyRegion;
-    mutable Rect                mSwapRectangle;
-    mutable uint8_t             mBackbufferIndex;
+
+    // must be used from the lock/unlock thread
+    sp<GraphicBuffer>           mLockedBuffer;
+    sp<GraphicBuffer>           mPostedBuffer;
+    mutable Region              mOldDirtyRegion;
+    bool                        mNeedFullUpdate;
+
+    // query() must be called from dequeueBuffer() thread
+    uint32_t                    mWidth;
+    uint32_t                    mHeight;
+
+    // Inherently thread-safe
     mutable Mutex               mSurfaceLock;
+    mutable Mutex               mApiLock;
 };
 
 }; // namespace android
diff --git a/include/ui/SurfaceComposerClient.h b/include/ui/SurfaceComposerClient.h
index 76a3b55..777b878 100644
--- a/include/ui/SurfaceComposerClient.h
+++ b/include/ui/SurfaceComposerClient.h
@@ -20,8 +20,9 @@
 #include <stdint.h>
 #include <sys/types.h>
 
+#include <binder/IBinder.h>
+
 #include <utils/SortedVector.h>
-#include <utils/KeyedVector.h>
 #include <utils/RefBase.h>
 #include <utils/threads.h>
 
@@ -36,8 +37,7 @@
 
 class Region;
 class SurfaceFlingerSynchro;
-struct per_client_cblk_t;
-struct layer_cblk_t;
+class SharedClient;
 
 class SurfaceComposerClient : virtual public RefBase
 {
@@ -62,13 +62,13 @@
     // surface creation / destruction
 
     //! Create a surface
-    sp<Surface>   createSurface(
-            int pid,            //!< pid of the process the surfacec is for
-            DisplayID display,  //!< Display to create this surface on
-            uint32_t w,         //!< width in pixel
-            uint32_t h,         //!< height in pixel
-            PixelFormat format, //!< pixel-format desired
-            uint32_t flags = 0  //!< usage flags
+    sp<SurfaceControl> createSurface(
+            int pid,            // pid of the process the surface is for
+            DisplayID display,  // Display to create this surface on
+            uint32_t w,         // width in pixel
+            uint32_t h,         // height in pixel
+            PixelFormat format, // pixel-format desired
+            uint32_t flags = 0  // usage flags
     );
 
     // ------------------------------------------------------------------------
@@ -108,54 +108,40 @@
     static ssize_t getDisplayHeight(DisplayID dpy);
     static ssize_t getDisplayOrientation(DisplayID dpy);
 
+    status_t linkToComposerDeath(const sp<IBinder::DeathRecipient>& recipient,
+            void* cookie = NULL, uint32_t flags = 0);
 
 private:
     friend class Surface;
+    friend class SurfaceControl;
     
     SurfaceComposerClient(const sp<ISurfaceComposer>& sm, 
             const sp<IBinder>& conn);
 
-    status_t    hide(Surface* surface);
-    status_t    show(Surface* surface, int32_t layer = -1);
-    status_t    freeze(Surface* surface);
-    status_t    unfreeze(Surface* surface);
-    status_t    setFlags(Surface* surface, uint32_t flags, uint32_t mask);
-    status_t    setTransparentRegionHint(Surface* surface, const Region& transparent);
-    status_t    setLayer(Surface* surface, int32_t layer);
-    status_t    setAlpha(Surface* surface, float alpha=1.0f);
-    status_t    setFreezeTint(Surface* surface, uint32_t tint);
-    status_t    setMatrix(Surface* surface, float dsdx, float dtdx, float dsdy, float dtdy);
-    status_t    setPosition(Surface* surface, int32_t x, int32_t y);
-    status_t    setSize(Surface* surface, uint32_t w, uint32_t h);
+    status_t    hide(SurfaceID id);
+    status_t    show(SurfaceID id, int32_t layer = -1);
+    status_t    freeze(SurfaceID id);
+    status_t    unfreeze(SurfaceID id);
+    status_t    setFlags(SurfaceID id, uint32_t flags, uint32_t mask);
+    status_t    setTransparentRegionHint(SurfaceID id, const Region& transparent);
+    status_t    setLayer(SurfaceID id, int32_t layer);
+    status_t    setAlpha(SurfaceID id, float alpha=1.0f);
+    status_t    setFreezeTint(SurfaceID id, uint32_t tint);
+    status_t    setMatrix(SurfaceID id, float dsdx, float dtdx, float dsdy, float dtdy);
+    status_t    setPosition(SurfaceID id, int32_t x, int32_t y);
+    status_t    setSize(SurfaceID id, uint32_t w, uint32_t h);
     
-    //! Unlock the surface, and specify the dirty region if any
-    status_t    unlockAndPostSurface(Surface* surface);
-    status_t    unlockSurface(Surface* surface);
-
-    status_t    lockSurface(Surface* surface,
-                            Surface::SurfaceInfo* info,
-                            Region* dirty,
-                            bool blocking = true);
-
-    status_t    nextBuffer(Surface* surface,
-                            Surface::SurfaceInfo* info);
+    void        signalServer();
 
     status_t    destroySurface(SurfaceID sid);
 
     void        _init(const sp<ISurfaceComposer>& sm,
                     const sp<ISurfaceFlingerClient>& conn);
-    void        _signal_server();
-    static void _send_dirty_region(layer_cblk_t* lcblk, const Region& dirty);
 
-    inline layer_state_t*   _get_state_l(const sp<Surface>& surface);
-    layer_state_t*          _lockLayerState(const sp<Surface>& surface);
+    inline layer_state_t*   _get_state_l(SurfaceID id);
+    layer_state_t*          _lockLayerState(SurfaceID id);
     inline void             _unlockLayerState();
 
-    status_t validateSurface(
-            per_client_cblk_t const* cblk, Surface const * surface);
-
-    void pinHeap(const sp<IMemoryHeap>& heap);
-
     mutable     Mutex                               mLock;
                 layer_state_t*                      mPrebuiltLayerState;
                 SortedVector<layer_state_t>         mStates;
@@ -164,13 +150,10 @@
                 // these don't need to be protected because they never change
                 // after assignment
                 status_t                    mStatus;
-                per_client_cblk_t*          mControl;
-                sp<IMemory>                 mControlMemory;
+                SharedClient*               mControl;
+                sp<IMemoryHeap>             mControlMemory;
                 sp<ISurfaceFlingerClient>   mClient;
-                sp<IMemoryHeap>             mSurfaceHeap;
-                uint8_t*                    mSurfaceHeapBase;
-                void*                       mGL;
-                SurfaceFlingerSynchro*      mSignalServer;
+                sp<ISurfaceComposer>        mSignalServer;
 };
 
 }; // namespace android
diff --git a/include/ui/android_native_buffer.h b/include/ui/android_native_buffer.h
new file mode 100644
index 0000000..9c92af8
--- /dev/null
+++ b/include/ui/android_native_buffer.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_ANDROID_NATIVES_PRIV_H
+#define ANDROID_ANDROID_NATIVES_PRIV_H
+
+#include <ui/egl/android_natives.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*****************************************************************************/
+
+typedef struct android_native_buffer_t
+{
+#ifdef __cplusplus
+    android_native_buffer_t() { 
+        common.magic = ANDROID_NATIVE_BUFFER_MAGIC;
+        common.version = sizeof(android_native_buffer_t);
+        memset(common.reserved, 0, sizeof(common.reserved));
+    }
+#endif
+
+    struct android_native_base_t common;
+
+    int width;
+    int height;
+    int stride;
+    int format;
+    int usage;
+    
+    void* reserved[2];
+
+    buffer_handle_t handle;
+
+    void* reserved_proc[8];
+} android_native_buffer_t;
+
+
+/*****************************************************************************/
+
+#ifdef __cplusplus
+}
+#endif
+
+/*****************************************************************************/
+
+#endif /* ANDROID_ANDROID_NATIVES_PRIV_H */
diff --git a/include/ui/egl/android_natives.h b/include/ui/egl/android_natives.h
new file mode 100644
index 0000000..3740db5
--- /dev/null
+++ b/include/ui/egl/android_natives.h
@@ -0,0 +1,263 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_ANDROID_NATIVES_H
+#define ANDROID_ANDROID_NATIVES_H
+
+#include <sys/types.h>
+#include <string.h>
+
+#include <hardware/gralloc.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*****************************************************************************/
+
+#define ANDROID_NATIVE_MAKE_CONSTANT(a,b,c,d) \
+    (((unsigned)(a)<<24)|((unsigned)(b)<<16)|((unsigned)(c)<<8)|(unsigned)(d))
+
+#define ANDROID_NATIVE_WINDOW_MAGIC \
+    ANDROID_NATIVE_MAKE_CONSTANT('_','w','n','d')
+
+#define ANDROID_NATIVE_BUFFER_MAGIC \
+    ANDROID_NATIVE_MAKE_CONSTANT('_','b','f','r')
+
+// ---------------------------------------------------------------------------
+
+struct android_native_buffer_t;
+
+// ---------------------------------------------------------------------------
+
+typedef struct android_native_base_t
+{
+    /* a magic value defined by the actual EGL native type */
+    int magic;
+    
+    /* the sizeof() of the actual EGL native type */
+    int version;
+
+    void* reserved[4];
+
+    /* reference-counting interface */
+    void (*incRef)(struct android_native_base_t* base);
+    void (*decRef)(struct android_native_base_t* base);
+} android_native_base_t;
+
+// ---------------------------------------------------------------------------
+
+/* attributes queriable with query() */
+enum {
+    NATIVE_WINDOW_WIDTH     = 0,
+    NATIVE_WINDOW_HEIGHT    = 1,
+    NATIVE_WINDOW_FORMAT    = 2,
+};
+
+/* valid operations for the (*perform)() hook */
+enum {
+    NATIVE_WINDOW_SET_USAGE = 0
+};
+
+typedef struct android_native_window_t 
+{
+#ifdef __cplusplus
+    android_native_window_t()
+        : flags(0), minSwapInterval(0), maxSwapInterval(0), xdpi(0), ydpi(0)
+    {
+        common.magic = ANDROID_NATIVE_WINDOW_MAGIC;
+        common.version = sizeof(android_native_window_t);
+        memset(common.reserved, 0, sizeof(common.reserved));
+    }
+#endif
+    
+    struct android_native_base_t common;
+
+    /* flags describing some attributes of this surface or its updater */
+    const uint32_t flags;
+    
+    /* min swap interval supported by this updated */
+    const int   minSwapInterval;
+
+    /* max swap interval supported by this updated */
+    const int   maxSwapInterval;
+
+    /* horizontal and vertical resolution in DPI */
+    const float xdpi;
+    const float ydpi;
+
+    /* Some storage reserved for the OEM's driver. */
+    intptr_t    oem[4];
+        
+
+    /*
+     * Set the swap interval for this surface.
+     * 
+     * Returns 0 on success or -errno on error.
+     */
+    int     (*setSwapInterval)(struct android_native_window_t* window,
+                int interval);
+    
+    /*
+     * hook called by EGL to acquire a buffer. After this call, the buffer
+     * is not locked, so its content cannot be modified.
+     * this call may block if no buffers are available.
+     * 
+     * Returns 0 on success or -errno on error.
+     */
+    int     (*dequeueBuffer)(struct android_native_window_t* window, 
+                struct android_native_buffer_t** buffer);
+
+    /*
+     * hook called by EGL to lock a buffer. This MUST be called before modifying
+     * the content of a buffer. The buffer must have been acquired with 
+     * dequeueBuffer first.
+     * 
+     * Returns 0 on success or -errno on error.
+     */
+    int     (*lockBuffer)(struct android_native_window_t* window,
+                struct android_native_buffer_t* buffer);
+   /*
+    * hook called by EGL when modifications to the render buffer are done. 
+    * This unlocks and post the buffer.
+    * 
+    * Buffers MUST be queued in the same order than they were dequeued.
+    * 
+    * Returns 0 on success or -errno on error.
+    */
+    int     (*queueBuffer)(struct android_native_window_t* window,
+                struct android_native_buffer_t* buffer);
+
+    /*
+     * hook used to retrieve information about the native window.
+     * 
+     * Returns 0 on success or -errno on error.
+     */
+    int     (*query)(struct android_native_window_t* window,
+                int what, int* value);
+    
+    /*
+     * hook used to perform various operations on the surface.
+     * (*perform)() is a generic mechanism to add functionality to
+     * android_native_window_t while keeping backward binary compatibility.
+     * 
+     * This hook should not be called directly, instead use the helper functions
+     * defined below.
+     * 
+     * The valid operations are:
+     *     NATIVE_WINDOW_SET_USAGE
+     *  
+     */
+    
+    int     (*perform)(struct android_native_window_t* window,
+                int operation, ... );
+    
+    void* reserved_proc[3];
+} android_native_window_t;
+
+
+/*
+ *  native_window_set_usage() sets the intended usage flags for the next
+ *  buffers acquired with (*lockBuffer)() and on.
+ *  By default (if this function is never called), a usage of
+ *      GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE
+ *  is assumed.
+ *  Calling this function will usually cause following buffers to be
+ *  reallocated.
+ */
+
+static inline int native_window_set_usage(
+        android_native_window_t* window, int usage)
+{
+    return window->perform(window, NATIVE_WINDOW_SET_USAGE, usage);
+}
+
+
+// ---------------------------------------------------------------------------
+
+/* FIXME: this is legacy for pixmaps */
+typedef struct egl_native_pixmap_t
+{
+    int32_t     version;    /* must be 32 */
+    int32_t     width;
+    int32_t     height;
+    int32_t     stride;
+    uint8_t*    data;
+    uint8_t     format;
+    uint8_t     rfu[3];
+    union {
+        uint32_t    compressedFormat;
+        int32_t     vstride;
+    };
+    int32_t     reserved;
+} egl_native_pixmap_t;
+
+/*****************************************************************************/
+
+#ifdef __cplusplus
+}
+#endif
+
+
+/*****************************************************************************/
+
+#ifdef __cplusplus
+
+#include <utils/RefBase.h>
+
+namespace android {
+
+/*
+ * This helper class turns an EGL android_native_xxx type into a C++
+ * reference-counted object; with proper type conversions.
+ */
+template <typename NATIVE_TYPE, typename TYPE, typename REF>
+class EGLNativeBase : public NATIVE_TYPE, public REF
+{
+protected:
+    typedef EGLNativeBase<NATIVE_TYPE, TYPE, REF> BASE;
+    EGLNativeBase() : NATIVE_TYPE(), REF() {
+        NATIVE_TYPE::common.incRef = incRef;
+        NATIVE_TYPE::common.decRef = decRef;
+    }
+    static inline TYPE* getSelf(NATIVE_TYPE* self) {
+        return static_cast<TYPE*>(self);
+    }
+    static inline TYPE const* getSelf(NATIVE_TYPE const* self) {
+        return static_cast<TYPE const *>(self);
+    }
+    static inline TYPE* getSelf(android_native_base_t* base) {
+        return getSelf(reinterpret_cast<NATIVE_TYPE*>(base));
+    }
+    static inline TYPE const * getSelf(android_native_base_t const* base) {
+        return getSelf(reinterpret_cast<NATIVE_TYPE const*>(base));
+    }
+    static void incRef(android_native_base_t* base) {
+        EGLNativeBase* self = getSelf(base);
+        self->incStrong(self);
+    }
+    static void decRef(android_native_base_t* base) {
+        EGLNativeBase* self = getSelf(base);
+        self->decStrong(self);
+    }
+};
+
+} // namespace android
+#endif // __cplusplus
+
+/*****************************************************************************/
+
+#endif /* ANDROID_ANDROID_NATIVES_H */
diff --git a/include/utils.h b/include/utils.h
deleted file mode 100644
index 30648b1..0000000
--- a/include/utils.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2005 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.
- */
-
-//
-// Handy utility functions and portability code.  This file includes all
-// of the generally-useful headers in the "utils" directory.
-//
-#ifndef _LIBS_UTILS_H
-#define _LIBS_UTILS_H
-
-#include <utils/ported.h>
-#include <utils/Log.h>
-#include <utils/threads.h>
-#include <utils/Timers.h>
-#include <utils/List.h>
-#include <utils/string_array.h>
-#include <utils/misc.h>
-#include <utils/Errors.h>
-
-#endif // _LIBS_UTILS_H
diff --git a/include/utils/Debug.h b/include/utils/Debug.h
index a662b9c..d9ed32d 100644
--- a/include/utils/Debug.h
+++ b/include/utils/Debug.h
@@ -14,10 +14,6 @@
  * limitations under the License.
  */
 
-//
-// Debugging tools.  These should be able to be stripped
-// in release builds.
-//
 #ifndef ANDROID_DEBUG_H
 #define ANDROID_DEBUG_H
 
@@ -25,9 +21,32 @@
 #include <sys/types.h>
 
 namespace android {
+// ---------------------------------------------------------------------------
 
+#ifdef __cplusplus
 template<bool> struct CompileTimeAssert;
 template<> struct CompileTimeAssert<true> {};
+#define COMPILE_TIME_ASSERT(_exp) \
+    template class CompileTimeAssert< (_exp) >;
+#endif
+#define COMPILE_TIME_ASSERT_FUNCTION_SCOPE(_exp) \
+    CompileTimeAssert<( _exp )>();
+
+// ---------------------------------------------------------------------------
+
+#ifdef __cplusplus
+template<bool C, typename LSH, typename RHS> struct CompileTimeIfElse;
+template<typename LHS, typename RHS> 
+struct CompileTimeIfElse<true,  LHS, RHS> { typedef LHS TYPE; };
+template<typename LHS, typename RHS> 
+struct CompileTimeIfElse<false, LHS, RHS> { typedef RHS TYPE; };
+#endif
+
+// ---------------------------------------------------------------------------
+
+#ifdef __cplusplus
+extern "C" {
+#endif
 
 const char* stringForIndent(int32_t indentLevel);
 
@@ -35,11 +54,17 @@
 
 void printTypeCode(uint32_t typeCode,
     debugPrintFunc func = 0, void* cookie = 0);
+
 void printHexData(int32_t indent, const void *buf, size_t length,
     size_t bytesPerLine=16, int32_t singleLineBytesCutoff=16,
     size_t alignment=0, bool cArrayStyle=false,
     debugPrintFunc func = 0, void* cookie = 0);
 
+#ifdef __cplusplus
+}
+#endif
+
+// ---------------------------------------------------------------------------
 }; // namespace android
 
 #endif // ANDROID_DEBUG_H
diff --git a/include/utils/Errors.h b/include/utils/Errors.h
index 1bf9e6f..81f818b 100644
--- a/include/utils/Errors.h
+++ b/include/utils/Errors.h
@@ -63,7 +63,7 @@
     BAD_INDEX           = -EOVERFLOW,
     NOT_ENOUGH_DATA     = -ENODATA,
     WOULD_BLOCK         = -EWOULDBLOCK, 
-    TIMED_OUT           = -ETIME,
+    TIMED_OUT           = -ETIMEDOUT,
     UNKNOWN_TRANSACTION = -EBADMSG,
 #else    
     BAD_INDEX           = -E2BIG,
diff --git a/include/utils/KeyedVector.h b/include/utils/KeyedVector.h
index f4513ee..6bcdea4 100644
--- a/include/utils/KeyedVector.h
+++ b/include/utils/KeyedVector.h
@@ -164,7 +164,7 @@
 template<typename KEY, typename VALUE> inline
 ssize_t KeyedVector<KEY,VALUE>::replaceValueAt(size_t index, const VALUE& item) {
     if (index<size()) {
-        mVector.editValueAt(index).value = item;
+        mVector.editItemAt(index).value = item;
         return index;
     }
     return BAD_INDEX;
diff --git a/include/utils/List.h b/include/utils/List.h
index 1a6be9a..403cd7f 100644
--- a/include/utils/List.h
+++ b/include/utils/List.h
@@ -22,147 +22,200 @@
 // construction, so if the compiler's auto-generated versions won't work for
 // you, define your own.
 //
-// The only class you want to use from here is "List".  Do not use classes
-// starting with "_" directly.
+// The only class you want to use from here is "List".
 //
 #ifndef _LIBS_UTILS_LIST_H
 #define _LIBS_UTILS_LIST_H
 
+#include <stddef.h>
+#include <stdint.h>
+
 namespace android {
 
 /*
- * One element in the list.
- */
-template<class T> class _ListNode {
-public:
-    typedef _ListNode<T> _Node;
-
-    _ListNode(const T& val) : mVal(val) {}
-    ~_ListNode(void) {}
-
-    T& getRef(void) { return mVal; }
-    void setVal(const T& val) { mVal = val; }
-
-    _Node* getPrev(void) const { return mpPrev; }
-    void setPrev(_Node* ptr) { mpPrev = ptr; }
-    _Node* getNext(void) const { return mpNext; }
-    void setNext(_Node* ptr) { mpNext = ptr; }
-
-private:
-    T           mVal;
-    _Node*      mpPrev;
-    _Node*      mpNext;
-};
-
-/*
- * Iterator for walking through the list.
- */
-template<class T, class Tref> class _ListIterator {
-public:
-    typedef _ListIterator<T,Tref> _Iter;
-    typedef _ListNode<T> _Node;
-
-    _ListIterator(void) {}
-    _ListIterator(_Node* ptr) : mpNode(ptr) {}
-    ~_ListIterator(void) {}
-
-    /*
-     * Dereference operator.  Used to get at the juicy insides.
-     */
-    Tref operator*() const { return mpNode->getRef(); }
-
-    /*
-     * Iterator comparison.
-     */
-    bool operator==(const _Iter& right) const { return mpNode == right.mpNode; }
-    bool operator!=(const _Iter& right) const { return mpNode != right.mpNode; }
-
-    /*
-     * Incr/decr, used to move through the list.
-     */
-    _Iter& operator++(void) {        // pre-increment
-        mpNode = mpNode->getNext();
-        return *this;
-    }
-    _Iter operator++(int) {          // post-increment
-        _Iter tmp = *this;
-        ++*this;
-        return tmp;
-    }
-    _Iter& operator--(void) {        // pre-increment
-        mpNode = mpNode->getPrev();
-        return *this;
-    }
-    _Iter operator--(int) {          // post-increment
-        _Iter tmp = *this;
-        --*this;
-        return tmp;
-    }
-
-    _Node* getNode(void) const { return mpNode; }
-
-private:
-    _Node*      mpNode;
-};
-
-
-/*
  * Doubly-linked list.  Instantiate with "List<MyClass> myList".
  *
  * Objects added to the list are copied using the assignment operator,
  * so this must be defined.
  */
-template<class T> class List {
-public:
-    typedef _ListNode<T> _Node;
+template<typename T> 
+class List 
+{
+protected:
+    /*
+     * One element in the list.
+     */
+    class _Node {
+    public:
+        explicit _Node(const T& val) : mVal(val) {}
+        ~_Node() {}
+        inline T& getRef() { return mVal; }
+        inline const T& getRef() const { return mVal; }
+        inline _Node* getPrev() const { return mpPrev; }
+        inline _Node* getNext() const { return mpNext; }
+        inline void setVal(const T& val) { mVal = val; }
+        inline void setPrev(_Node* ptr) { mpPrev = ptr; }
+        inline void setNext(_Node* ptr) { mpNext = ptr; }
+    private:
+        friend class List;
+        friend class _ListIterator;
+        T           mVal;
+        _Node*      mpPrev;
+        _Node*      mpNext;
+    };
 
-    List(void) {
+    /*
+     * Iterator for walking through the list.
+     */
+    
+    template <typename TYPE>
+    struct CONST_ITERATOR {
+        typedef _Node const * NodePtr;
+        typedef const TYPE Type;
+    };
+    
+    template <typename TYPE>
+    struct NON_CONST_ITERATOR {
+        typedef _Node* NodePtr;
+        typedef TYPE Type;
+    };
+    
+    template<
+        typename U,
+        template <class> class Constness
+    > 
+    class _ListIterator {
+        typedef _ListIterator<U, Constness>     _Iter;
+        typedef typename Constness<U>::NodePtr  _NodePtr;
+        typedef typename Constness<U>::Type     _Type;
+
+        explicit _ListIterator(_NodePtr ptr) : mpNode(ptr) {}
+
+    public:
+        _ListIterator() {}
+        _ListIterator(const _Iter& rhs) : mpNode(rhs.mpNode) {}
+        ~_ListIterator() {}
+        
+        // this will handle conversions from iterator to const_iterator
+        // (and also all convertible iterators)
+        // Here, in this implementation, the iterators can be converted
+        // if the nodes can be converted
+        template<typename V> explicit 
+        _ListIterator(const V& rhs) : mpNode(rhs.mpNode) {}
+        
+
+        /*
+         * Dereference operator.  Used to get at the juicy insides.
+         */
+        _Type& operator*() const { return mpNode->getRef(); }
+        _Type* operator->() const { return &(mpNode->getRef()); }
+
+        /*
+         * Iterator comparison.
+         */
+        inline bool operator==(const _Iter& right) const { 
+            return mpNode == right.mpNode; }
+        
+        inline bool operator!=(const _Iter& right) const { 
+            return mpNode != right.mpNode; }
+
+        /*
+         * handle comparisons between iterator and const_iterator
+         */
+        template<typename OTHER>
+        inline bool operator==(const OTHER& right) const { 
+            return mpNode == right.mpNode; }
+        
+        template<typename OTHER>
+        inline bool operator!=(const OTHER& right) const { 
+            return mpNode != right.mpNode; }
+
+        /*
+         * Incr/decr, used to move through the list.
+         */
+        inline _Iter& operator++() {     // pre-increment
+            mpNode = mpNode->getNext();
+            return *this;
+        }
+        const _Iter operator++(int) {    // post-increment
+            _Iter tmp(*this);
+            mpNode = mpNode->getNext();
+            return tmp;
+        }
+        inline _Iter& operator--() {     // pre-increment
+            mpNode = mpNode->getPrev();
+            return *this;
+        }
+        const _Iter operator--(int) {   // post-increment
+            _Iter tmp(*this);
+            mpNode = mpNode->getPrev();
+            return tmp;
+        }
+
+        inline _NodePtr getNode() const { return mpNode; }
+
+        _NodePtr mpNode;    /* should be private, but older gcc fails */
+    private:
+        friend class List;
+    };
+
+public:
+    List() {
         prep();
     }
     List(const List<T>& src) {      // copy-constructor
         prep();
         insert(begin(), src.begin(), src.end());
     }
-    virtual ~List(void) {
+    virtual ~List() {
         clear();
         delete[] (unsigned char*) mpMiddle;
     }
 
-    typedef _ListIterator<T,T&> iterator;
-    typedef _ListIterator<T, const T&> const_iterator;
+    typedef _ListIterator<T, NON_CONST_ITERATOR> iterator;
+    typedef _ListIterator<T, CONST_ITERATOR> const_iterator;
 
     List<T>& operator=(const List<T>& right);
 
     /* returns true if the list is empty */
-    bool empty(void) const { return mpMiddle->getNext() == mpMiddle; }
+    inline bool empty() const { return mpMiddle->getNext() == mpMiddle; }
 
     /* return #of elements in list */
-    unsigned int size(void) const {
-        return distance(begin(), end());
+    size_t size() const {
+        return size_t(distance(begin(), end()));
     }
 
     /*
      * Return the first element or one past the last element.  The
-     * _ListNode* we're returning is converted to an "iterator" by a
+     * _Node* we're returning is converted to an "iterator" by a
      * constructor in _ListIterator.
      */
-    iterator begin()                { return mpMiddle->getNext(); }
-    const_iterator begin() const    { return mpMiddle->getNext(); }
-    iterator end()                  { return mpMiddle; }
-    const_iterator end() const      { return mpMiddle; }
+    inline iterator begin() { 
+        return iterator(mpMiddle->getNext()); 
+    }
+    inline const_iterator begin() const { 
+        return const_iterator(const_cast<_Node const*>(mpMiddle->getNext())); 
+    }
+    inline iterator end() { 
+        return iterator(mpMiddle); 
+    }
+    inline const_iterator end() const { 
+        return const_iterator(const_cast<_Node const*>(mpMiddle)); 
+    }
 
     /* add the object to the head or tail of the list */
     void push_front(const T& val) { insert(begin(), val); }
     void push_back(const T& val) { insert(end(), val); }
 
     /* insert before the current node; returns iterator at new node */
-    iterator insert(iterator posn, const T& val) {
+    iterator insert(iterator posn, const T& val) 
+    {
         _Node* newNode = new _Node(val);        // alloc & copy-construct
         newNode->setNext(posn.getNode());
         newNode->setPrev(posn.getNode()->getPrev());
         posn.getNode()->getPrev()->setNext(newNode);
         posn.getNode()->setPrev(newNode);
-        return newNode;
+        return iterator(newNode);
     }
 
     /* insert a range of elements before the current node */
@@ -178,18 +231,18 @@
         pPrev->setNext(pNext);
         pNext->setPrev(pPrev);
         delete posn.getNode();
-        return pNext;
+        return iterator(pNext);
     }
 
     /* remove a range of elements */
     iterator erase(iterator first, iterator last) {
         while (first != last)
             erase(first++);     // don't erase than incr later!
-        return last;
+        return iterator(last);
     }
 
     /* remove all contents of the list */
-    void clear(void) {
+    void clear() {
         _Node* pCurrent = mpMiddle->getNext();
         _Node* pNext;
 
@@ -207,21 +260,20 @@
      * will be equal to "last".  The iterators must refer to the same
      * list.
      *
-     * (This is actually a generic iterator function.  It should be part
-     * of some other class, possibly an iterator base class.  It needs to
-     * know the difference between a list, which has to march through,
-     * and a vector, which can just do pointer math.)
+     * FIXME: This is actually a generic iterator function. It should be a 
+     * template function at the top-level with specializations for things like
+     * vector<>, which can just do pointer math). Here we limit it to
+     * _ListIterator of the same type but different constness.
      */
-    unsigned int distance(iterator first, iterator last) {
-        unsigned int count = 0;
-        while (first != last) {
-            ++first;
-            ++count;
-        }
-        return count;
-    }
-    unsigned int distance(const_iterator first, const_iterator last) const {
-        unsigned int count = 0;
+    template<
+        typename U,
+        template <class> class CL,
+        template <class> class CR
+    > 
+    ptrdiff_t distance(
+            _ListIterator<U, CL> first, _ListIterator<U, CR> last) const 
+    {
+        ptrdiff_t count = 0;
         while (first != last) {
             ++first;
             ++count;
@@ -231,12 +283,12 @@
 
 private:
     /*
-     * I want a _ListNode but don't need it to hold valid data.  More
+     * I want a _Node but don't need it to hold valid data.  More
      * to the point, I don't want T's constructor to fire, since it
      * might have side-effects or require arguments.  So, we do this
      * slightly uncouth storage alloc.
      */
-    void prep(void) {
+    void prep() {
         mpMiddle = (_Node*) new unsigned char[sizeof(_Node)];
         mpMiddle->setPrev(mpMiddle);
         mpMiddle->setNext(mpMiddle);
diff --git a/include/utils/LogSocket.h b/include/utils/LogSocket.h
deleted file mode 100644
index 01fbfb5..0000000
--- a/include/utils/LogSocket.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/* utils/LogSocket.h
-** 
-** Copyright 2008, The Android Open Source Project
-**
-** This file is dual licensed.  It may be redistributed and/or modified
-** under the terms of the Apache 2.0 License OR version 2 of the GNU
-** General Public License.
-*/
-
-#ifndef _UTILS_LOGSOCKET_H
-#define _UTILS_LOGSOCKET_H
-
-#define SOCKET_CLOSE_LOCAL 0
-
-void add_send_stats(int fd, int send);
-void add_recv_stats(int fd, int recv);
-void log_socket_close(int fd, short reason);
-void log_socket_connect(int fd, unsigned int ip, unsigned short port);
-
-#endif /* _UTILS_LOGSOCKET_H */
diff --git a/include/utils/Pipe.h b/include/utils/Pipe.h
deleted file mode 100644
index 6404168..0000000
--- a/include/utils/Pipe.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (C) 2005 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.
- */
-
-//
-// FIFO I/O.
-//
-#ifndef _LIBS_UTILS_PIPE_H
-#define _LIBS_UTILS_PIPE_H
-
-#ifdef HAVE_ANDROID_OS
-#error DO NOT USE THIS FILE IN THE DEVICE BUILD
-#endif
-
-namespace android {
-
-/*
- * Simple anonymous unidirectional pipe.
- *
- * The primary goal is to create an implementation with minimal overhead
- * under Linux.  Making Windows, Mac OS X, and Linux all work the same way
- * is a secondary goal.  Part of this goal is to have something that can
- * be fed to a select() call, so that the application can sleep in the
- * kernel until something interesting happens.
- */
-class Pipe {
-public:
-    Pipe(void);
-    virtual ~Pipe(void);
-
-    /* Create the pipe */
-    bool create(void);
-
-    /* Create a read-only pipe, using the supplied handle as read handle */
-    bool createReader(unsigned long handle);
-    /* Create a write-only pipe, using the supplied handle as write handle */
-    bool createWriter(unsigned long handle);
-
-    /* Is this object ready to go? */
-    bool isCreated(void);
-
-    /*
-     * Read "count" bytes from the pipe.  Returns the amount of data read,
-     * or 0 if no data available and we're non-blocking.
-     * Returns -1 on error.
-     */
-    int read(void* buf, int count);
-
-    /*
-     * Write "count" bytes into the pipe.  Returns number of bytes written,
-     * or 0 if there's no room for more data and we're non-blocking.
-     * Returns -1 on error.
-     */
-    int write(const void* buf, int count);
-
-    /* Returns "true" if data is available to read */
-    bool readReady(void);
-
-    /* Enable or disable non-blocking I/O for reads */
-    bool setReadNonBlocking(bool val);
-    /* Enable or disable non-blocking I/O for writes.  Only works on Linux. */
-    bool setWriteNonBlocking(bool val);
-
-    /*
-     * Get the handle.  Only useful in some platform-specific situations.
-     */
-    unsigned long getReadHandle(void);
-    unsigned long getWriteHandle(void);
-
-    /*
-     * Modify inheritance, i.e. whether or not a child process will get
-     * copies of the descriptors.  Systems with fork+exec allow us to close
-     * the descriptors before launching the child process, but Win32
-     * doesn't allow it.
-     */
-    bool disallowReadInherit(void);
-    bool disallowWriteInherit(void);
-
-    /*
-     * Close one side or the other.  Useful in the parent after launching
-     * a child process.
-     */
-    bool closeRead(void);
-    bool closeWrite(void);
-
-private:
-    bool    mReadNonBlocking;
-    bool    mWriteNonBlocking;
-
-    unsigned long mReadHandle;
-    unsigned long mWriteHandle;
-};
-
-}; // android
-
-#endif // _LIBS_UTILS_PIPE_H
diff --git a/include/utils/RefBase.h b/include/utils/RefBase.h
index cbda0fd..bd7f28c 100644
--- a/include/utils/RefBase.h
+++ b/include/utils/RefBase.h
@@ -156,6 +156,10 @@
             delete static_cast<const T*>(this);
         }
     }
+    //! DEBUGGING ONLY: Get current strong ref count.
+    inline int32_t getStrongCount() const {
+        return mCount;
+    }
     
 protected:
     inline ~LightRefBase() { }
diff --git a/include/utils/ResourceTypes.h b/include/utils/ResourceTypes.h
index e524e2a..49145e8 100644
--- a/include/utils/ResourceTypes.h
+++ b/include/utils/ResourceTypes.h
@@ -864,6 +864,13 @@
         KEYSHIDDEN_SOFT = 0x0003,
     };
     
+    enum {
+        MASK_NAVHIDDEN = 0x000c,
+        NAVHIDDEN_ANY = 0x0000,
+        NAVHIDDEN_NO = 0x0004,
+        NAVHIDDEN_YES = 0x0008,
+    };
+    
     union {
         struct {
             uint8_t keyboard;
@@ -1011,7 +1018,8 @@
         if (orientation != o.orientation) diffs |= CONFIG_ORIENTATION;
         if (density != o.density) diffs |= CONFIG_DENSITY;
         if (touchscreen != o.touchscreen) diffs |= CONFIG_TOUCHSCREEN;
-        if (((inputFlags^o.inputFlags)&MASK_KEYSHIDDEN) != 0) diffs |= CONFIG_KEYBOARD_HIDDEN;
+        if (((inputFlags^o.inputFlags)&(MASK_KEYSHIDDEN|MASK_NAVHIDDEN)) != 0)
+                diffs |= CONFIG_KEYBOARD_HIDDEN;
         if (keyboard != o.keyboard) diffs |= CONFIG_KEYBOARD;
         if (navigation != o.navigation) diffs |= CONFIG_NAVIGATION;
         if (screenSize != o.screenSize) diffs |= CONFIG_SCREEN_SIZE;
@@ -1082,6 +1090,11 @@
                 if (!(o.inputFlags & MASK_KEYSHIDDEN)) return true;
             }
 
+            if (((inputFlags^o.inputFlags) & MASK_NAVHIDDEN) != 0) {
+                if (!(inputFlags & MASK_NAVHIDDEN)) return false;
+                if (!(o.inputFlags & MASK_NAVHIDDEN)) return true;
+            }
+
             if (keyboard != o.keyboard) {
                 if (!keyboard) return false;
                 if (!o.keyboard) return true;
@@ -1225,6 +1238,18 @@
                     }
                 }
 
+                const int navHidden = inputFlags & MASK_NAVHIDDEN;
+                const int oNavHidden = o.inputFlags & MASK_NAVHIDDEN;
+                if (navHidden != oNavHidden) {
+                    const int reqNavHidden =
+                            requested->inputFlags & MASK_NAVHIDDEN;
+                    if (reqNavHidden) {
+
+                        if (!navHidden) return false;
+                        if (!oNavHidden) return true;
+                    }
+                }
+
                 if ((keyboard != o.keyboard) && requested->keyboard) {
                     return (keyboard);
                 }
@@ -1247,7 +1272,7 @@
 
             if (version || o.version) {
                 if ((sdkVersion != o.sdkVersion) && requested->sdkVersion) {
-                    return (sdkVersion);
+                    return (sdkVersion > o.sdkVersion);
                 }
 
                 if ((minorVersion != o.minorVersion) &&
@@ -1332,6 +1357,12 @@
                     return false;
                 }
             }
+            const int navHidden = inputFlags&MASK_NAVHIDDEN;
+            const int setNavHidden = settings.inputFlags&MASK_NAVHIDDEN;
+            if (setNavHidden != 0 && navHidden != 0
+                && navHidden != setNavHidden) {
+                return false;
+            }
             if (settings.keyboard != 0 && keyboard != 0
                 && keyboard != settings.keyboard) {
                 return false;
@@ -1353,7 +1384,7 @@
         }
         if (version != 0) {
             if (settings.sdkVersion != 0 && sdkVersion != 0
-                && sdkVersion != settings.sdkVersion) {
+                && sdkVersion > settings.sdkVersion) {
                 return false;
             }
             if (settings.minorVersion != 0 && minorVersion != 0
diff --git a/include/utils/Singleton.h b/include/utils/Singleton.h
new file mode 100644
index 0000000..bc7626a
--- /dev/null
+++ b/include/utils/Singleton.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_UTILS_SINGLETON_H
+#define ANDROID_UTILS_SINGLETON_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <utils/threads.h>
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+template <typename TYPE>
+class Singleton
+{
+public:
+    static TYPE& getInstance() {
+        Mutex::Autolock _l(sLock);
+        TYPE* instance = sInstance;
+        if (instance == 0) {
+            instance = new TYPE();
+            sInstance = instance;
+        }
+        return *instance;
+    }
+    
+protected:
+    ~Singleton() { };
+    Singleton() { };
+
+private:
+    Singleton(const Singleton&);
+    Singleton& operator = (const Singleton&);
+    static Mutex sLock;
+    static TYPE* sInstance;
+};
+
+/*
+ * use ANDROID_SINGLETON_STATIC_INSTANCE(TYPE) in your implementation file
+ * (eg: <TYPE>.cpp) to create the static instance of Singleton<>'s attributes,
+ * and avoid to have a copy of them in each compilation units Singleton<TYPE>
+ * is used.
+ */
+
+#define ANDROID_SINGLETON_STATIC_INSTANCE(TYPE)             \
+    template class Singleton< TYPE >;                       \
+    template< class TYPE > Mutex Singleton< TYPE >::sLock;  \
+    template<> TYPE* Singleton< TYPE >::sInstance(0);
+
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_UTILS_SINGLETON_H
+
diff --git a/include/utils/Socket.h b/include/utils/Socket.h
deleted file mode 100644
index 8b7f406..0000000
--- a/include/utils/Socket.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2005 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.
- */
-
-//
-// Socket class.  Modeled after Java classes.
-//
-#ifndef _RUNTIME_SOCKET_H
-#define _RUNTIME_SOCKET_H
-
-#include <utils/inet_address.h>
-#include <sys/types.h>
-
-namespace android {
-
-/*
- * Basic socket class, needed to abstract away the differences between
- * BSD sockets and WinSock.  This establishes a streaming network
- * connection (TCP/IP) to somebody.
- */
-class Socket {
-public:
-    Socket(void);
-    ~Socket(void);
-
-    // Create a connection to somewhere.
-    // Return 0 on success.
-    int connect(const char* host, int port);
-    int connect(const InetAddress* addr, int port);
-
-
-    // Close the socket.  Don't try to use this object again after
-    // calling this.  Returns false on failure.
-    bool close(void);
-
-    // If we created the socket without an address, we can use these
-    // to finish the connection.  Returns 0 on success.
-    int bind(const SocketAddress& bindPoint);
-    int connect(const SocketAddress& endPoint);
-
-    // Here we deviate from the traditional object-oriented fanciness
-    // and just provide read/write operators instead of getters for
-    // objects that abstract a stream.
-    //
-    // Standard read/write semantics.
-    int read(void* buf, ssize_t len) const;
-    int write(const void* buf, ssize_t len) const;
-
-    // This must be called once, at program startup.
-    static bool bootInit(void);
-    static void finalShutdown(void);
-
-private:
-    // Internal function that establishes a connection.
-    int doConnect(const InetSocketAddress& addr);
-
-    unsigned long   mSock;      // holds SOCKET or int
-
-    static bool     mBootInitialized;
-};
-
-
-// debug -- unit tests
-void TestSockets(void);
-
-}; // namespace android
-
-#endif // _RUNTIME_SOCKET_H
diff --git a/include/utils/SortedVector.h b/include/utils/SortedVector.h
index c8a6153..8beec57 100644
--- a/include/utils/SortedVector.h
+++ b/include/utils/SortedVector.h
@@ -141,8 +141,7 @@
     : SortedVectorImpl(sizeof(TYPE),
                 ((traits<TYPE>::has_trivial_ctor   ? HAS_TRIVIAL_CTOR   : 0)
                 |(traits<TYPE>::has_trivial_dtor   ? HAS_TRIVIAL_DTOR   : 0)
-                |(traits<TYPE>::has_trivial_copy   ? HAS_TRIVIAL_COPY   : 0)
-                |(traits<TYPE>::has_trivial_assign ? HAS_TRIVIAL_ASSIGN : 0))
+                |(traits<TYPE>::has_trivial_copy   ? HAS_TRIVIAL_COPY   : 0))
                 )
 {
 }
diff --git a/include/utils/StringArray.h b/include/utils/StringArray.h
new file mode 100644
index 0000000..c2445871
--- /dev/null
+++ b/include/utils/StringArray.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+//
+// Sortable array of strings.  STL-ish, but STL-free.
+//  
+#ifndef _LIBS_UTILS_STRING_ARRAY_H
+#define _LIBS_UTILS_STRING_ARRAY_H
+
+#include <stdlib.h>
+#include <string.h>
+
+namespace android {
+
+//
+// An expanding array of strings.  Add, get, sort, delete.
+//
+class StringArray {
+public:
+    StringArray();
+    virtual ~StringArray();
+
+    //
+    // Add a string.  A copy of the string is made.
+    //
+    bool push_back(const char* str);
+
+    //
+    // Delete an entry.
+    //
+    void erase(int idx);
+
+    //
+    // Sort the array.
+    //
+    void sort(int (*compare)(const void*, const void*));
+    
+    //
+    // Pass this to the sort routine to do an ascending alphabetical sort.
+    //
+    static int cmpAscendingAlpha(const void* pstr1, const void* pstr2);
+    
+    //
+    // Get the #of items in the array.
+    //
+    inline int size(void) const { return mCurrent; }
+
+    //
+    // Return entry N.
+    // [should use operator[] here]
+    //
+    const char* getEntry(int idx) const {
+        return (unsigned(idx) >= unsigned(mCurrent)) ? NULL : mArray[idx];
+    }
+
+    //
+    // Set entry N to specified string.
+    // [should use operator[] here]
+    //
+    void setEntry(int idx, const char* str);
+
+private:
+    int     mMax;
+    int     mCurrent;
+    char**  mArray;
+};
+
+}; // namespace android
+
+#endif // _LIBS_UTILS_STRING_ARRAY_H
diff --git a/include/utils/TextOutput.h b/include/utils/TextOutput.h
index d8d86ba..de2fbbe 100644
--- a/include/utils/TextOutput.h
+++ b/include/utils/TextOutput.h
@@ -28,8 +28,8 @@
 class TextOutput
 {
 public:
-                        TextOutput() { }
-    virtual             ~TextOutput() { }
+                        TextOutput();
+    virtual             ~TextOutput();
     
     virtual status_t    print(const char* txt, size_t len) = 0;
     virtual void        moveIndent(int delta) = 0;
diff --git a/include/utils/TimerProbe.h b/include/utils/TimerProbe.h
deleted file mode 100644
index f2e32b2..0000000
--- a/include/utils/TimerProbe.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_TIMER_PROBE_H
-#define ANDROID_TIMER_PROBE_H
-
-#if 0 && defined(HAVE_POSIX_CLOCKS)
-#define ENABLE_TIMER_PROBE 1
-#else
-#define ENABLE_TIMER_PROBE 0
-#endif
-
-#if ENABLE_TIMER_PROBE
-
-#include <time.h>
-#include <sys/time.h>
-#include <utils/Vector.h>
-
-#define TIMER_PROBE(tag) \
-    static int _timer_slot_; \
-    android::TimerProbe probe(tag, &_timer_slot_)
-#define TIMER_PROBE_END() probe.end()
-#else
-#define TIMER_PROBE(tag)
-#define TIMER_PROBE_END()
-#endif
-
-#if ENABLE_TIMER_PROBE
-namespace android {
-
-class TimerProbe {
-public:
-    TimerProbe(const char tag[], int* slot);
-    void end();
-    ~TimerProbe();
-private:
-    struct Bucket {
-        int mStart, mReal, mProcess, mThread, mCount;
-        const char* mTag;
-        int* mSlotPtr;
-        int mIndent;
-    };
-    static Vector<Bucket> gBuckets;
-    static TimerProbe* gExecuteChain;
-    static int gIndent;
-    static timespec gRealBase;
-    TimerProbe* mNext;
-    static uint32_t ElapsedTime(const timespec& start, const timespec& end);
-    void print(const timespec& r, const timespec& p, const timespec& t) const;
-    timespec mRealStart, mPStart, mTStart;
-    const char* mTag;
-    int mIndent;
-    int mBucket;
-};
-
-}; // namespace android
-
-#endif
-#endif
diff --git a/include/utils/Timers.h b/include/utils/Timers.h
index 9610399..9a9e07c 100644
--- a/include/utils/Timers.h
+++ b/include/utils/Timers.h
@@ -88,9 +88,6 @@
 nsecs_t systemTime(int clock);
 #endif // def __cplusplus
 
-// return the system-time according to the specified clock
-int sleepForInterval(long interval, struct timeval* pNextTick);
-
 #ifdef __cplusplus
 } // extern "C"
 #endif
@@ -108,15 +105,15 @@
  */
 class DurationTimer {
 public:
-    DurationTimer(void) {}
-    ~DurationTimer(void) {}
+    DurationTimer() {}
+    ~DurationTimer() {}
 
     // Start the timer.
-    void start(void);
+    void start();
     // Stop the timer.
-    void stop(void);
+    void stop();
     // Get the duration in microseconds.
-    long long durationUsecs(void) const;
+    long long durationUsecs() const;
 
     // Subtract two timevals.  Returns the difference (ptv1-ptv2) in
     // microseconds.
diff --git a/include/utils/TypeHelpers.h b/include/utils/TypeHelpers.h
index c04c37f..2ff2749 100644
--- a/include/utils/TypeHelpers.h
+++ b/include/utils/TypeHelpers.h
@@ -29,35 +29,39 @@
 /*
  * Types traits
  */
-    
-template <typename T> struct trait_trivial_ctor  { enum { value = false }; };
-template <typename T> struct trait_trivial_dtor  { enum { value = false }; };
-template <typename T> struct trait_trivial_copy  { enum { value = false }; };
-template <typename T> struct trait_trivial_assign{ enum { value = false }; };
 
-template <typename T> struct trait_pointer     { enum { value = false }; };    
-template <typename T> struct trait_pointer<T*> { enum { value = true }; };
+template <typename T> struct trait_trivial_ctor { enum { value = false }; };
+template <typename T> struct trait_trivial_dtor { enum { value = false }; };
+template <typename T> struct trait_trivial_copy { enum { value = false }; };
+template <typename T> struct trait_trivial_move { enum { value = false }; };
+template <typename T> struct trait_pointer      { enum { value = false }; };    
+template <typename T> struct trait_pointer<T*>  { enum { value = true }; };
 
-#define ANDROID_BASIC_TYPES_TRAITS( T )                                       \
-    template<> struct trait_trivial_ctor< T >  { enum { value = true }; };    \
-    template<> struct trait_trivial_dtor< T >  { enum { value = true }; };    \
-    template<> struct trait_trivial_copy< T >  { enum { value = true }; };    \
-    template<> struct trait_trivial_assign< T >{ enum { value = true }; }; 
+// sp<> can be trivially moved
+template <typename T> class sp;
+template <typename T> struct trait_trivial_move< sp<T> >{
+    enum { value = true }; 
+};
 
-#define ANDROID_TYPE_TRAITS( T, ctor, dtor, copy, assign )                    \
-    template<> struct trait_trivial_ctor< T >  { enum { value = ctor }; };    \
-    template<> struct trait_trivial_dtor< T >  { enum { value = dtor }; };    \
-    template<> struct trait_trivial_copy< T >  { enum { value = copy }; };    \
-    template<> struct trait_trivial_assign< T >{ enum { value = assign }; }; 
+// wp<> can be trivially moved
+template <typename T> class wp;
+template <typename T> struct trait_trivial_move< wp<T> >{ 
+    enum { value = true }; 
+};
 
 template <typename TYPE>
 struct traits {
     enum {
+        // whether this type is a pointer
         is_pointer          = trait_pointer<TYPE>::value,
+        // whether this type's constructor is a no-op
         has_trivial_ctor    = is_pointer || trait_trivial_ctor<TYPE>::value,
+        // whether this type's destructor is a no-op
         has_trivial_dtor    = is_pointer || trait_trivial_dtor<TYPE>::value,
+        // whether this type type can be copy-constructed with memcpy
         has_trivial_copy    = is_pointer || trait_trivial_copy<TYPE>::value,
-        has_trivial_assign  = is_pointer || trait_trivial_assign<TYPE>::value   
+        // whether this type can be moved with memmove
+        has_trivial_move    = is_pointer || trait_trivial_move<TYPE>::value
     };
 };
 
@@ -65,37 +69,47 @@
 struct aggregate_traits {
     enum {
         is_pointer          = false,
-        has_trivial_ctor    = traits<T>::has_trivial_ctor && traits<U>::has_trivial_ctor,
-        has_trivial_dtor    = traits<T>::has_trivial_dtor && traits<U>::has_trivial_dtor,
-        has_trivial_copy    = traits<T>::has_trivial_copy && traits<U>::has_trivial_copy,
-        has_trivial_assign  = traits<T>::has_trivial_assign && traits<U>::has_trivial_assign
+        has_trivial_ctor    = 
+            traits<T>::has_trivial_ctor && traits<U>::has_trivial_ctor,
+        has_trivial_dtor    = 
+            traits<T>::has_trivial_dtor && traits<U>::has_trivial_dtor,
+        has_trivial_copy    = 
+            traits<T>::has_trivial_copy && traits<U>::has_trivial_copy,
+        has_trivial_move    = 
+            traits<T>::has_trivial_move && traits<U>::has_trivial_move
     };
 };
 
+#define ANDROID_BASIC_TYPES_TRAITS( T )                                     \
+    template<> struct trait_trivial_ctor< T >   { enum { value = true }; }; \
+    template<> struct trait_trivial_dtor< T >   { enum { value = true }; }; \
+    template<> struct trait_trivial_copy< T >   { enum { value = true }; }; \
+    template<> struct trait_trivial_move< T >   { enum { value = true }; };
+
 // ---------------------------------------------------------------------------
 
 /*
  * basic types traits
  */
- 
-ANDROID_BASIC_TYPES_TRAITS( void );
-ANDROID_BASIC_TYPES_TRAITS( bool );
-ANDROID_BASIC_TYPES_TRAITS( char );
-ANDROID_BASIC_TYPES_TRAITS( unsigned char );
-ANDROID_BASIC_TYPES_TRAITS( short );
-ANDROID_BASIC_TYPES_TRAITS( unsigned short );
-ANDROID_BASIC_TYPES_TRAITS( int );
-ANDROID_BASIC_TYPES_TRAITS( unsigned int );
-ANDROID_BASIC_TYPES_TRAITS( long );
-ANDROID_BASIC_TYPES_TRAITS( unsigned long );
-ANDROID_BASIC_TYPES_TRAITS( long long );
-ANDROID_BASIC_TYPES_TRAITS( unsigned long long );
-ANDROID_BASIC_TYPES_TRAITS( float );
-ANDROID_BASIC_TYPES_TRAITS( double );
+
+ANDROID_BASIC_TYPES_TRAITS( void )
+ANDROID_BASIC_TYPES_TRAITS( bool )
+ANDROID_BASIC_TYPES_TRAITS( char )
+ANDROID_BASIC_TYPES_TRAITS( unsigned char )
+ANDROID_BASIC_TYPES_TRAITS( short )
+ANDROID_BASIC_TYPES_TRAITS( unsigned short )
+ANDROID_BASIC_TYPES_TRAITS( int )
+ANDROID_BASIC_TYPES_TRAITS( unsigned int )
+ANDROID_BASIC_TYPES_TRAITS( long )
+ANDROID_BASIC_TYPES_TRAITS( unsigned long )
+ANDROID_BASIC_TYPES_TRAITS( long long )
+ANDROID_BASIC_TYPES_TRAITS( unsigned long long )
+ANDROID_BASIC_TYPES_TRAITS( float )
+ANDROID_BASIC_TYPES_TRAITS( double )
 
 // ---------------------------------------------------------------------------
 
-    
+
 /*
  * compare and order types
  */
@@ -111,9 +125,9 @@
 }
 
 /*
- * create, destroy, copy and assign types...
+ * create, destroy, copy and move types...
  */
- 
+
 template<typename TYPE> inline
 void construct_type(TYPE* p, size_t n) {
     if (!traits<TYPE>::has_trivial_ctor) {
@@ -146,17 +160,6 @@
 }
 
 template<typename TYPE> inline
-void assign_type(TYPE* d, const TYPE* s, size_t n) {
-    if (!traits<TYPE>::has_trivial_assign) {
-        while (n--) {
-            *d++ = *s++;
-        }
-    } else {
-        memcpy(d,s,n*sizeof(TYPE));
-    }
-}
-
-template<typename TYPE> inline
 void splat_type(TYPE* where, const TYPE* what, size_t n) {
     if (!traits<TYPE>::has_trivial_copy) {
         while (n--) {
@@ -164,15 +167,19 @@
             where++;
         }
     } else {
-         while (n--) {
-             *where++ = *what;
+        while (n--) {
+            *where++ = *what;
         }
     }
 }
 
 template<typename TYPE> inline
 void move_forward_type(TYPE* d, const TYPE* s, size_t n = 1) {
-    if (!traits<TYPE>::has_trivial_copy || !traits<TYPE>::has_trivial_dtor) {
+    if ((traits<TYPE>::has_trivial_dtor && traits<TYPE>::has_trivial_copy) 
+            || traits<TYPE>::has_trivial_move) 
+    {
+        memmove(d,s,n*sizeof(TYPE));
+    } else {
         d += n;
         s += n;
         while (n--) {
@@ -180,35 +187,37 @@
             if (!traits<TYPE>::has_trivial_copy) {
                 new(d) TYPE(*s);
             } else {
-                *d = *s;
+                *d = *s;   
             }
             if (!traits<TYPE>::has_trivial_dtor) {
                 s->~TYPE();
             }
         }
-    } else {
-        memmove(d,s,n*sizeof(TYPE));
     }
 }
 
 template<typename TYPE> inline
 void move_backward_type(TYPE* d, const TYPE* s, size_t n = 1) {
-    if (!traits<TYPE>::has_trivial_copy || !traits<TYPE>::has_trivial_dtor) {
+    if ((traits<TYPE>::has_trivial_dtor && traits<TYPE>::has_trivial_copy) 
+            || traits<TYPE>::has_trivial_move) 
+    {
+        memmove(d,s,n*sizeof(TYPE));
+    } else {
         while (n--) {
             if (!traits<TYPE>::has_trivial_copy) {
                 new(d) TYPE(*s);
             } else {
-                *d = *s;
+                *d = *s;   
             }
             if (!traits<TYPE>::has_trivial_dtor) {
                 s->~TYPE();
             }
             d++, s++;
         }
-    } else {
-        memmove(d,s,n*sizeof(TYPE));
     }
 }
+
+
 // ---------------------------------------------------------------------------
 
 /*
@@ -242,8 +251,8 @@
 { enum { value = aggregate_traits<K,V>::has_trivial_copy }; };
 template<> 
 template <typename K, typename V>
-struct trait_trivial_assign< key_value_pair_t<K, V> >
-{ enum { value = aggregate_traits<K,V>::has_trivial_assign};};
+struct trait_trivial_move< key_value_pair_t<K, V> >
+{ enum { value = aggregate_traits<K,V>::has_trivial_move }; };
 
 // ---------------------------------------------------------------------------
 
diff --git a/include/utils/Vector.h b/include/utils/Vector.h
index be365d8..ad59fd6 100644
--- a/include/utils/Vector.h
+++ b/include/utils/Vector.h
@@ -175,8 +175,7 @@
     : VectorImpl(sizeof(TYPE),
                 ((traits<TYPE>::has_trivial_ctor   ? HAS_TRIVIAL_CTOR   : 0)
                 |(traits<TYPE>::has_trivial_dtor   ? HAS_TRIVIAL_DTOR   : 0)
-                |(traits<TYPE>::has_trivial_copy   ? HAS_TRIVIAL_COPY   : 0)
-                |(traits<TYPE>::has_trivial_assign ? HAS_TRIVIAL_ASSIGN : 0))
+                |(traits<TYPE>::has_trivial_copy   ? HAS_TRIVIAL_COPY   : 0))
                 )
 {
 }
diff --git a/include/utils/VectorImpl.h b/include/utils/VectorImpl.h
index 2525229..49b03f1 100644
--- a/include/utils/VectorImpl.h
+++ b/include/utils/VectorImpl.h
@@ -44,7 +44,6 @@
         HAS_TRIVIAL_CTOR    = 0x00000001,
         HAS_TRIVIAL_DTOR    = 0x00000002,
         HAS_TRIVIAL_COPY    = 0x00000004,
-        HAS_TRIVIAL_ASSIGN  = 0x00000008
     };
 
                             VectorImpl(size_t itemSize, uint32_t flags);
diff --git a/include/utils/ZipEntry.h b/include/utils/ZipEntry.h
deleted file mode 100644
index e4698df..0000000
--- a/include/utils/ZipEntry.h
+++ /dev/null
@@ -1,345 +0,0 @@
-/*
- * Copyright (C) 2006 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.
- */
-
-//
-// Zip archive entries.
-//
-// The ZipEntry class is tightly meshed with the ZipFile class.
-//
-#ifndef __LIBS_ZIPENTRY_H
-#define __LIBS_ZIPENTRY_H
-
-#include "Errors.h"
-
-#include <stdlib.h>
-#include <stdio.h>
-
-namespace android {
-
-class ZipFile;
-
-/*
- * ZipEntry objects represent a single entry in a Zip archive.
- *
- * You can use one of these to get or set information about an entry, but
- * there are no functions here for accessing the data itself.  (We could
- * tuck a pointer to the ZipFile in here for convenience, but that raises
- * the likelihood of using ZipEntry objects after discarding the ZipFile.)
- *
- * File information is stored in two places: next to the file data (the Local
- * File Header, and possibly a Data Descriptor), and at the end of the file
- * (the Central Directory Entry).  The two must be kept in sync.
- */
-class ZipEntry {
-public:
-    friend class ZipFile;
-
-    ZipEntry(void)
-        : mDeleted(false), mMarked(false)
-        {}
-    ~ZipEntry(void) {}
-
-    /*
-     * Returns "true" if the data is compressed.
-     */
-    bool isCompressed(void) const {
-        return mCDE.mCompressionMethod != kCompressStored;
-    }
-    int getCompressionMethod(void) const { return mCDE.mCompressionMethod; }
-
-    /*
-     * Return the uncompressed length.
-     */
-    off_t getUncompressedLen(void) const { return mCDE.mUncompressedSize; }
-
-    /*
-     * Return the compressed length.  For uncompressed data, this returns
-     * the same thing as getUncompresesdLen().
-     */
-    off_t getCompressedLen(void) const { return mCDE.mCompressedSize; }
-
-    /*
-     * Return the absolute file offset of the start of the compressed or
-     * uncompressed data.
-     */
-    off_t getFileOffset(void) const {
-        return mCDE.mLocalHeaderRelOffset +
-                LocalFileHeader::kLFHLen +
-                mLFH.mFileNameLength +
-                mLFH.mExtraFieldLength;
-    }
-
-    /*
-     * Return the data CRC.
-     */
-    unsigned long getCRC32(void) const { return mCDE.mCRC32; }
-
-    /*
-     * Return file modification time in UNIX seconds-since-epoch.
-     */
-    time_t getModWhen(void) const;
-
-    /*
-     * Return the archived file name.
-     */
-    const char* getFileName(void) const { return (const char*) mCDE.mFileName; }
-
-    /*
-     * Application-defined "mark".  Can be useful when synchronizing the
-     * contents of an archive with contents on disk.
-     */
-    bool getMarked(void) const { return mMarked; }
-    void setMarked(bool val) { mMarked = val; }
-
-    /*
-     * Some basic functions for raw data manipulation.  "LE" means
-     * Little Endian.
-     */
-    static inline unsigned short getShortLE(const unsigned char* buf) {
-        return buf[0] | (buf[1] << 8);
-    }
-    static inline unsigned long getLongLE(const unsigned char* buf) {
-        return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
-    }
-    static inline void putShortLE(unsigned char* buf, short val) {
-        buf[0] = (unsigned char) val;
-        buf[1] = (unsigned char) (val >> 8);
-    }
-    static inline void putLongLE(unsigned char* buf, long val) {
-        buf[0] = (unsigned char) val;
-        buf[1] = (unsigned char) (val >> 8);
-        buf[2] = (unsigned char) (val >> 16);
-        buf[3] = (unsigned char) (val >> 24);
-    }
-
-    /* defined for Zip archives */
-    enum {
-        kCompressStored     = 0,        // no compression
-        // shrunk           = 1,
-        // reduced 1        = 2,
-        // reduced 2        = 3,
-        // reduced 3        = 4,
-        // reduced 4        = 5,
-        // imploded         = 6,
-        // tokenized        = 7,
-        kCompressDeflated   = 8,        // standard deflate
-        // Deflate64        = 9,
-        // lib imploded     = 10,
-        // reserved         = 11,
-        // bzip2            = 12,
-    };
-
-    /*
-     * Deletion flag.  If set, the entry will be removed on the next
-     * call to "flush".
-     */
-    bool getDeleted(void) const { return mDeleted; }
-
-protected:
-    /*
-     * Initialize the structure from the file, which is pointing at
-     * our Central Directory entry.
-     */
-    status_t initFromCDE(FILE* fp);
-
-    /*
-     * Initialize the structure for a new file.  We need the filename
-     * and comment so that we can properly size the LFH area.  The
-     * filename is mandatory, the comment is optional.
-     */
-    void initNew(const char* fileName, const char* comment);
-
-    /*
-     * Initialize the structure with the contents of a ZipEntry from
-     * another file.
-     */
-    status_t initFromExternal(const ZipFile* pZipFile, const ZipEntry* pEntry);
-
-    /*
-     * Add some pad bytes to the LFH.  We do this by adding or resizing
-     * the "extra" field.
-     */
-    status_t addPadding(int padding);
-
-    /*
-     * Set information about the data for this entry.
-     */
-    void setDataInfo(long uncompLen, long compLen, unsigned long crc32,
-        int compressionMethod);
-
-    /*
-     * Set the modification date.
-     */
-    void setModWhen(time_t when);
-
-    /*
-     * Return the offset of the local file header.
-     */
-    off_t getLFHOffset(void) const { return mCDE.mLocalHeaderRelOffset; }
-
-    /*
-     * Set the offset of the local file header, relative to the start of
-     * the current file.
-     */
-    void setLFHOffset(off_t offset) {
-        mCDE.mLocalHeaderRelOffset = (long) offset;
-    }
-
-    /* mark for deletion; used by ZipFile::remove() */
-    void setDeleted(void) { mDeleted = true; }
-
-private:
-    /* these are private and not defined */
-    ZipEntry(const ZipEntry& src);
-    ZipEntry& operator=(const ZipEntry& src);
-
-    /* returns "true" if the CDE and the LFH agree */
-    bool compareHeaders(void) const;
-    void copyCDEtoLFH(void);
-
-    bool        mDeleted;       // set if entry is pending deletion
-    bool        mMarked;        // app-defined marker
-
-    /*
-     * Every entry in the Zip archive starts off with one of these.
-     */
-    class LocalFileHeader {
-    public:
-        LocalFileHeader(void) :
-            mVersionToExtract(0),
-            mGPBitFlag(0),
-            mCompressionMethod(0),
-            mLastModFileTime(0),
-            mLastModFileDate(0),
-            mCRC32(0),
-            mCompressedSize(0),
-            mUncompressedSize(0),
-            mFileNameLength(0),
-            mExtraFieldLength(0),
-            mFileName(NULL),
-            mExtraField(NULL)
-        {}
-        virtual ~LocalFileHeader(void) {
-            delete[] mFileName;
-            delete[] mExtraField;
-        }
-
-        status_t read(FILE* fp);
-        status_t write(FILE* fp);
-
-        // unsigned long mSignature;
-        unsigned short  mVersionToExtract;
-        unsigned short  mGPBitFlag;
-        unsigned short  mCompressionMethod;
-        unsigned short  mLastModFileTime;
-        unsigned short  mLastModFileDate;
-        unsigned long   mCRC32;
-        unsigned long   mCompressedSize;
-        unsigned long   mUncompressedSize;
-        unsigned short  mFileNameLength;
-        unsigned short  mExtraFieldLength;
-        unsigned char*  mFileName;
-        unsigned char*  mExtraField;
-
-        enum {
-            kSignature      = 0x04034b50,
-            kLFHLen         = 30,       // LocalFileHdr len, excl. var fields
-        };
-
-        void dump(void) const;
-    };
-
-    /*
-     * Every entry in the Zip archive has one of these in the "central
-     * directory" at the end of the file.
-     */
-    class CentralDirEntry {
-    public:
-        CentralDirEntry(void) :
-            mVersionMadeBy(0),
-            mVersionToExtract(0),
-            mGPBitFlag(0),
-            mCompressionMethod(0),
-            mLastModFileTime(0),
-            mLastModFileDate(0),
-            mCRC32(0),
-            mCompressedSize(0),
-            mUncompressedSize(0),
-            mFileNameLength(0),
-            mExtraFieldLength(0),
-            mFileCommentLength(0),
-            mDiskNumberStart(0),
-            mInternalAttrs(0),
-            mExternalAttrs(0),
-            mLocalHeaderRelOffset(0),
-            mFileName(NULL),
-            mExtraField(NULL),
-            mFileComment(NULL)
-        {}
-        virtual ~CentralDirEntry(void) {
-            delete[] mFileName;
-            delete[] mExtraField;
-            delete[] mFileComment;
-        }
-
-        status_t read(FILE* fp);
-        status_t write(FILE* fp);
-
-        // unsigned long mSignature;
-        unsigned short  mVersionMadeBy;
-        unsigned short  mVersionToExtract;
-        unsigned short  mGPBitFlag;
-        unsigned short  mCompressionMethod;
-        unsigned short  mLastModFileTime;
-        unsigned short  mLastModFileDate;
-        unsigned long   mCRC32;
-        unsigned long   mCompressedSize;
-        unsigned long   mUncompressedSize;
-        unsigned short  mFileNameLength;
-        unsigned short  mExtraFieldLength;
-        unsigned short  mFileCommentLength;
-        unsigned short  mDiskNumberStart;
-        unsigned short  mInternalAttrs;
-        unsigned long   mExternalAttrs;
-        unsigned long   mLocalHeaderRelOffset;
-        unsigned char*  mFileName;
-        unsigned char*  mExtraField;
-        unsigned char*  mFileComment;
-
-        void dump(void) const;
-
-        enum {
-            kSignature      = 0x02014b50,
-            kCDELen         = 46,       // CentralDirEnt len, excl. var fields
-        };
-    };
-
-    enum {
-        //kDataDescriptorSignature  = 0x08074b50,   // currently unused
-        kDataDescriptorLen  = 16,           // four 32-bit fields
-
-        kDefaultVersion     = 20,           // need deflate, nothing much else
-        kDefaultMadeBy      = 0x0317,       // 03=UNIX, 17=spec v2.3
-        kUsesDataDescr      = 0x0008,       // GPBitFlag bit 3
-    };
-
-    LocalFileHeader     mLFH;
-    CentralDirEntry     mCDE;
-};
-
-}; // namespace android
-
-#endif // __LIBS_ZIPENTRY_H
diff --git a/include/utils/ZipFile.h b/include/utils/ZipFile.h
deleted file mode 100644
index 44df5bb..0000000
--- a/include/utils/ZipFile.h
+++ /dev/null
@@ -1,269 +0,0 @@
-/*
- * Copyright (C) 2006 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.
- */
-
-//
-// General-purpose Zip archive access.  This class allows both reading and
-// writing to Zip archives, including deletion of existing entries.
-//
-#ifndef __LIBS_ZIPFILE_H
-#define __LIBS_ZIPFILE_H
-
-#include "ZipEntry.h"
-#include "Vector.h"
-#include "Errors.h"
-#include <stdio.h>
-
-namespace android {
-
-/*
- * Manipulate a Zip archive.
- *
- * Some changes will not be visible in the until until "flush" is called.
- *
- * The correct way to update a file archive is to make all changes to a
- * copy of the archive in a temporary file, and then unlink/rename over
- * the original after everything completes.  Because we're only interested
- * in using this for packaging, we don't worry about such things.  Crashing
- * after making changes and before flush() completes could leave us with
- * an unusable Zip archive.
- */
-class ZipFile {
-public:
-    ZipFile(void)
-      : mZipFp(NULL), mReadOnly(false), mNeedCDRewrite(false)
-      {}
-    ~ZipFile(void) {
-        if (!mReadOnly)
-            flush();
-        if (mZipFp != NULL)
-            fclose(mZipFp);
-        discardEntries();
-    }
-
-    /*
-     * Open a new or existing archive.
-     */
-    typedef enum {
-        kOpenReadOnly   = 0x01,
-        kOpenReadWrite  = 0x02,
-        kOpenCreate     = 0x04,     // create if it doesn't exist
-        kOpenTruncate   = 0x08,     // if it exists, empty it
-    };
-    status_t open(const char* zipFileName, int flags);
-
-    /*
-     * Add a file to the end of the archive.  Specify whether you want the
-     * library to try to store it compressed.
-     *
-     * If "storageName" is specified, the archive will use that instead
-     * of "fileName".
-     *
-     * If there is already an entry with the same name, the call fails.
-     * Existing entries with the same name must be removed first.
-     *
-     * If "ppEntry" is non-NULL, a pointer to the new entry will be returned.
-     */
-    status_t add(const char* fileName, int compressionMethod,
-        ZipEntry** ppEntry)
-    {
-        return add(fileName, fileName, compressionMethod, ppEntry);
-    }
-    status_t add(const char* fileName, const char* storageName,
-        int compressionMethod, ZipEntry** ppEntry)
-    {
-        return addCommon(fileName, NULL, 0, storageName,
-                         ZipEntry::kCompressStored,
-                         compressionMethod, ppEntry);
-    }
-
-    /*
-     * Add a file that is already compressed with gzip.
-     *
-     * If "ppEntry" is non-NULL, a pointer to the new entry will be returned.
-     */
-    status_t addGzip(const char* fileName, const char* storageName,
-        ZipEntry** ppEntry)
-    {
-        return addCommon(fileName, NULL, 0, storageName,
-                         ZipEntry::kCompressDeflated,
-                         ZipEntry::kCompressDeflated, ppEntry);
-    }
-
-    /*
-     * Add a file from an in-memory data buffer.
-     *
-     * If "ppEntry" is non-NULL, a pointer to the new entry will be returned.
-     */
-    status_t add(const void* data, size_t size, const char* storageName,
-        int compressionMethod, ZipEntry** ppEntry)
-    {
-        return addCommon(NULL, data, size, storageName,
-                         ZipEntry::kCompressStored,
-                         compressionMethod, ppEntry);
-    }
-
-    /*
-     * Add an entry by copying it from another zip file.  If "padding" is
-     * nonzero, the specified number of bytes will be added to the "extra"
-     * field in the header.
-     *
-     * If "ppEntry" is non-NULL, a pointer to the new entry will be returned.
-     */
-    status_t add(const ZipFile* pSourceZip, const ZipEntry* pSourceEntry,
-        int padding, ZipEntry** ppEntry);
-
-    /*
-     * Mark an entry as having been removed.  It is not actually deleted
-     * from the archive or our internal data structures until flush() is
-     * called.
-     */
-    status_t remove(ZipEntry* pEntry);
-
-    /*
-     * Flush changes.  If mNeedCDRewrite is set, this writes the central dir.
-     */
-    status_t flush(void);
-
-    /*
-     * Expand the data into the buffer provided.  The buffer must hold
-     * at least <uncompressed len> bytes.  Variation expands directly
-     * to a file.
-     *
-     * Returns "false" if an error was encountered in the compressed data.
-     */
-    //bool uncompress(const ZipEntry* pEntry, void* buf) const;
-    //bool uncompress(const ZipEntry* pEntry, FILE* fp) const;
-    void* uncompress(const ZipEntry* pEntry);
-
-    /*
-     * Get an entry, by name.  Returns NULL if not found.
-     *
-     * Does not return entries pending deletion.
-     */
-    ZipEntry* getEntryByName(const char* fileName) const;
-
-    /*
-     * Get the Nth entry in the archive.
-     *
-     * This will return an entry that is pending deletion.
-     */
-    int getNumEntries(void) const { return mEntries.size(); }
-    ZipEntry* getEntryByIndex(int idx) const;
-
-private:
-    /* these are private and not defined */
-    ZipFile(const ZipFile& src);
-    ZipFile& operator=(const ZipFile& src);
-
-    class EndOfCentralDir {
-    public:
-        EndOfCentralDir(void) :
-            mDiskNumber(0),
-            mDiskWithCentralDir(0),
-            mNumEntries(0),
-            mTotalNumEntries(0),
-            mCentralDirSize(0),
-            mCentralDirOffset(0),
-            mCommentLen(0),
-            mComment(NULL)
-            {}
-        virtual ~EndOfCentralDir(void) {
-            delete[] mComment;
-        }
-
-        status_t readBuf(const unsigned char* buf, int len);
-        status_t write(FILE* fp);
-
-        //unsigned long   mSignature;
-        unsigned short  mDiskNumber;
-        unsigned short  mDiskWithCentralDir;
-        unsigned short  mNumEntries;
-        unsigned short  mTotalNumEntries;
-        unsigned long   mCentralDirSize;
-        unsigned long   mCentralDirOffset;      // offset from first disk
-        unsigned short  mCommentLen;
-        unsigned char*  mComment;
-
-        enum {
-            kSignature      = 0x06054b50,
-            kEOCDLen        = 22,       // EndOfCentralDir len, excl. comment
-
-            kMaxCommentLen  = 65535,    // longest possible in ushort
-            kMaxEOCDSearch  = kMaxCommentLen + EndOfCentralDir::kEOCDLen,
-
-        };
-
-        void dump(void) const;
-    };
-
-
-    /* read all entries in the central dir */
-    status_t readCentralDir(void);
-
-    /* crunch deleted entries out */
-    status_t crunchArchive(void);
-
-    /* clean up mEntries */
-    void discardEntries(void);
-
-    /* common handler for all "add" functions */
-    status_t addCommon(const char* fileName, const void* data, size_t size,
-        const char* storageName, int sourceType, int compressionMethod,
-        ZipEntry** ppEntry);
-
-    /* copy all of "srcFp" into "dstFp" */
-    status_t copyFpToFp(FILE* dstFp, FILE* srcFp, unsigned long* pCRC32);
-    /* copy all of "data" into "dstFp" */
-    status_t copyDataToFp(FILE* dstFp,
-        const void* data, size_t size, unsigned long* pCRC32);
-    /* copy some of "srcFp" into "dstFp" */
-    status_t copyPartialFpToFp(FILE* dstFp, FILE* srcFp, long length,
-        unsigned long* pCRC32);
-    /* like memmove(), but on parts of a single file */
-    status_t filemove(FILE* fp, off_t dest, off_t src, size_t n);
-    /* compress all of "srcFp" into "dstFp", using Deflate */
-    status_t compressFpToFp(FILE* dstFp, FILE* srcFp,
-        const void* data, size_t size, unsigned long* pCRC32);
-
-    /* get modification date from a file descriptor */
-    time_t getModTime(int fd);
-
-    /*
-     * We use stdio FILE*, which gives us buffering but makes dealing
-     * with files >2GB awkward.  Until we support Zip64, we're fine.
-     */
-    FILE*           mZipFp;             // Zip file pointer
-
-    /* one of these per file */
-    EndOfCentralDir mEOCD;
-
-    /* did we open this read-only? */
-    bool            mReadOnly;
-
-    /* set this when we trash the central dir */
-    bool            mNeedCDRewrite;
-
-    /*
-     * One ZipEntry per entry in the zip file.  I'm using pointers instead
-     * of objects because it's easier than making operator= work for the
-     * classes and sub-classes.
-     */
-    Vector<ZipEntry*>   mEntries;
-};
-
-}; // namespace android
-
-#endif // __LIBS_ZIPFILE_H
diff --git a/include/utils/executablepath.h b/include/utils/executablepath.h
deleted file mode 100644
index c979432..0000000
--- a/include/utils/executablepath.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef _UTILS_EXECUTABLEPATH_H
-#define _UTILS_EXECUTABLEPATH_H
-
-#include <limits.h>
-
-// returns the path to this executable
-#if __cplusplus
-extern "C"
-#endif
-void executablepath(char s[PATH_MAX]);
-
-#endif // _UTILS_EXECUTABLEPATH_H
diff --git a/include/utils/inet_address.h b/include/utils/inet_address.h
deleted file mode 100644
index dbd8672..0000000
--- a/include/utils/inet_address.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (C) 2005 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.
- */
-
-//
-// Internet address classes.  Modeled after Java classes.
-//
-#ifndef _RUNTIME_INET_ADDRESS_H
-#define _RUNTIME_INET_ADDRESS_H
-
-#ifdef HAVE_ANDROID_OS
-#error DO NOT USE THIS FILE IN THE DEVICE BUILD
-#endif
-
-
-namespace android {
-
-/*
- * This class holds Internet addresses.  Perhaps more useful is its
- * ability to look up addresses by name.
- *
- * Invoke one of the static factory methods to create a new object.
- */
-class InetAddress {
-public:
-    virtual ~InetAddress(void);
-
-    // create from w.x.y.z or foo.bar.com notation
-    static InetAddress* getByName(const char* host);
-
-    // copy-construction
-    InetAddress(const InetAddress& orig);
-
-    const void* getAddress(void) const { return mAddress; }
-    int getAddressLength(void) const { return mLength; }
-    const char* getHostName(void) const { return mName; }
-
-private:
-    InetAddress(void);
-    // assignment (private)
-    InetAddress& operator=(const InetAddress& addr);
-
-    // use a void* here so we don't have to expose actual socket headers
-    void*       mAddress;   // this is really a ptr to sockaddr_in
-    int         mLength;
-    char*       mName;
-};
-
-
-/*
- * Base class for socket addresses.
- */
-class SocketAddress {
-public:
-    SocketAddress() {}
-    virtual ~SocketAddress() {}
-};
-
-
-/*
- * Internet address class.  This combines an InetAddress with a port.
- */
-class InetSocketAddress : public SocketAddress {
-public:
-    InetSocketAddress() :
-        mAddress(0), mPort(-1)
-        {}
-    ~InetSocketAddress(void) {
-        delete mAddress;
-    }
-
-    // Create an address with a host wildcard (useful for servers).
-    bool create(int port);
-    // Create an address with the specified host and port.
-    bool create(const InetAddress* addr, int port);
-    // Create an address with the specified host and port.  Does the
-    // hostname lookup.
-    bool create(const char* host, int port);
-
-    const InetAddress* getAddress(void) const { return mAddress; }
-    const int getPort(void) const { return mPort; }
-    const char* getHostName(void) const { return mAddress->getHostName(); }
-
-private:
-    InetAddress* mAddress;
-    int         mPort;
-};
-
-}; // namespace android
-
-#endif // _RUNTIME_INET_ADDRESS_H
diff --git a/include/utils/misc.h b/include/utils/misc.h
index 62e84b4..23f2a4c 100644
--- a/include/utils/misc.h
+++ b/include/utils/misc.h
@@ -21,7 +21,7 @@
 #define _LIBS_UTILS_MISC_H
 
 #include <sys/time.h>
-#include "utils/Endian.h"
+#include <utils/Endian.h>
 
 namespace android {
 
diff --git a/include/utils/ported.h b/include/utils/ported.h
deleted file mode 100644
index eb3be01..0000000
--- a/include/utils/ported.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2005 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.
- */
-
-//
-// Standard functions ported to the current platform.  Note these are NOT
-// in the "android" namespace.
-//
-#ifndef _LIBS_UTILS_PORTED_H
-#define _LIBS_UTILS_PORTED_H
-
-#include <sys/time.h>       // for timeval
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* library replacement functions */
-#if defined(NEED_GETTIMEOFDAY)
-int gettimeofday(struct timeval* tv, struct timezone* tz);
-#endif
-#if defined(NEED_USLEEP)
-void usleep(unsigned long usec);
-#endif
-#if defined(NEED_PIPE)
-int pipe(int filedes[2]);
-#endif
-#if defined(NEED_SETENV)
-int setenv(const char* name, const char* value, int overwrite);
-void unsetenv(const char* name);
-char* getenv(const char* name);
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // _LIBS_UTILS_PORTED_H
diff --git a/include/utils/string_array.h b/include/utils/string_array.h
deleted file mode 100644
index 064dda2..0000000
--- a/include/utils/string_array.h
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (C) 2005 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.
- */
-
-//
-// Sortable array of strings.  STL-ish, but STL-free.
-//  
-#ifndef _LIBS_UTILS_STRING_ARRAY_H
-#define _LIBS_UTILS_STRING_ARRAY_H
-
-#include <stdlib.h>
-#include <string.h>
-
-namespace android {
-
-//
-// An expanding array of strings.  Add, get, sort, delete.
-//
-class StringArray {
-public:
-    StringArray()
-        : mMax(0), mCurrent(0), mArray(NULL)
-        {}
-    virtual ~StringArray() {
-        for (int i = 0; i < mCurrent; i++)
-            delete[] mArray[i];
-        delete[] mArray;
-    }
-
-    //
-    // Add a string.  A copy of the string is made.
-    //
-    bool push_back(const char* str) {
-        if (mCurrent >= mMax) {
-            char** tmp;
-
-            if (mMax == 0)
-                mMax = 16;      // initial storage
-            else
-                mMax *= 2;
-
-            tmp = new char*[mMax];
-            if (tmp == NULL)
-                return false;
-
-            memcpy(tmp, mArray, mCurrent * sizeof(char*));
-            delete[] mArray;
-            mArray = tmp;
-        }
-
-        int len = strlen(str);
-        mArray[mCurrent] = new char[len+1];
-        memcpy(mArray[mCurrent], str, len+1);
-        mCurrent++;
-
-        return true;
-    }
-
-    //
-    // Delete an entry.
-    //
-    void erase(int idx) {
-        if (idx < 0 || idx >= mCurrent)
-            return;
-        delete[] mArray[idx];
-        if (idx < mCurrent-1) {
-            memmove(&mArray[idx], &mArray[idx+1],
-                (mCurrent-1 - idx) * sizeof(char*));
-        }
-        mCurrent--;
-    }
-
-    //
-    // Sort the array.
-    //
-    void sort(int (*compare)(const void*, const void*)) {
-        qsort(mArray, mCurrent, sizeof(char*), compare);
-    }
-
-    //
-    // Pass this to the sort routine to do an ascending alphabetical sort.
-    //
-    static int cmpAscendingAlpha(const void* pstr1, const void* pstr2) {
-        return strcmp(*(const char**)pstr1, *(const char**)pstr2);
-    }
-
-    //
-    // Get the #of items in the array.
-    //
-    inline int size(void) const { return mCurrent; }
-
-    //
-    // Return entry N.
-    // [should use operator[] here]
-    //
-    const char* getEntry(int idx) const {
-        if (idx < 0 || idx >= mCurrent)
-            return NULL;
-        return mArray[idx];
-    }
-
-    //
-    // Set entry N to specified string.
-    // [should use operator[] here]
-    //
-    void setEntry(int idx, const char* str) {
-        if (idx < 0 || idx >= mCurrent)
-            return;
-        delete[] mArray[idx];
-        int len = strlen(str);
-        mArray[idx] = new char[len+1];
-        memcpy(mArray[idx], str, len+1);
-    }
-
-private:
-    int     mMax;
-    int     mCurrent;
-    char**  mArray;
-};
-
-}; // namespace android
-
-#endif // _LIBS_UTILS_STRING_ARRAY_H
diff --git a/include/utils/threads.h b/include/utils/threads.h
index b320915..0fc533f 100644
--- a/include/utils/threads.h
+++ b/include/utils/threads.h
@@ -21,6 +21,10 @@
 #include <sys/types.h>
 #include <time.h>
 
+#if defined(HAVE_PTHREADS)
+# include <pthread.h>
+#endif
+
 // ------------------------------------------------------------------
 // C API
 
@@ -176,6 +180,8 @@
     return androidGetThreadId();
 }
 
+/*****************************************************************************/
+
 /*
  * Simple mutex class.  The implementation is system-dependent.
  *
@@ -184,8 +190,14 @@
  */
 class Mutex {
 public:
+    enum {
+        NORMAL = 0,
+        SHARED = 1
+    };
+    
                 Mutex();
                 Mutex(const char* name);
+                Mutex(int type, const char* name = NULL);
                 ~Mutex();
 
     // lock or unlock the mutex
@@ -199,11 +211,11 @@
     // constructed and released when Autolock goes out of scope.
     class Autolock {
     public:
-        inline Autolock(Mutex& mutex) : mpMutex(&mutex) { mutex.lock(); }
-        inline Autolock(Mutex* mutex) : mpMutex(mutex) { mutex->lock(); }
-        inline ~Autolock() { mpMutex->unlock(); }
+        inline Autolock(Mutex& mutex) : mLock(mutex)  { mLock.lock(); }
+        inline Autolock(Mutex* mutex) : mLock(*mutex) { mLock.lock(); }
+        inline ~Autolock() { mLock.unlock(); }
     private:
-        Mutex*  mpMutex;
+        Mutex& mLock;
     };
 
 private:
@@ -212,11 +224,49 @@
     // A mutex cannot be copied
                 Mutex(const Mutex&);
     Mutex&      operator = (const Mutex&);
-    void        _init();
     
+#if defined(HAVE_PTHREADS)
+    pthread_mutex_t mMutex;
+#else
+    void    _init();
     void*   mState;
+#endif
 };
 
+#if defined(HAVE_PTHREADS)
+
+inline Mutex::Mutex() {
+    pthread_mutex_init(&mMutex, NULL);
+}
+inline Mutex::Mutex(const char* name) {
+    pthread_mutex_init(&mMutex, NULL);
+}
+inline Mutex::Mutex(int type, const char* name) {
+    if (type == SHARED) {
+        pthread_mutexattr_t attr;
+        pthread_mutexattr_init(&attr);
+        pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
+        pthread_mutex_init(&mMutex, &attr);
+        pthread_mutexattr_destroy(&attr);
+    } else {
+        pthread_mutex_init(&mMutex, NULL);
+    }
+}
+inline Mutex::~Mutex() {
+    pthread_mutex_destroy(&mMutex);
+}
+inline status_t Mutex::lock() {
+    return -pthread_mutex_lock(&mMutex);
+}
+inline void Mutex::unlock() {
+    pthread_mutex_unlock(&mMutex);
+}
+inline status_t Mutex::tryLock() {
+    return -pthread_mutex_trylock(&mMutex);
+}
+
+#endif // HAVE_PTHREADS
+
 /*
  * Automatic mutex.  Declare one of these at the top of a function.
  * When the function returns, it will go out of scope, and release the
@@ -225,6 +275,7 @@
  
 typedef Mutex::Autolock AutoMutex;
 
+/*****************************************************************************/
 
 /*
  * Condition variable class.  The implementation is system-dependent.
@@ -240,9 +291,6 @@
     ~Condition();
     // Wait on the condition variable.  Lock the mutex before calling.
     status_t wait(Mutex& mutex);
-    // Wait on the condition variable until the given time.  Lock the mutex
-    // before calling.
-    status_t wait(Mutex& mutex, nsecs_t abstime);
     // same with relative timeout
     status_t waitRelative(Mutex& mutex, nsecs_t reltime);
     // Signal the condition variable, allowing one thread to continue.
@@ -251,9 +299,60 @@
     void broadcast();
 
 private:
+#if defined(HAVE_PTHREADS)
+    pthread_cond_t mCond;
+#else
     void*   mState;
+#endif
 };
 
+#if defined(HAVE_PTHREADS)
+
+inline Condition::Condition() {
+    pthread_cond_init(&mCond, NULL);
+}
+inline Condition::~Condition() {
+    pthread_cond_destroy(&mCond);
+}
+inline status_t Condition::wait(Mutex& mutex) {
+    return -pthread_cond_wait(&mCond, &mutex.mMutex);
+}
+inline status_t Condition::waitRelative(Mutex& mutex, nsecs_t reltime) {
+#if defined(HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE)
+    struct timespec ts;
+    ts.tv_sec  = reltime/1000000000;
+    ts.tv_nsec = reltime%1000000000;
+    return -pthread_cond_timedwait_relative_np(&mCond, &mutex.mMutex, &ts);
+#else // HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE
+    struct timespec ts;
+#if defined(HAVE_POSIX_CLOCKS)
+    clock_gettime(CLOCK_REALTIME, &ts);
+#else // HAVE_POSIX_CLOCKS
+    // we don't support the clocks here.
+    struct timeval t;
+    gettimeofday(&t, NULL);
+    ts.tv_sec = t.tv_sec;
+    ts.tv_nsec= t.tv_usec*1000;
+#endif // HAVE_POSIX_CLOCKS
+    ts.tv_sec += reltime/1000000000;
+    ts.tv_nsec+= reltime%1000000000;
+    if (ts.tv_nsec >= 1000000000) {
+        ts.tv_nsec -= 1000000000;
+        ts.tv_sec  += 1;
+    }
+    return -pthread_cond_timedwait(&mCond, &mutex.mMutex, &ts);
+#endif // HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE
+}
+inline void Condition::signal() {
+    pthread_cond_signal(&mCond);
+}
+inline void Condition::broadcast() {
+    pthread_cond_broadcast(&mCond);
+}
+
+#endif // HAVE_PTHREADS
+
+/*****************************************************************************/
 
 /*
  * This is our spiffy thread object!
@@ -291,7 +390,7 @@
             bool        exitPending() const;
     
 private:
-    // Derived class must implemtent threadLoop(). The thread starts its life
+    // Derived class must implement threadLoop(). The thread starts its life
     // here. There are two ways of using the Thread object:
     // 1) loop: if threadLoop() returns true, it will be called again if
     //          requestExit() wasn't called.
@@ -309,6 +408,9 @@
     volatile bool           mExitPending;
     volatile bool           mRunning;
             sp<Thread>      mHoldSelf;
+#if HAVE_ANDROID_OS
+            int             mTid;
+#endif
 };
 
 
diff --git a/libs/audioflinger/A2dpAudioInterface.cpp b/libs/audioflinger/A2dpAudioInterface.cpp
index 16a4f2d..351815b 100644
--- a/libs/audioflinger/A2dpAudioInterface.cpp
+++ b/libs/audioflinger/A2dpAudioInterface.cpp
@@ -16,7 +16,7 @@
 
 #include <math.h>
 
-#define LOG_NDEBUG 0
+//#define LOG_NDEBUG 0
 #define LOG_TAG "A2dpAudioInterface"
 #include <utils/Log.h>
 #include <utils/String8.h>
@@ -29,25 +29,41 @@
 
 // ----------------------------------------------------------------------------
 
-A2dpAudioInterface::A2dpAudioInterface() :
-    mOutput(0)
+//AudioHardwareInterface* A2dpAudioInterface::createA2dpInterface()
+//{
+//    AudioHardwareInterface* hw = 0;
+//
+//    hw = AudioHardwareInterface::create();
+//    LOGD("new A2dpAudioInterface(hw: %p)", hw);
+//    hw = new A2dpAudioInterface(hw);
+//    return hw;
+//}
+
+A2dpAudioInterface::A2dpAudioInterface(AudioHardwareInterface* hw) :
+    mOutput(0), mHardwareInterface(hw), mBluetoothEnabled(true), mSuspended(false)
 {
 }
 
 A2dpAudioInterface::~A2dpAudioInterface()
 {
-    delete mOutput;
+    closeOutputStream((AudioStreamOut *)mOutput);
+    delete mHardwareInterface;
 }
 
 status_t A2dpAudioInterface::initCheck()
 {
-    return 0;
+    if (mHardwareInterface == 0) return NO_INIT;
+    return mHardwareInterface->initCheck();
 }
 
 AudioStreamOut* A2dpAudioInterface::openOutputStream(
-        int format, int channelCount, uint32_t sampleRate, status_t *status)
+        uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status)
 {
-    LOGD("A2dpAudioInterface::openOutputStream %d, %d, %d\n", format, channelCount, sampleRate);
+    if (!AudioSystem::isA2dpDevice((AudioSystem::audio_devices)devices)) {
+        LOGV("A2dpAudioInterface::openOutputStream() open HW device: %x", devices);
+        return mHardwareInterface->openOutputStream(devices, format, channels, sampleRate, status);
+    }
+
     status_t err = 0;
 
     // only one output stream allowed
@@ -59,71 +75,142 @@
 
     // create new output stream
     A2dpAudioStreamOut* out = new A2dpAudioStreamOut();
-    if ((err = out->set(format, channelCount, sampleRate)) == NO_ERROR) {
+    if ((err = out->set(devices, format, channels, sampleRate)) == NO_ERROR) {
         mOutput = out;
+        mOutput->setBluetoothEnabled(mBluetoothEnabled);
+        mOutput->setSuspended(mSuspended);
     } else {
         delete out;
     }
-    
+
     if (status)
         *status = err;
     return mOutput;
 }
 
+void A2dpAudioInterface::closeOutputStream(AudioStreamOut* out) {
+    if (mOutput == 0 || mOutput != out) {
+        mHardwareInterface->closeOutputStream(out);
+    }
+    else {
+        delete mOutput;
+        mOutput = 0;
+    }
+}
+
+
 AudioStreamIn* A2dpAudioInterface::openInputStream(
-        int inputSource, int format, int channelCount, uint32_t sampleRate,
-        status_t *status, AudioSystem::audio_in_acoustics acoustics)
+        uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status,
+        AudioSystem::audio_in_acoustics acoustics)
 {
-    if (status)
-        *status = -1;
-    return NULL;
+    return mHardwareInterface->openInputStream(devices, format, channels, sampleRate, status, acoustics);
+}
+
+void A2dpAudioInterface::closeInputStream(AudioStreamIn* in)
+{
+    return mHardwareInterface->closeInputStream(in);
+}
+
+status_t A2dpAudioInterface::setMode(int mode)
+{
+    return mHardwareInterface->setMode(mode);
 }
 
 status_t A2dpAudioInterface::setMicMute(bool state)
 {
-    return 0;
+    return mHardwareInterface->setMicMute(state);
 }
 
 status_t A2dpAudioInterface::getMicMute(bool* state)
 {
-    return 0;
+    return mHardwareInterface->getMicMute(state);
 }
 
-status_t A2dpAudioInterface::setParameter(const char *key, const char *value)
+status_t A2dpAudioInterface::setParameters(const String8& keyValuePairs)
 {
-    LOGD("setParameter %s,%s\n", key, value);
+    AudioParameter param = AudioParameter(keyValuePairs);
+    String8 value;
+    String8 key;
+    status_t status = NO_ERROR;
 
-    if (!key || !value)
-        return -EINVAL;
+    LOGV("setParameters() %s", keyValuePairs.string());
 
-    if (strcmp(key, "a2dp_sink_address") == 0) {
-        return mOutput->setAddress(value);
+    key = "bluetooth_enabled";
+    if (param.get(key, value) == NO_ERROR) {
+        mBluetoothEnabled = (value == "true");
+        if (mOutput) {
+            mOutput->setBluetoothEnabled(mBluetoothEnabled);
+        }
+        param.remove(key);
     }
-    if (strcmp(key, "bluetooth_enabled") == 0) {
-        mOutput->setBluetoothEnabled(strcmp(value, "true") == 0);
+    key = String8("A2dpSuspended");
+    if (param.get(key, value) == NO_ERROR) {
+        mSuspended = (value == "true");
+        if (mOutput) {
+            mOutput->setSuspended(mSuspended);
+        }
+        param.remove(key);
     }
 
-    return 0;
+    if (param.size()) {
+        status_t hwStatus = mHardwareInterface->setParameters(param.toString());
+        if (status == NO_ERROR) {
+            status = hwStatus;
+        }
+    }
+
+    return status;
+}
+
+String8 A2dpAudioInterface::getParameters(const String8& keys)
+{
+    AudioParameter param = AudioParameter(keys);
+    AudioParameter a2dpParam = AudioParameter();
+    String8 value;
+    String8 key;
+
+    key = "bluetooth_enabled";
+    if (param.get(key, value) == NO_ERROR) {
+        value = mBluetoothEnabled ? "true" : "false";
+        a2dpParam.add(key, value);
+        param.remove(key);
+    }
+    key = "A2dpSuspended";
+    if (param.get(key, value) == NO_ERROR) {
+        value = mSuspended ? "true" : "false";
+        a2dpParam.add(key, value);
+        param.remove(key);
+    }
+
+    String8 keyValuePairs  = a2dpParam.toString();
+
+    if (param.size()) {
+        keyValuePairs += ";";
+        keyValuePairs += mHardwareInterface->getParameters(param.toString());
+    }
+
+    LOGV("getParameters() %s", keyValuePairs.string());
+    return keyValuePairs;
+}
+
+size_t A2dpAudioInterface::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
+{
+    return mHardwareInterface->getInputBufferSize(sampleRate, format, channelCount);
 }
 
 status_t A2dpAudioInterface::setVoiceVolume(float v)
 {
-    return 0;
+    return mHardwareInterface->setVoiceVolume(v);
 }
 
 status_t A2dpAudioInterface::setMasterVolume(float v)
 {
-    return 0;
-}
-
-status_t A2dpAudioInterface::doRouting()
-{
-    return 0;
+    return mHardwareInterface->setMasterVolume(v);
 }
 
 status_t A2dpAudioInterface::dump(int fd, const Vector<String16>& args)
 {
-    return 0;
+    return mHardwareInterface->dumpState(fd, args);
 }
 
 // ----------------------------------------------------------------------------
@@ -132,7 +219,7 @@
     mFd(-1), mStandby(true), mStartCount(0), mRetryCount(0), mData(NULL),
     // assume BT enabled to start, this is safe because its only the
     // enabled->disabled transition we are worried about
-    mBluetoothEnabled(true)
+    mBluetoothEnabled(true), mDevice(0), mClosing(false), mSuspended(false)
 {
     // use any address by default
     strcpy(mA2dpAddress, "00:00:00:00:00:00");
@@ -140,27 +227,43 @@
 }
 
 status_t A2dpAudioInterface::A2dpAudioStreamOut::set(
-        int format, int channels, uint32_t rate)
+        uint32_t device, int *pFormat, uint32_t *pChannels, uint32_t *pRate)
 {
-    LOGD("A2dpAudioStreamOut::set %d, %d, %d\n", format, channels, rate);
+    int lFormat = pFormat ? *pFormat : 0;
+    uint32_t lChannels = pChannels ? *pChannels : 0;
+    uint32_t lRate = pRate ? *pRate : 0;
+
+    LOGD("A2dpAudioStreamOut::set %x, %d, %d, %d\n", device, lFormat, lChannels, lRate);
 
     // fix up defaults
-    if (format == 0) format = AudioSystem::PCM_16_BIT;
-    if (channels == 0) channels = channelCount();
-    if (rate == 0) rate = sampleRate();
+    if (lFormat == 0) lFormat = format();
+    if (lChannels == 0) lChannels = channels();
+    if (lRate == 0) lRate = sampleRate();
 
     // check values
-    if ((format != AudioSystem::PCM_16_BIT) ||
-            (channels != channelCount()) ||
-            (rate != sampleRate()))
+    if ((lFormat != format()) ||
+            (lChannels != channels()) ||
+            (lRate != sampleRate())){
+        if (pFormat) *pFormat = format();
+        if (pChannels) *pChannels = channels();
+        if (pRate) *pRate = sampleRate();
         return BAD_VALUE;
+    }
 
+    if (pFormat) *pFormat = lFormat;
+    if (pChannels) *pChannels = lChannels;
+    if (pRate) *pRate = lRate;
+
+    mDevice = device;
     return NO_ERROR;
 }
 
 A2dpAudioInterface::A2dpAudioStreamOut::~A2dpAudioStreamOut()
 {
+    LOGV("A2dpAudioStreamOut destructor");
+    standby();
     close();
+    LOGV("A2dpAudioStreamOut destructor returning from close()");
 }
 
 ssize_t A2dpAudioInterface::A2dpAudioStreamOut::write(const void* buffer, size_t bytes)
@@ -170,8 +273,10 @@
     size_t remaining = bytes;
     status_t status = -1;
 
-    if (!mBluetoothEnabled) {
-        LOGW("A2dpAudioStreamOut::write(), but bluetooth disabled");
+    if (!mBluetoothEnabled || mClosing || mSuspended) {
+        LOGV("A2dpAudioStreamOut::write(), but bluetooth disabled \
+               mBluetoothEnabled %d, mClosing %d, mSuspended %d",
+                mBluetoothEnabled, mClosing, mSuspended);
         goto Error;
     }
 
@@ -219,6 +324,11 @@
 {
     int result = 0;
 
+    if (mClosing) {
+        LOGV("Ignore standby, closing");
+        return result;
+    }
+
     Mutex::Autolock lock(mLock);
 
     if (!mStandby) {
@@ -230,6 +340,64 @@
     return result;
 }
 
+status_t A2dpAudioInterface::A2dpAudioStreamOut::setParameters(const String8& keyValuePairs)
+{
+    AudioParameter param = AudioParameter(keyValuePairs);
+    String8 value;
+    String8 key = String8("a2dp_sink_address");
+    status_t status = NO_ERROR;
+    int device;
+    LOGV("A2dpAudioStreamOut::setParameters() %s", keyValuePairs.string());
+
+    if (param.get(key, value) == NO_ERROR) {
+        if (value.length() != strlen("00:00:00:00:00:00")) {
+            status = BAD_VALUE;
+        } else {
+            setAddress(value.string());
+        }
+        param.remove(key);
+    }
+    key = String8("closing");
+    if (param.get(key, value) == NO_ERROR) {
+        mClosing = (value == "true");
+        param.remove(key);
+    }
+    key = AudioParameter::keyRouting;
+    if (param.getInt(key, device) == NO_ERROR) {
+        if (AudioSystem::isA2dpDevice((AudioSystem::audio_devices)device)) {
+            mDevice = device;
+            status = NO_ERROR;
+        } else {
+            status = BAD_VALUE;
+        }
+        param.remove(key);
+    }
+
+    if (param.size()) {
+        status = BAD_VALUE;
+    }
+    return status;
+}
+
+String8 A2dpAudioInterface::A2dpAudioStreamOut::getParameters(const String8& keys)
+{
+    AudioParameter param = AudioParameter(keys);
+    String8 value;
+    String8 key = String8("a2dp_sink_address");
+
+    if (param.get(key, value) == NO_ERROR) {
+        value = mA2dpAddress;
+        param.add(key, value);
+    }
+    key = AudioParameter::keyRouting;
+    if (param.get(key, value) == NO_ERROR) {
+        param.addInt(key, (int)mDevice);
+    }
+
+    LOGV("A2dpAudioStreamOut::getParameters() %s", param.toString().string());
+    return param.toString();
+}
+
 status_t A2dpAudioInterface::A2dpAudioStreamOut::setAddress(const char* address)
 {
     Mutex::Autolock lock(mLock);
@@ -257,15 +425,25 @@
     return NO_ERROR;
 }
 
+status_t A2dpAudioInterface::A2dpAudioStreamOut::setSuspended(bool onOff)
+{
+    LOGV("setSuspended %d", onOff);
+    mSuspended = onOff;
+    standby();
+    return NO_ERROR;
+}
+
 status_t A2dpAudioInterface::A2dpAudioStreamOut::close()
 {
     Mutex::Autolock lock(mLock);
+    LOGV("A2dpAudioStreamOut::close() calling close_l()");
     return close_l();
 }
 
 status_t A2dpAudioInterface::A2dpAudioStreamOut::close_l()
 {
     if (mData) {
+        LOGV("A2dpAudioStreamOut::close_l() calling a2dp_cleanup(mData)");
         a2dp_cleanup(mData);
         mData = NULL;
     }
@@ -277,5 +455,4 @@
     return NO_ERROR;
 }
 
-
 }; // namespace android
diff --git a/libs/audioflinger/A2dpAudioInterface.h b/libs/audioflinger/A2dpAudioInterface.h
index 091e775..530e432 100644
--- a/libs/audioflinger/A2dpAudioInterface.h
+++ b/libs/audioflinger/A2dpAudioInterface.h
@@ -32,38 +32,44 @@
     class A2dpAudioStreamOut;
 
 public:
-                        A2dpAudioInterface();
+                        A2dpAudioInterface(AudioHardwareInterface* hw);
     virtual             ~A2dpAudioInterface();
     virtual status_t    initCheck();
 
     virtual status_t    setVoiceVolume(float volume);
     virtual status_t    setMasterVolume(float volume);
 
+    virtual status_t    setMode(int mode);
+
     // mic mute
     virtual status_t    setMicMute(bool state);
     virtual status_t    getMicMute(bool* state);
 
-    // Temporary interface, do not use
-    // TODO: Replace with a more generic key:value get/set mechanism
-    virtual status_t    setParameter(const char *key, const char *value);
+    virtual status_t    setParameters(const String8& keyValuePairs);
+    virtual String8     getParameters(const String8& keys);
+
+    virtual size_t      getInputBufferSize(uint32_t sampleRate, int format, int channelCount);
 
     // create I/O streams
     virtual AudioStreamOut* openOutputStream(
-                                int format=0,
-                                int channelCount=0,
-                                uint32_t sampleRate=0,
+                                uint32_t devices,
+                                int *format=0,
+                                uint32_t *channels=0,
+                                uint32_t *sampleRate=0,
                                 status_t *status=0);
+    virtual    void        closeOutputStream(AudioStreamOut* out);
 
     virtual AudioStreamIn* openInputStream(
-                                int inputSource,
-                                int format,
-                                int channelCount,
-                                uint32_t sampleRate,
+                                uint32_t devices,
+                                int *format,
+                                uint32_t *channels,
+                                uint32_t *sampleRate,
                                 status_t *status,
                                 AudioSystem::audio_in_acoustics acoustics);
+    virtual    void        closeInputStream(AudioStreamIn* in);
+//    static AudioHardwareInterface* createA2dpInterface();
 
 protected:
-    virtual status_t    doRouting();
     virtual status_t    dump(int fd, const Vector<String16>& args);
 
 private:
@@ -71,19 +77,22 @@
     public:
                             A2dpAudioStreamOut();
         virtual             ~A2dpAudioStreamOut();
-                status_t    set(int format,
-                                int channelCount,
-                                uint32_t sampleRate);
+                status_t    set(uint32_t device,
+                                int *pFormat,
+                                uint32_t *pChannels,
+                                uint32_t *pRate);
         virtual uint32_t    sampleRate() const { return 44100; }
         // SBC codec wants a multiple of 512
         virtual size_t      bufferSize() const { return 512 * 20; }
-        virtual int         channelCount() const { return 2; }
+        virtual uint32_t    channels() const { return AudioSystem::CHANNEL_OUT_STEREO; }
         virtual int         format() const { return AudioSystem::PCM_16_BIT; }
         virtual uint32_t    latency() const { return ((1000*bufferSize())/frameSize())/sampleRate() + 200; }
-        virtual status_t    setVolume(float volume) { return INVALID_OPERATION; }
+        virtual status_t    setVolume(float left, float right) { return INVALID_OPERATION; }
         virtual ssize_t     write(const void* buffer, size_t bytes);
                 status_t    standby();
         virtual status_t    dump(int fd, const Vector<String16>& args);
+        virtual status_t    setParameters(const String8& keyValuePairs);
+        virtual String8     getParameters(const String8& keys);
 
     private:
         friend class A2dpAudioInterface;
@@ -92,6 +101,7 @@
                 status_t    close_l();
                 status_t    setAddress(const char* address);
                 status_t    setBluetoothEnabled(bool enabled);
+                status_t    setSuspended(bool onOff);
 
     private:
                 int         mFd;
@@ -102,11 +112,21 @@
                 void*       mData;
                 Mutex       mLock;
                 bool        mBluetoothEnabled;
+                uint32_t    mDevice;
+                bool        mClosing;
+                bool        mSuspended;
     };
 
+    friend class A2dpAudioStreamOut;
+
     A2dpAudioStreamOut*     mOutput;
+    AudioHardwareInterface  *mHardwareInterface;
+    char        mA2dpAddress[20];
+    bool        mBluetoothEnabled;
+    bool        mSuspended;
 };
 
+
 // ----------------------------------------------------------------------------
 
 }; // namespace android
diff --git a/libs/audioflinger/Android.mk b/libs/audioflinger/Android.mk
index 50d516b..f5c03bb 100644
--- a/libs/audioflinger/Android.mk
+++ b/libs/audioflinger/Android.mk
@@ -1,16 +1,30 @@
 LOCAL_PATH:= $(call my-dir)
 
+#AUDIO_POLICY_TEST := true
+#ENABLE_AUDIO_DUMP := true
+
 include $(CLEAR_VARS)
 
+
+ifeq ($(AUDIO_POLICY_TEST),true)
+  ENABLE_AUDIO_DUMP := true
+endif
+
+
 LOCAL_SRC_FILES:= \
     AudioHardwareGeneric.cpp \
     AudioHardwareStub.cpp \
-    AudioDumpInterface.cpp \
     AudioHardwareInterface.cpp
 
+ifeq ($(ENABLE_AUDIO_DUMP),true)
+  LOCAL_SRC_FILES += AudioDumpInterface.cpp
+  LOCAL_CFLAGS += -DENABLE_AUDIO_DUMP
+endif
+
 LOCAL_SHARED_LIBRARIES := \
     libcutils \
     libutils \
+	libbinder \
     libmedia \
     libhardware_legacy
 
@@ -20,8 +34,44 @@
 
 LOCAL_MODULE:= libaudiointerface
 
+ifeq ($(BOARD_HAVE_BLUETOOTH),true)
+  LOCAL_SRC_FILES += A2dpAudioInterface.cpp
+  LOCAL_SHARED_LIBRARIES += liba2dp
+  LOCAL_CFLAGS += -DWITH_BLUETOOTH -DWITH_A2DP
+  LOCAL_C_INCLUDES += $(call include-path-for, bluez)
+endif
+
 include $(BUILD_STATIC_LIBRARY)
 
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:=               \
+    AudioPolicyManagerGeneric.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+    libcutils \
+    libutils \
+    libmedia
+
+ifeq ($(TARGET_SIMULATOR),true)
+ LOCAL_LDLIBS += -ldl
+else
+ LOCAL_SHARED_LIBRARIES += libdl
+endif
+
+LOCAL_MODULE:= libaudiopolicygeneric
+
+ifeq ($(BOARD_HAVE_BLUETOOTH),true)
+  LOCAL_CFLAGS += -DWITH_A2DP
+endif
+
+ifeq ($(AUDIO_POLICY_TEST),true)
+  LOCAL_CFLAGS += -DAUDIO_POLICY_TEST
+endif
+
+include $(BUILD_SHARED_LIBRARY)
+
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:=               \
@@ -29,28 +79,45 @@
     AudioMixer.cpp.arm          \
     AudioResampler.cpp.arm      \
     AudioResamplerSinc.cpp.arm  \
-    AudioResamplerCubic.cpp.arm
+    AudioResamplerCubic.cpp.arm \
+    AudioPolicyService.cpp
 
 LOCAL_SHARED_LIBRARIES := \
     libcutils \
     libutils \
+	libbinder \
     libmedia \
-    libhardware_legacy
+    libhardware_legacy \
+    libaudiopolicygeneric
 
 ifeq ($(strip $(BOARD_USES_GENERIC_AUDIO)),true)
   LOCAL_STATIC_LIBRARIES += libaudiointerface
+  LOCAL_CFLAGS += -DGENERIC_AUDIO
 else
-  LOCAL_SHARED_LIBRARIES += libaudio
+  LOCAL_SHARED_LIBRARIES += libaudio libaudiopolicy
+endif
+
+ifeq ($(TARGET_SIMULATOR),true)
+ LOCAL_LDLIBS += -ldl
+else
+ LOCAL_SHARED_LIBRARIES += libdl
 endif
 
 LOCAL_MODULE:= libaudioflinger
 
 ifeq ($(BOARD_HAVE_BLUETOOTH),true)
-  LOCAL_SRC_FILES += A2dpAudioInterface.cpp
-  LOCAL_SHARED_LIBRARIES += liba2dp
   LOCAL_CFLAGS += -DWITH_BLUETOOTH -DWITH_A2DP
-  LOCAL_C_INCLUDES += $(call include-path-for, bluez-libs)
-  LOCAL_C_INCLUDES += $(call include-path-for, bluez-utils)
+  LOCAL_SHARED_LIBRARIES += liba2dp
+endif
+
+ifeq ($(AUDIO_POLICY_TEST),true)
+  LOCAL_CFLAGS += -DAUDIO_POLICY_TEST
+endif
+
+ifeq ($(TARGET_SIMULATOR),true)
+	ifeq ($(HOST_OS),linux)
+		LOCAL_LDLIBS += -lrt -lpthread
+	endif
 endif
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/libs/audioflinger/AudioDumpInterface.cpp b/libs/audioflinger/AudioDumpInterface.cpp
index b4940cb..858e5aa 100644
--- a/libs/audioflinger/AudioDumpInterface.cpp
+++ b/libs/audioflinger/AudioDumpInterface.cpp
@@ -16,6 +16,7 @@
 */
 
 #define LOG_TAG "AudioFlingerDump"
+//#define LOG_NDEBUG 0
 
 #include <stdint.h>
 #include <sys/types.h>
@@ -28,68 +29,240 @@
 
 namespace android {
 
-bool gFirst = true;       // true if first write after a standby
-
 // ----------------------------------------------------------------------------
 
 AudioDumpInterface::AudioDumpInterface(AudioHardwareInterface* hw)
+    : mFirstHwOutput(true), mPolicyCommands(String8("")), mFileName(String8(""))
 {
     if(hw == 0) {
         LOGE("Dump construct hw = 0");
     }
     mFinalInterface = hw;
-    mStreamOut = 0;
+    LOGV("Constructor %p, mFinalInterface %p", this, mFinalInterface);
 }
 
 
 AudioDumpInterface::~AudioDumpInterface()
 {
+    for (size_t i = 0; i < mOutputs.size(); i++) {
+        closeOutputStream((AudioStreamOut *)mOutputs[i]);
+    }
     if(mFinalInterface) delete mFinalInterface;
-    if(mStreamOut) delete mStreamOut;
 }
 
 
 AudioStreamOut* AudioDumpInterface::openOutputStream(
-        int format, int channelCount, uint32_t sampleRate, status_t *status)
+        uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status)
 {
-    AudioStreamOut* outFinal = mFinalInterface->openOutputStream(format, channelCount, sampleRate, status);
+    AudioStreamOut* outFinal = NULL;
+    int lFormat = AudioSystem::PCM_16_BIT;
+    uint32_t lChannels = AudioSystem::CHANNEL_OUT_STEREO;
+    uint32_t lRate = 44100;
 
-    if(outFinal) {
-        mStreamOut =  new AudioStreamOutDump(outFinal);
-        return mStreamOut;
+
+    if (AudioSystem::isA2dpDevice((AudioSystem::audio_devices)devices) || mFirstHwOutput) {
+        outFinal = mFinalInterface->openOutputStream(devices, format, channels, sampleRate, status);
+        if (outFinal != 0) {
+            lFormat = outFinal->format();
+            lChannels = outFinal->channels();
+            lRate = outFinal->sampleRate();
+            if (!AudioSystem::isA2dpDevice((AudioSystem::audio_devices)devices)) {
+                mFirstHwOutput = false;
+            }
+        }
     } else {
-        LOGE("Dump outFinal=0");
-        return 0;
+        if (format != 0 && *format != 0) {
+            lFormat = *format;
+        } else {
+            lFormat = AudioSystem::PCM_16_BIT;
+        }
+        if (channels != 0 && *channels != 0) {
+            lChannels = *channels;
+        } else {
+            lChannels = AudioSystem::CHANNEL_OUT_STEREO;
+        }
+        if (sampleRate != 0 && *sampleRate != 0) {
+            lRate = *sampleRate;
+        } else {
+            lRate = 44100;
+        }
+        if (status) *status = NO_ERROR;
     }
+    LOGV("openOutputStream(), outFinal %p", outFinal);
+
+    AudioStreamOutDump *dumOutput = new AudioStreamOutDump(this, mOutputs.size(), outFinal,
+            devices, lFormat, lChannels, lRate);
+    mOutputs.add(dumOutput);
+
+    return dumOutput;
 }
 
+void AudioDumpInterface::closeOutputStream(AudioStreamOut* out)
+{
+    AudioStreamOutDump *dumpOut = (AudioStreamOutDump *)out;
+
+    if (mOutputs.indexOf(dumpOut) < 0) {
+        LOGW("Attempt to close invalid output stream");
+        return;
+    }
+
+    LOGV("closeOutputStream() output %p", out);
+
+    dumpOut->standby();
+    if (dumpOut->finalStream() != NULL) {
+        mFinalInterface->closeOutputStream(dumpOut->finalStream());
+        mFirstHwOutput = true;
+    }
+
+    mOutputs.remove(dumpOut);
+    delete dumpOut;
+}
+
+AudioStreamIn* AudioDumpInterface::openInputStream(uint32_t devices, int *format, uint32_t *channels,
+        uint32_t *sampleRate, status_t *status, AudioSystem::audio_in_acoustics acoustics)
+{
+    AudioStreamIn* inFinal = NULL;
+    int lFormat = AudioSystem::PCM_16_BIT;
+    uint32_t lChannels = AudioSystem::CHANNEL_IN_MONO;
+    uint32_t lRate = 8000;
+
+
+    if (mInputs.size() == 0) {
+        inFinal = mFinalInterface->openInputStream(devices, format, channels, sampleRate, status, acoustics);
+        if (inFinal == 0) return 0;
+
+        lFormat = inFinal->format();
+        lChannels = inFinal->channels();
+        lRate = inFinal->sampleRate();
+    } else {
+        if (format != 0 && *format != 0) lFormat = *format;
+        if (channels != 0 && *channels != 0) lChannels = *channels;
+        if (sampleRate != 0 && *sampleRate != 0) lRate = *sampleRate;
+        if (status) *status = NO_ERROR;
+    }
+    LOGV("openInputStream(), inFinal %p", inFinal);
+
+    AudioStreamInDump *dumInput = new AudioStreamInDump(this, mInputs.size(), inFinal,
+            devices, lFormat, lChannels, lRate);
+    mInputs.add(dumInput);
+
+    return dumInput;
+}
+void AudioDumpInterface::closeInputStream(AudioStreamIn* in)
+{
+    AudioStreamInDump *dumpIn = (AudioStreamInDump *)in;
+
+    if (mInputs.indexOf(dumpIn) < 0) {
+        LOGW("Attempt to close invalid input stream");
+        return;
+    }
+    dumpIn->standby();
+    if (dumpIn->finalStream() != NULL) {
+        mFinalInterface->closeInputStream(dumpIn->finalStream());
+    }
+
+    mInputs.remove(dumpIn);
+    delete dumpIn;
+}
+
+
+status_t AudioDumpInterface::setParameters(const String8& keyValuePairs)
+{
+    AudioParameter param = AudioParameter(keyValuePairs);
+    String8 value;
+    int valueInt;
+    LOGV("setParameters %s", keyValuePairs.string());
+
+    if (param.get(String8("test_cmd_file_name"), value) == NO_ERROR) {
+        mFileName = value;
+        param.remove(String8("test_cmd_file_name"));
+    }
+    if (param.get(String8("test_cmd_policy"), value) == NO_ERROR) {
+        Mutex::Autolock _l(mLock);
+        param.remove(String8("test_cmd_policy"));
+        mPolicyCommands = param.toString();
+        LOGV("test_cmd_policy command %s written", mPolicyCommands.string());
+        return NO_ERROR;
+    }
+
+    if (mFinalInterface != 0 ) return mFinalInterface->setParameters(keyValuePairs);
+    return NO_ERROR;
+}
+
+String8 AudioDumpInterface::getParameters(const String8& keys)
+{
+    AudioParameter param = AudioParameter(keys);
+    AudioParameter response;
+    String8 value;
+
+//    LOGV("getParameters %s", keys.string());
+    if (param.get(String8("test_cmd_policy"), value) == NO_ERROR) {
+        Mutex::Autolock _l(mLock);
+        if (mPolicyCommands.length() != 0) {
+            response = AudioParameter(mPolicyCommands);
+            response.addInt(String8("test_cmd_policy"), 1);
+        } else {
+            response.addInt(String8("test_cmd_policy"), 0);
+        }
+        param.remove(String8("test_cmd_policy"));
+//        LOGV("test_cmd_policy command %s read", mPolicyCommands.string());
+    }
+
+    if (param.get(String8("test_cmd_file_name"), value) == NO_ERROR) {
+        response.add(String8("test_cmd_file_name"), mFileName);
+        param.remove(String8("test_cmd_file_name"));
+    }
+
+    String8 keyValuePairs = response.toString();
+
+    if (param.size() && mFinalInterface != 0 ) {
+        keyValuePairs += ";";
+        keyValuePairs += mFinalInterface->getParameters(param.toString());
+    }
+
+    return keyValuePairs;
+}
+
+
 // ----------------------------------------------------------------------------
 
-AudioStreamOutDump::AudioStreamOutDump( AudioStreamOut* finalStream)
+AudioStreamOutDump::AudioStreamOutDump(AudioDumpInterface *interface,
+                                        int id,
+                                        AudioStreamOut* finalStream,
+                                        uint32_t devices,
+                                        int format,
+                                        uint32_t channels,
+                                        uint32_t sampleRate)
+    : mInterface(interface), mId(id),
+      mSampleRate(sampleRate), mFormat(format), mChannels(channels), mLatency(0), mDevice(devices),
+      mBufferSize(1024), mFinalStream(finalStream), mOutFile(0), mFileCount(0)
 {
-    mFinalStream = finalStream;
-    mOutFile = 0;
+    LOGV("AudioStreamOutDump Constructor %p, mInterface %p, mFinalStream %p", this, mInterface, mFinalStream);
 }
 
 
 AudioStreamOutDump::~AudioStreamOutDump()
 {
+    LOGV("AudioStreamOutDump destructor");
     Close();
-    delete mFinalStream;
 }
 
 ssize_t AudioStreamOutDump::write(const void* buffer, size_t bytes)
 {
     ssize_t ret;
 
-    ret = mFinalStream->write(buffer, bytes);
-    if(!mOutFile && gFirst) {
-        gFirst = false;
-        // check if dump file exist
-        mOutFile = fopen(FLINGER_DUMP_NAME, "r");
-        if(mOutFile) {
-            fclose(mOutFile);
-            mOutFile = fopen(FLINGER_DUMP_NAME, "ab");
+    if (mFinalStream) {
+        ret = mFinalStream->write(buffer, bytes);
+    } else {
+        usleep((bytes * 1000000) / frameSize() / sampleRate());
+        ret = bytes;
+    }
+    if(!mOutFile) {
+        if (mInterface->fileName() != "") {
+            char name[255];
+            sprintf(name, "%s_%d_%d.pcm", mInterface->fileName().string(), mId, ++mFileCount);
+            mOutFile = fopen(name, "wb");
+            LOGV("Opening dump file %s, fh %p", name, mOutFile);
         }
     }
     if (mOutFile) {
@@ -100,13 +273,105 @@
 
 status_t AudioStreamOutDump::standby()
 {
+    LOGV("AudioStreamOutDump standby(), mOutFile %p, mFinalStream %p", mOutFile, mFinalStream);
+
     Close();
-    gFirst = true;
-    return mFinalStream->standby();
+    if (mFinalStream != 0 ) return mFinalStream->standby();
+    return NO_ERROR;
 }
 
+uint32_t AudioStreamOutDump::sampleRate() const
+{
+    if (mFinalStream != 0 ) return mFinalStream->sampleRate();
+    return mSampleRate;
+}
 
-void AudioStreamOutDump::Close(void)
+size_t AudioStreamOutDump::bufferSize() const
+{
+    if (mFinalStream != 0 ) return mFinalStream->bufferSize();
+    return mBufferSize;
+}
+
+uint32_t AudioStreamOutDump::channels() const
+{
+    if (mFinalStream != 0 ) return mFinalStream->channels();
+    return mChannels;
+}
+int AudioStreamOutDump::format() const
+{
+    if (mFinalStream != 0 ) return mFinalStream->format();
+    return mFormat;
+}
+uint32_t AudioStreamOutDump::latency() const
+{
+    if (mFinalStream != 0 ) return mFinalStream->latency();
+    return 0;
+}
+status_t AudioStreamOutDump::setVolume(float left, float right)
+{
+    if (mFinalStream != 0 ) return mFinalStream->setVolume(left, right);
+    return NO_ERROR;
+}
+status_t AudioStreamOutDump::setParameters(const String8& keyValuePairs)
+{
+    LOGV("AudioStreamOutDump::setParameters %s", keyValuePairs.string());
+
+    if (mFinalStream != 0 ) {
+        return mFinalStream->setParameters(keyValuePairs);
+    }
+
+    AudioParameter param = AudioParameter(keyValuePairs);
+    String8 value;
+    int valueInt;
+    status_t status = NO_ERROR;
+
+    if (param.getInt(String8("set_id"), valueInt) == NO_ERROR) {
+        mId = valueInt;
+    }
+
+    if (param.getInt(String8("format"), valueInt) == NO_ERROR) {
+        if (mOutFile == 0) {
+            mFormat = valueInt;
+        } else {
+            status = INVALID_OPERATION;
+        }
+    }
+    if (param.getInt(String8("channels"), valueInt) == NO_ERROR) {
+        if (valueInt == AudioSystem::CHANNEL_OUT_STEREO || valueInt == AudioSystem::CHANNEL_OUT_MONO) {
+            mChannels = valueInt;
+        } else {
+            status = BAD_VALUE;
+        }
+    }
+    if (param.getInt(String8("sampling_rate"), valueInt) == NO_ERROR) {
+        if (valueInt > 0 && valueInt <= 48000) {
+            if (mOutFile == 0) {
+                mSampleRate = valueInt;
+            } else {
+                status = INVALID_OPERATION;
+            }
+        } else {
+            status = BAD_VALUE;
+        }
+    }
+    return status;
+}
+
+String8 AudioStreamOutDump::getParameters(const String8& keys)
+{
+    if (mFinalStream != 0 ) return mFinalStream->getParameters(keys);
+
+    AudioParameter param = AudioParameter(keys);
+    return param.toString();
+}
+
+status_t AudioStreamOutDump::dump(int fd, const Vector<String16>& args)
+{
+    if (mFinalStream != 0 ) return mFinalStream->dump(fd, args);
+    return NO_ERROR;
+}
+
+void AudioStreamOutDump::Close()
 {
     if(mOutFile) {
         fclose(mOutFile);
@@ -114,4 +379,141 @@
     }
 }
 
+// ----------------------------------------------------------------------------
+
+AudioStreamInDump::AudioStreamInDump(AudioDumpInterface *interface,
+                                        int id,
+                                        AudioStreamIn* finalStream,
+                                        uint32_t devices,
+                                        int format,
+                                        uint32_t channels,
+                                        uint32_t sampleRate)
+    : mInterface(interface), mId(id),
+      mSampleRate(sampleRate), mFormat(format), mChannels(channels), mDevice(devices),
+      mBufferSize(1024), mFinalStream(finalStream), mInFile(0)
+{
+    LOGV("AudioStreamInDump Constructor %p, mInterface %p, mFinalStream %p", this, mInterface, mFinalStream);
+}
+
+
+AudioStreamInDump::~AudioStreamInDump()
+{
+    Close();
+}
+
+ssize_t AudioStreamInDump::read(void* buffer, ssize_t bytes)
+{
+    if (mFinalStream) {
+        return mFinalStream->read(buffer, bytes);
+    }
+
+    usleep((bytes * 1000000) / frameSize() / sampleRate());
+
+    if(!mInFile) {
+        char name[255];
+        strcpy(name, "/sdcard/music/sine440");
+        if (channels() == AudioSystem::CHANNEL_IN_MONO) {
+            strcat(name, "_mo");
+        } else {
+            strcat(name, "_st");
+        }
+        if (format() == AudioSystem::PCM_16_BIT) {
+            strcat(name, "_16b");
+        } else {
+            strcat(name, "_8b");
+        }
+        if (sampleRate() < 16000) {
+            strcat(name, "_8k");
+        } else if (sampleRate() < 32000) {
+            strcat(name, "_22k");
+        } else if (sampleRate() < 48000) {
+            strcat(name, "_44k");
+        } else {
+            strcat(name, "_48k");
+        }
+        strcat(name, ".wav");
+        mInFile = fopen(name, "rb");
+        LOGV("Opening dump file %s, fh %p", name, mInFile);
+        if (mInFile) {
+            fseek(mInFile, AUDIO_DUMP_WAVE_HDR_SIZE, SEEK_SET);
+        }
+
+    }
+    if (mInFile) {
+        ssize_t bytesRead = fread(buffer, bytes, 1, mInFile);
+        if (bytesRead != bytes) {
+            fseek(mInFile, AUDIO_DUMP_WAVE_HDR_SIZE, SEEK_SET);
+            fread((uint8_t *)buffer+bytesRead, bytes-bytesRead, 1, mInFile);
+        }
+    }
+    return bytes;
+}
+
+status_t AudioStreamInDump::standby()
+{
+    LOGV("AudioStreamInDump standby(), mInFile %p, mFinalStream %p", mInFile, mFinalStream);
+
+    Close();
+    if (mFinalStream != 0 ) return mFinalStream->standby();
+    return NO_ERROR;
+}
+
+status_t AudioStreamInDump::setGain(float gain)
+{
+    if (mFinalStream != 0 ) return mFinalStream->setGain(gain);
+    return NO_ERROR;
+}
+
+uint32_t AudioStreamInDump::sampleRate() const
+{
+    if (mFinalStream != 0 ) return mFinalStream->sampleRate();
+    return mSampleRate;
+}
+
+size_t AudioStreamInDump::bufferSize() const
+{
+    if (mFinalStream != 0 ) return mFinalStream->bufferSize();
+    return mBufferSize;
+}
+
+uint32_t AudioStreamInDump::channels() const
+{
+    if (mFinalStream != 0 ) return mFinalStream->channels();
+    return mChannels;
+}
+
+int AudioStreamInDump::format() const
+{
+    if (mFinalStream != 0 ) return mFinalStream->format();
+    return mFormat;
+}
+
+status_t AudioStreamInDump::setParameters(const String8& keyValuePairs)
+{
+    LOGV("AudioStreamInDump::setParameters()");
+    if (mFinalStream != 0 ) return mFinalStream->setParameters(keyValuePairs);
+    return NO_ERROR;
+}
+
+String8 AudioStreamInDump::getParameters(const String8& keys)
+{
+    if (mFinalStream != 0 ) return mFinalStream->getParameters(keys);
+
+    AudioParameter param = AudioParameter(keys);
+    return param.toString();
+}
+
+status_t AudioStreamInDump::dump(int fd, const Vector<String16>& args)
+{
+    if (mFinalStream != 0 ) return mFinalStream->dump(fd, args);
+    return NO_ERROR;
+}
+
+void AudioStreamInDump::Close()
+{
+    if(mInFile) {
+        fclose(mInFile);
+        mInFile = 0;
+    }
+}
 }; // namespace android
diff --git a/libs/audioflinger/AudioDumpInterface.h b/libs/audioflinger/AudioDumpInterface.h
index b72c94e..1136ce1 100644
--- a/libs/audioflinger/AudioDumpInterface.h
+++ b/libs/audioflinger/AudioDumpInterface.h
@@ -20,35 +20,95 @@
 
 #include <stdint.h>
 #include <sys/types.h>
+#include <utils/String8.h>
+#include <utils/SortedVector.h>
 
 #include <hardware_legacy/AudioHardwareBase.h>
 
 namespace android {
 
-#define FLINGER_DUMP_NAME "/data/FlingerOut.pcm" // name of file used for dump
+#define AUDIO_DUMP_WAVE_HDR_SIZE 44
+
+class AudioDumpInterface;
 
 class AudioStreamOutDump : public AudioStreamOut {
 public:
-                        AudioStreamOutDump( AudioStreamOut* FinalStream);
+                        AudioStreamOutDump(AudioDumpInterface *interface,
+                                            int id,
+                                            AudioStreamOut* finalStream,
+                                            uint32_t devices,
+                                            int format,
+                                            uint32_t channels,
+                                            uint32_t sampleRate);
                         ~AudioStreamOutDump();
-                        virtual ssize_t     write(const void* buffer, size_t bytes);
 
-    virtual uint32_t    sampleRate() const { return mFinalStream->sampleRate(); }
-    virtual size_t      bufferSize() const { return mFinalStream->bufferSize(); }
-    virtual int         channelCount() const { return mFinalStream->channelCount(); }
-    virtual int         format() const { return mFinalStream->format(); }
-    virtual uint32_t    latency() const { return mFinalStream->latency(); }
-    virtual status_t    setVolume(float volume)
-                            { return mFinalStream->setVolume(volume); }
+    virtual ssize_t     write(const void* buffer, size_t bytes);
+    virtual uint32_t    sampleRate() const;
+    virtual size_t      bufferSize() const;
+    virtual uint32_t    channels() const;
+    virtual int         format() const;
+    virtual uint32_t    latency() const;
+    virtual status_t    setVolume(float left, float right);
     virtual status_t    standby();
-    virtual status_t    dump(int fd, const Vector<String16>& args) { return mFinalStream->dump(fd, args); }
+    virtual status_t    setParameters(const String8& keyValuePairs);
+    virtual String8     getParameters(const String8& keys);
+    virtual status_t    dump(int fd, const Vector<String16>& args);
     void                Close(void);
+    AudioStreamOut*     finalStream() { return mFinalStream; }
+    uint32_t            device() { return mDevice; }
 
+    int                 getId()  { return mId; }
 private:
+    AudioDumpInterface *mInterface;
+    int                  mId;
+    uint32_t mSampleRate;               //
+    uint32_t mFormat;                   //
+    uint32_t mChannels;                 // output configuration
+    uint32_t mLatency;                  //
+    uint32_t mDevice;                   // current device this output is routed to
+    size_t  mBufferSize;
     AudioStreamOut      *mFinalStream;
-    FILE                *mOutFile;     // output file
+    FILE                *mOutFile;      // output file
+    int                 mFileCount;
 };
 
+class AudioStreamInDump : public AudioStreamIn {
+public:
+                        AudioStreamInDump(AudioDumpInterface *interface,
+                                            int id,
+                                            AudioStreamIn* finalStream,
+                                            uint32_t devices,
+                                            int format,
+                                            uint32_t channels,
+                                            uint32_t sampleRate);
+                        ~AudioStreamInDump();
+
+    virtual uint32_t    sampleRate() const;
+    virtual size_t      bufferSize() const;
+    virtual uint32_t    channels() const;
+    virtual int         format() const;
+
+    virtual status_t    setGain(float gain);
+    virtual ssize_t     read(void* buffer, ssize_t bytes);
+    virtual status_t    standby();
+    virtual status_t    setParameters(const String8& keyValuePairs);
+    virtual String8     getParameters(const String8& keys);
+    virtual status_t    dump(int fd, const Vector<String16>& args);
+    void                Close(void);
+    AudioStreamIn*     finalStream() { return mFinalStream; }
+    uint32_t            device() { return mDevice; }
+
+private:
+    AudioDumpInterface *mInterface;
+    int                  mId;
+    uint32_t mSampleRate;               //
+    uint32_t mFormat;                   //
+    uint32_t mChannels;                 // output configuration
+    uint32_t mDevice;                   // current device this output is routed to
+    size_t  mBufferSize;
+    AudioStreamIn      *mFinalStream;
+    FILE                *mInFile;      // output file
+};
 
 class AudioDumpInterface : public AudioHardwareBase
 {
@@ -56,10 +116,13 @@
 public:
                         AudioDumpInterface(AudioHardwareInterface* hw);
     virtual AudioStreamOut* openOutputStream(
-                                int format=0,
-                                int channelCount=0,
-                                uint32_t sampleRate=0,
+                                uint32_t devices,
+                                int *format=0,
+                                uint32_t *channels=0,
+                                uint32_t *sampleRate=0,
                                 status_t *status=0);
+    virtual    void        closeOutputStream(AudioStreamOut* out);
+
     virtual             ~AudioDumpInterface();
 
     virtual status_t    initCheck()
@@ -75,21 +138,25 @@
     virtual status_t    getMicMute(bool* state)
                             {return mFinalInterface->getMicMute(state);}
 
-    virtual status_t    setParameter(const char* key, const char* value)
-                            {return mFinalInterface->setParameter(key, value);}
+    virtual status_t    setParameters(const String8& keyValuePairs);
+    virtual String8     getParameters(const String8& keys);
 
-    virtual AudioStreamIn* openInputStream(int inputSource, int format, int channelCount,
-            uint32_t sampleRate, status_t *status, AudioSystem::audio_in_acoustics acoustics)
-        { return mFinalInterface->openInputStream(inputSource, format, channelCount, sampleRate, status, acoustics); }
+    virtual AudioStreamIn* openInputStream(uint32_t devices, int *format, uint32_t *channels,
+            uint32_t *sampleRate, status_t *status, AudioSystem::audio_in_acoustics acoustics);
+    virtual    void        closeInputStream(AudioStreamIn* in);
 
     virtual status_t    dump(int fd, const Vector<String16>& args) { return mFinalInterface->dumpState(fd, args); }
 
+            String8     fileName() const { return mFileName; }
 protected:
-    virtual status_t    doRouting() {return mFinalInterface->setRouting(mMode, mRoutes[mMode]);}
 
-    AudioHardwareInterface  *mFinalInterface;
-    AudioStreamOutDump      *mStreamOut;
-
+    AudioHardwareInterface          *mFinalInterface;
+    SortedVector<AudioStreamOutDump *>    mOutputs;
+    bool                            mFirstHwOutput;
+    SortedVector<AudioStreamInDump *>    mInputs;
+    Mutex                           mLock;
+    String8                         mPolicyCommands;
+    String8                         mFileName;
 };
 
 }; // namespace android
diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp
index da7cc8a..ebd470f 100644
--- a/libs/audioflinger/AudioFlinger.cpp
+++ b/libs/audioflinger/AudioFlinger.cpp
@@ -24,10 +24,10 @@
 #include <sys/time.h>
 #include <sys/resource.h>
 
-#include <utils/IServiceManager.h>
+#include <binder/IServiceManager.h>
 #include <utils/Log.h>
-#include <utils/Parcel.h>
-#include <utils/IPCThreadState.h>
+#include <binder/Parcel.h>
+#include <binder/IPCThreadState.h>
 #include <utils/String16.h>
 #include <utils/threads.h>
 
@@ -62,8 +62,6 @@
 static const char* kHardwareLockedString = "Hardware lock is taken\n";
 
 //static const nsecs_t kStandbyTimeInNsecs = seconds(3);
-static const unsigned long kBufferRecoveryInUsecs = 2000;
-static const unsigned long kMaxBufferRecoveryInUsecs = 20000;
 static const float MAX_GAIN = 4096.0f;
 
 // retry counts for buffer fill timeout
@@ -71,14 +69,10 @@
 static const int8_t kMaxTrackRetries = 50;
 static const int8_t kMaxTrackStartupRetries = 50;
 
-static const int kStartSleepTime = 30000;
-static const int kStopSleepTime = 30000;
-
 static const int kDumpLockRetries = 50;
 static const int kDumpLockSleep = 20000;
 
-// Maximum number of pending buffers allocated by OutputTrack::write()
-static const uint8_t kMaxOutputTrackBuffers = 5;
+static const nsecs_t kWarningThrottle = seconds(5);
 
 
 #define AUDIOFLINGER_SECURITY_ENABLED 1
@@ -121,132 +115,41 @@
 
 AudioFlinger::AudioFlinger()
     : BnAudioFlinger(),
-        mAudioHardware(0), mA2dpAudioInterface(0), mA2dpEnabled(false), mNotifyA2dpChange(false),
-        mForcedSpeakerCount(0), mA2dpDisableCount(0), mA2dpSuppressed(false), mForcedRoute(0),
-        mRouteRestoreTime(0), mMusicMuteSaved(false)
+        mAudioHardware(0), mMasterVolume(1.0f), mMasterMute(false), mNextThreadId(0)
 {
     mHardwareStatus = AUDIO_HW_IDLE;
+
     mAudioHardware = AudioHardwareInterface::create();
+
     mHardwareStatus = AUDIO_HW_INIT;
     if (mAudioHardware->initCheck() == NO_ERROR) {
         // open 16-bit output stream for s/w mixer
-        mHardwareStatus = AUDIO_HW_OUTPUT_OPEN;
-        status_t status;
-        AudioStreamOut *hwOutput = mAudioHardware->openOutputStream(AudioSystem::PCM_16_BIT, 0, 0, &status);
-        mHardwareStatus = AUDIO_HW_IDLE;
-        if (hwOutput) {
-            mHardwareMixerThread = new MixerThread(this, hwOutput, AudioSystem::AUDIO_OUTPUT_HARDWARE);
-        } else {
-            LOGE("Failed to initialize hardware output stream, status: %d", status);
-        }
-        
-#ifdef WITH_A2DP
-        // Create A2DP interface
-        mA2dpAudioInterface = new A2dpAudioInterface();
-        AudioStreamOut *a2dpOutput = mA2dpAudioInterface->openOutputStream(AudioSystem::PCM_16_BIT, 0, 0, &status);
-        if (a2dpOutput) {
-            mA2dpMixerThread = new MixerThread(this, a2dpOutput, AudioSystem::AUDIO_OUTPUT_A2DP);
-            if (hwOutput) {  
-                uint32_t frameCount = ((a2dpOutput->bufferSize()/a2dpOutput->frameSize()) * hwOutput->sampleRate()) / a2dpOutput->sampleRate();
-                MixerThread::OutputTrack *a2dpOutTrack = new MixerThread::OutputTrack(mA2dpMixerThread,
-                                                            hwOutput->sampleRate(),
-                                                            AudioSystem::PCM_16_BIT,
-                                                            hwOutput->channelCount(),
-                                                            frameCount);
-                mHardwareMixerThread->setOuputTrack(a2dpOutTrack);                
-            }
-        } else {
-            LOGE("Failed to initialize A2DP output stream, status: %d", status);
-        }
-#endif
- 
-        // FIXME - this should come from settings
-        setRouting(AudioSystem::MODE_NORMAL, AudioSystem::ROUTE_SPEAKER, AudioSystem::ROUTE_ALL);
-        setRouting(AudioSystem::MODE_RINGTONE, AudioSystem::ROUTE_SPEAKER, AudioSystem::ROUTE_ALL);
-        setRouting(AudioSystem::MODE_IN_CALL, AudioSystem::ROUTE_EARPIECE, AudioSystem::ROUTE_ALL);
+
         setMode(AudioSystem::MODE_NORMAL);
 
         setMasterVolume(1.0f);
         setMasterMute(false);
-
-        // Start record thread
-        mAudioRecordThread = new AudioRecordThread(mAudioHardware, this);
-        if (mAudioRecordThread != 0) {
-            mAudioRecordThread->run("AudioRecordThread", PRIORITY_URGENT_AUDIO);            
-        }
-     } else {
+    } else {
         LOGE("Couldn't even initialize the stubbed audio hardware!");
     }
 }
 
 AudioFlinger::~AudioFlinger()
 {
-    if (mAudioRecordThread != 0) {
-        mAudioRecordThread->exit();
-        mAudioRecordThread.clear();        
+    while (!mRecordThreads.isEmpty()) {
+        // closeInput() will remove first entry from mRecordThreads
+        closeInput(mRecordThreads.keyAt(0));
     }
-    mHardwareMixerThread.clear();
-    delete mAudioHardware;
-    // deleting mA2dpAudioInterface also deletes mA2dpOutput;
-#ifdef WITH_A2DP
-    mA2dpMixerThread.clear();
-    delete mA2dpAudioInterface;
-#endif
-}
-
-
-#ifdef WITH_A2DP
-// setA2dpEnabled_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::setA2dpEnabled_l(bool enable)
-{    
-    SortedVector < sp<MixerThread::Track> > tracks;
-    SortedVector < wp<MixerThread::Track> > activeTracks;
-    
-    LOGD_IF(enable, "set output to A2DP\n");
-    LOGD_IF(!enable, "set output to hardware audio\n");
-
-    // Transfer tracks playing on MUSIC stream from one mixer to the other
-    if (enable) {
-        mHardwareMixerThread->getTracks_l(tracks, activeTracks);
-        mA2dpMixerThread->putTracks_l(tracks, activeTracks);
-    } else {
-        mA2dpMixerThread->getTracks_l(tracks, activeTracks);
-        mHardwareMixerThread->putTracks_l(tracks, activeTracks);
-        mA2dpMixerThread->mOutput->standby();
+    while (!mPlaybackThreads.isEmpty()) {
+        // closeOutput() will remove first entry from mPlaybackThreads
+        closeOutput(mPlaybackThreads.keyAt(0));
     }
-    mA2dpEnabled = enable;
-    mNotifyA2dpChange = true;
-    mWaitWorkCV.broadcast();
-}
-
-// checkA2dpEnabledChange_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::checkA2dpEnabledChange_l()
-{
-    if (mNotifyA2dpChange) {
-        // Notify AudioSystem of the A2DP activation/deactivation
-        size_t size = mNotificationClients.size();
-        for (size_t i = 0; i < size; i++) {
-            sp<IBinder> binder = mNotificationClients.itemAt(i).promote();
-            if (binder != NULL) {
-                LOGV("Notifying output change to client %p", binder.get());
-                sp<IAudioFlingerClient> client = interface_cast<IAudioFlingerClient> (binder);
-                client->a2dpEnabledChanged(mA2dpEnabled);
-            }
-        }
-        mNotifyA2dpChange = false;
+    if (mAudioHardware) {
+        delete mAudioHardware;
     }
 }
-#endif // WITH_A2DP
 
-bool AudioFlinger::streamForcedToSpeaker(int streamType)
-{
-    // NOTE that streams listed here must not be routed to A2DP by default:
-    // AudioSystem::routedToA2dpOutput(streamType) == false
-    return (streamType == AudioSystem::RING ||
-            streamType == AudioSystem::ALARM ||
-            streamType == AudioSystem::NOTIFICATION ||
-            streamType == AudioSystem::ENFORCED_AUDIBLE);
-}
+
 
 status_t AudioFlinger::dumpClients(int fd, const Vector<String16>& args)
 {
@@ -276,10 +179,7 @@
     char buffer[SIZE];
     String8 result;
     int hardwareStatus = mHardwareStatus;
-    
-    if (hardwareStatus == AUDIO_HW_IDLE && mHardwareMixerThread->mStandby) {
-        hardwareStatus = AUDIO_HW_STANDBY;
-    }
+
     snprintf(buffer, SIZE, "Hardware status: %d\n", hardwareStatus);
     result.append(buffer);
     write(fd, result.string(), result.size());
@@ -337,13 +237,16 @@
 
         dumpClients(fd, args);
         dumpInternals(fd, args);
-        mHardwareMixerThread->dump(fd, args);
-#ifdef WITH_A2DP
-        mA2dpMixerThread->dump(fd, args);
-#endif
 
-        // dump record client
-        if (mAudioRecordThread != 0) mAudioRecordThread->dump(fd, args);
+        // dump playback threads
+        for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
+            mPlaybackThreads.valueAt(i)->dump(fd, args);
+        }
+
+        // dump record threads
+        for (size_t i = 0; i < mRecordThreads.size(); i++) {
+            mRecordThreads.valueAt(i)->dump(fd, args);
+        }
 
         if (mAudioHardware) {
             mAudioHardware->dumpState(fd, args);
@@ -353,6 +256,7 @@
     return NO_ERROR;
 }
 
+
 // IAudioFlinger interface
 
 
@@ -365,9 +269,10 @@
         int frameCount,
         uint32_t flags,
         const sp<IMemory>& sharedBuffer,
+        int output,
         status_t *status)
 {
-    sp<MixerThread::Track> track;
+    sp<PlaybackThread::Track> track;
     sp<TrackHandle> trackHandle;
     sp<Client> client;
     wp<Client> wclient;
@@ -381,6 +286,12 @@
 
     {
         Mutex::Autolock _l(mLock);
+        PlaybackThread *thread = checkPlaybackThread_l(output);
+        if (thread == NULL) {
+            LOGE("unknown output thread");
+            lStatus = BAD_VALUE;
+            goto Exit;
+        }
 
         wclient = mClients.valueFor(pid);
 
@@ -390,20 +301,15 @@
             client = new Client(this, pid);
             mClients.add(pid, client);
         }
-#ifdef WITH_A2DP
-        if (isA2dpEnabled() && AudioSystem::routedToA2dpOutput(streamType)) {
-            track = mA2dpMixerThread->createTrack_l(client, streamType, sampleRate, format,
-                    channelCount, frameCount, sharedBuffer, &lStatus);            
-        } else 
-#endif
-        {
-            track = mHardwareMixerThread->createTrack_l(client, streamType, sampleRate, format,
-                    channelCount, frameCount, sharedBuffer, &lStatus);            
-        }
+        track = thread->createTrack_l(client, streamType, sampleRate, format,
+                channelCount, frameCount, sharedBuffer, &lStatus);
     }
     if (lStatus == NO_ERROR) {
         trackHandle = new TrackHandle(track);
     } else {
+        // remove local strong reference to Client before deleting the Track so that the Client
+        // destructor is called by the TrackBase destructor with mLock held
+        client.clear();
         track.clear();
     }
 
@@ -416,52 +322,57 @@
 
 uint32_t AudioFlinger::sampleRate(int output) const
 {
-#ifdef WITH_A2DP
-     if (output == AudioSystem::AUDIO_OUTPUT_A2DP) {
-         return mA2dpMixerThread->sampleRate();
-     }
-#endif
-     return mHardwareMixerThread->sampleRate();
+    Mutex::Autolock _l(mLock);
+    PlaybackThread *thread = checkPlaybackThread_l(output);
+    if (thread == NULL) {
+        LOGW("sampleRate() unknown thread %d", output);
+        return 0;
+    }
+    return thread->sampleRate();
 }
 
 int AudioFlinger::channelCount(int output) const
 {
-#ifdef WITH_A2DP
-     if (output == AudioSystem::AUDIO_OUTPUT_A2DP) {
-         return mA2dpMixerThread->channelCount();
-     }
-#endif
-     return mHardwareMixerThread->channelCount();
+    Mutex::Autolock _l(mLock);
+    PlaybackThread *thread = checkPlaybackThread_l(output);
+    if (thread == NULL) {
+        LOGW("channelCount() unknown thread %d", output);
+        return 0;
+    }
+    return thread->channelCount();
 }
 
 int AudioFlinger::format(int output) const
 {
-#ifdef WITH_A2DP
-     if (output == AudioSystem::AUDIO_OUTPUT_A2DP) {
-         return mA2dpMixerThread->format();
-     }
-#endif
-     return mHardwareMixerThread->format();
+    Mutex::Autolock _l(mLock);
+    PlaybackThread *thread = checkPlaybackThread_l(output);
+    if (thread == NULL) {
+        LOGW("format() unknown thread %d", output);
+        return 0;
+    }
+    return thread->format();
 }
 
 size_t AudioFlinger::frameCount(int output) const
 {
-#ifdef WITH_A2DP
-     if (output == AudioSystem::AUDIO_OUTPUT_A2DP) {
-         return mA2dpMixerThread->frameCount();
-     }
-#endif
-     return mHardwareMixerThread->frameCount();
+    Mutex::Autolock _l(mLock);
+    PlaybackThread *thread = checkPlaybackThread_l(output);
+    if (thread == NULL) {
+        LOGW("frameCount() unknown thread %d", output);
+        return 0;
+    }
+    return thread->frameCount();
 }
 
 uint32_t AudioFlinger::latency(int output) const
 {
-#ifdef WITH_A2DP
-     if (output == AudioSystem::AUDIO_OUTPUT_A2DP) {
-         return mA2dpMixerThread->latency();
-     }
-#endif
-     return mHardwareMixerThread->latency();
+    Mutex::Autolock _l(mLock);
+    PlaybackThread *thread = checkPlaybackThread_l(output);
+    if (thread == NULL) {
+        LOGW("latency() unknown thread %d", output);
+        return 0;
+    }
+    return thread->latency();
 }
 
 status_t AudioFlinger::setMasterVolume(float value)
@@ -478,96 +389,14 @@
         value = 1.0f;
     }
     mHardwareStatus = AUDIO_HW_IDLE;
-    mHardwareMixerThread->setMasterVolume(value);
-#ifdef WITH_A2DP
-    mA2dpMixerThread->setMasterVolume(value);
-#endif
+
+    mMasterVolume = value;
+    for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
+       mPlaybackThreads.valueAt(i)->setMasterVolume(value);
 
     return NO_ERROR;
 }
 
-status_t AudioFlinger::setRouting(int mode, uint32_t routes, uint32_t mask)
-{
-    status_t err = NO_ERROR;
-
-    // check calling permissions
-    if (!settingsAllowed()) {
-        return PERMISSION_DENIED;
-    }
-    if ((mode < AudioSystem::MODE_CURRENT) || (mode >= AudioSystem::NUM_MODES)) {
-        LOGW("Illegal value: setRouting(%d, %u, %u)", mode, routes, mask);
-        return BAD_VALUE;
-    }
-
-#ifdef WITH_A2DP
-    LOGV("setRouting %d %d %d, tid %d, calling tid %d\n", mode, routes, mask, gettid(),
-            IPCThreadState::self()->getCallingPid());
-    if (mode == AudioSystem::MODE_NORMAL && 
-            (mask & AudioSystem::ROUTE_BLUETOOTH_A2DP)) {
-        AutoMutex lock(&mLock);
-
-        bool enableA2dp = false;
-        if (routes & AudioSystem::ROUTE_BLUETOOTH_A2DP) {
-            enableA2dp = true;
-        }
-        if (mA2dpDisableCount > 0) {
-            mA2dpSuppressed = enableA2dp;
-        } else {
-            setA2dpEnabled_l(enableA2dp);
-        }
-        LOGV("setOutput done\n");
-    }
-    // setRouting() is always called at least for mode == AudioSystem::MODE_IN_CALL when 
-    // SCO is enabled, whatever current mode is so we can safely handle A2DP disabling only
-    // in this case to avoid doing it several times.
-    if (mode == AudioSystem::MODE_IN_CALL &&
-        (mask & AudioSystem::ROUTE_BLUETOOTH_SCO)) {
-        AutoMutex lock(&mLock);
-        handleRouteDisablesA2dp_l(routes);
-    }
-#endif
-
-    // do nothing if only A2DP routing is affected
-    mask &= ~AudioSystem::ROUTE_BLUETOOTH_A2DP;
-    if (mask) {
-        AutoMutex lock(mHardwareLock);
-        mHardwareStatus = AUDIO_HW_GET_ROUTING;
-        uint32_t r;
-        err = mAudioHardware->getRouting(mode, &r);
-        if (err == NO_ERROR) {
-            r = (r & ~mask) | (routes & mask);
-            if (mode == AudioSystem::MODE_NORMAL || 
-                (mode == AudioSystem::MODE_CURRENT && getMode() == AudioSystem::MODE_NORMAL)) {
-                mSavedRoute = r;
-                r |= mForcedRoute;
-                LOGV("setRouting mSavedRoute %08x mForcedRoute %08x\n", mSavedRoute, mForcedRoute);
-            }
-            mHardwareStatus = AUDIO_HW_SET_ROUTING;
-            err = mAudioHardware->setRouting(mode, r);
-        }
-        mHardwareStatus = AUDIO_HW_IDLE;
-    }
-    return err;
-}
-
-uint32_t AudioFlinger::getRouting(int mode) const
-{
-    uint32_t routes = 0;
-    if ((mode >= AudioSystem::MODE_CURRENT) && (mode < AudioSystem::NUM_MODES)) {
-        if (mode == AudioSystem::MODE_NORMAL || 
-            (mode == AudioSystem::MODE_CURRENT && getMode() == AudioSystem::MODE_NORMAL)) {
-            routes = mSavedRoute;                
-        } else {
-            mHardwareStatus = AUDIO_HW_GET_ROUTING;
-            mAudioHardware->getRouting(mode, &routes);
-            mHardwareStatus = AUDIO_HW_IDLE;
-        }
-    } else {
-        LOGW("Illegal value: getRouting(%d)", mode);
-    }
-    return routes;
-}
-
 status_t AudioFlinger::setMode(int mode)
 {
     // check calling permissions
@@ -586,15 +415,6 @@
     return ret;
 }
 
-int AudioFlinger::getMode() const
-{
-    int mode = AudioSystem::MODE_INVALID;
-    mHardwareStatus = AUDIO_HW_SET_MODE;
-    mAudioHardware->getMode(&mode);
-    mHardwareStatus = AUDIO_HW_IDLE;
-    return mode;
-}
-
 status_t AudioFlinger::setMicMute(bool state)
 {
     // check calling permissions
@@ -624,60 +444,55 @@
     if (!settingsAllowed()) {
         return PERMISSION_DENIED;
     }
-    mHardwareMixerThread->setMasterMute(muted);
-#ifdef WITH_A2DP
-    mA2dpMixerThread->setMasterMute(muted);
-#endif
+
+    mMasterMute = muted;
+    for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
+       mPlaybackThreads.valueAt(i)->setMasterMute(muted);
+
     return NO_ERROR;
 }
 
 float AudioFlinger::masterVolume() const
 {
-    return mHardwareMixerThread->masterVolume();
+    return mMasterVolume;
 }
 
 bool AudioFlinger::masterMute() const
 {
-    return mHardwareMixerThread->masterMute();
+    return mMasterMute;
 }
 
-status_t AudioFlinger::setStreamVolume(int stream, float value)
+status_t AudioFlinger::setStreamVolume(int stream, float value, int output)
 {
     // check calling permissions
     if (!settingsAllowed()) {
         return PERMISSION_DENIED;
     }
 
-    if (uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES ||
-        uint32_t(stream) == AudioSystem::ENFORCED_AUDIBLE) {
+    if (stream < 0 || uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) {
         return BAD_VALUE;
     }
 
-    status_t ret = NO_ERROR;
-    if (stream == AudioSystem::VOICE_CALL ||
-        stream == AudioSystem::BLUETOOTH_SCO) {
-        float hwValue;
-        if (stream == AudioSystem::VOICE_CALL) {
-            hwValue = (float)AudioSystem::logToLinear(value)/100.0f;
-            // offset value to reflect actual hardware volume that never reaches 0
-            // 1% corresponds roughly to first step in VOICE_CALL stream volume setting (see AudioService.java)
-            value = 0.01 + 0.99 * value;
-        } else { // (type == AudioSystem::BLUETOOTH_SCO)
-            hwValue = 1.0f;
+    AutoMutex lock(mLock);
+    PlaybackThread *thread = NULL;
+    if (output) {
+        thread = checkPlaybackThread_l(output);
+        if (thread == NULL) {
+            return BAD_VALUE;
         }
-
-        AutoMutex lock(mHardwareLock);
-        mHardwareStatus = AUDIO_SET_VOICE_VOLUME;
-        ret = mAudioHardware->setVoiceVolume(hwValue);
-        mHardwareStatus = AUDIO_HW_IDLE;
     }
 
-    mHardwareMixerThread->setStreamVolume(stream, value);
-#ifdef WITH_A2DP
-    mA2dpMixerThread->setStreamVolume(stream, value);
-#endif
+    mStreamTypes[stream].volume = value;
 
-    return ret;
+    if (thread == NULL) {
+        for (uint32_t i = 0; i < mPlaybackThreads.size(); i++) {
+           mPlaybackThreads.valueAt(i)->setStreamVolume(stream, value);
+        }
+    } else {
+        thread->setStreamVolume(stream, value);
+    }
+
+    return NO_ERROR;
 }
 
 status_t AudioFlinger::setStreamMute(int stream, bool muted)
@@ -687,82 +502,115 @@
         return PERMISSION_DENIED;
     }
 
-    if (uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES ||
+    if (stream < 0 || uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES ||
         uint32_t(stream) == AudioSystem::ENFORCED_AUDIBLE) {
         return BAD_VALUE;
     }
 
-#ifdef WITH_A2DP
-    mA2dpMixerThread->setStreamMute(stream, muted);
-#endif
-    if (stream == AudioSystem::MUSIC) 
-    {
-        AutoMutex lock(&mHardwareLock);
-        if (mForcedRoute != 0)
-            mMusicMuteSaved = muted;
-        else
-            mHardwareMixerThread->setStreamMute(stream, muted);
-    } else {
-        mHardwareMixerThread->setStreamMute(stream, muted);
-    }
+    mStreamTypes[stream].mute = muted;
+    for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
+       mPlaybackThreads.valueAt(i)->setStreamMute(stream, muted);
 
     return NO_ERROR;
 }
 
-float AudioFlinger::streamVolume(int stream) const
+float AudioFlinger::streamVolume(int stream, int output) const
 {
-    if (uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) {
+    if (stream < 0 || uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) {
         return 0.0f;
     }
-    
-    float volume = mHardwareMixerThread->streamVolume(stream); 
-    // remove correction applied by setStreamVolume()
-    if (stream == AudioSystem::VOICE_CALL) {
-        volume = (volume - 0.01) / 0.99 ;
+
+    AutoMutex lock(mLock);
+    float volume;
+    if (output) {
+        PlaybackThread *thread = checkPlaybackThread_l(output);
+        if (thread == NULL) {
+            return 0.0f;
+        }
+        volume = thread->streamVolume(stream);
+    } else {
+        volume = mStreamTypes[stream].volume;
     }
-    
+
     return volume;
 }
 
 bool AudioFlinger::streamMute(int stream) const
 {
-    if (uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) {
+    if (stream < 0 || stream >= (int)AudioSystem::NUM_STREAM_TYPES) {
         return true;
     }
-    
-    if (stream == AudioSystem::MUSIC && mForcedRoute != 0) 
-    {
-        return mMusicMuteSaved;
-    }
-    return mHardwareMixerThread->streamMute(stream);
+
+    return mStreamTypes[stream].mute;
 }
 
 bool AudioFlinger::isMusicActive() const
 {
     Mutex::Autolock _l(mLock);
- #ifdef WITH_A2DP
-     if (isA2dpEnabled()) {
-         return mA2dpMixerThread->isMusicActive_l();
-     }
- #endif
-    return mHardwareMixerThread->isMusicActive_l();
+    for (uint32_t i = 0; i < mPlaybackThreads.size(); i++) {
+        if (mPlaybackThreads.valueAt(i)->isMusicActive()) {
+            return true;
+        }
+    }
+    return false;
 }
 
-status_t AudioFlinger::setParameter(const char* key, const char* value)
+status_t AudioFlinger::setParameters(int ioHandle, const String8& keyValuePairs)
 {
-    status_t result, result2;
-    AutoMutex lock(mHardwareLock);
-    mHardwareStatus = AUDIO_SET_PARAMETER;
-    
-    LOGV("setParameter() key %s, value %s, tid %d, calling tid %d", key, value, gettid(), IPCThreadState::self()->getCallingPid());
-    result = mAudioHardware->setParameter(key, value);
-    if (mA2dpAudioInterface) {
-        result2 = mA2dpAudioInterface->setParameter(key, value);
-        if (result2)
-            result = result2;
+    status_t result;
+
+    LOGV("setParameters(): io %d, keyvalue %s, tid %d, calling tid %d",
+            ioHandle, keyValuePairs.string(), gettid(), IPCThreadState::self()->getCallingPid());
+    // check calling permissions
+    if (!settingsAllowed()) {
+        return PERMISSION_DENIED;
     }
-    mHardwareStatus = AUDIO_HW_IDLE;
-    return result;
+
+    // ioHandle == 0 means the parameters are global to the audio hardware interface
+    if (ioHandle == 0) {
+        AutoMutex lock(mHardwareLock);
+        mHardwareStatus = AUDIO_SET_PARAMETER;
+        result = mAudioHardware->setParameters(keyValuePairs);
+        mHardwareStatus = AUDIO_HW_IDLE;
+        return result;
+    }
+
+    // hold a strong ref on thread in case closeOutput() or closeInput() is called
+    // and the thread is exited once the lock is released
+    sp<ThreadBase> thread;
+    {
+        Mutex::Autolock _l(mLock);
+        thread = checkPlaybackThread_l(ioHandle);
+        if (thread == NULL) {
+            thread = checkRecordThread_l(ioHandle);
+        }
+    }
+    if (thread != NULL) {
+        return thread->setParameters(keyValuePairs);
+    }
+    return BAD_VALUE;
+}
+
+String8 AudioFlinger::getParameters(int ioHandle, const String8& keys)
+{
+//    LOGV("getParameters() io %d, keys %s, tid %d, calling tid %d",
+//            ioHandle, keys.string(), gettid(), IPCThreadState::self()->getCallingPid());
+
+    if (ioHandle == 0) {
+        return mAudioHardware->getParameters(keys);
+    }
+
+    Mutex::Autolock _l(mLock);
+
+    PlaybackThread *playbackThread = checkPlaybackThread_l(ioHandle);
+    if (playbackThread != NULL) {
+        return playbackThread->getParameters(keys);
+    }
+    RecordThread *recordThread = checkRecordThread_l(ioHandle);
+    if (recordThread != NULL) {
+        return recordThread->getParameters(keys);
+    }
+    return String8("");
 }
 
 size_t AudioFlinger::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
@@ -770,9 +618,24 @@
     return mAudioHardware->getInputBufferSize(sampleRate, format, channelCount);
 }
 
+status_t AudioFlinger::setVoiceVolume(float value)
+{
+    // check calling permissions
+    if (!settingsAllowed()) {
+        return PERMISSION_DENIED;
+    }
+
+    AutoMutex lock(mHardwareLock);
+    mHardwareStatus = AUDIO_SET_VOICE_VOLUME;
+    status_t ret = mAudioHardware->setVoiceVolume(value);
+    mHardwareStatus = AUDIO_HW_IDLE;
+
+    return ret;
+}
+
 void AudioFlinger::registerClient(const sp<IAudioFlingerClient>& client)
 {
-    
+
     LOGV("registerClient() %p, tid %d, calling tid %d", client.get(), gettid(), IPCThreadState::self()->getCallingPid());
     Mutex::Autolock _l(mLock);
 
@@ -781,12 +644,21 @@
         LOGV("Adding notification client %p", binder.get());
         binder->linkToDeath(this);
         mNotificationClients.add(binder);
-        client->a2dpEnabledChanged(isA2dpEnabled());
+    }
+
+    // the config change is always sent from playback or record threads to avoid deadlock
+    // with AudioSystem::gLock
+    for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
+        mPlaybackThreads.valueAt(i)->sendConfigEvent(AudioSystem::OUTPUT_OPENED);
+    }
+
+    for (size_t i = 0; i < mRecordThreads.size(); i++) {
+        mRecordThreads.valueAt(i)->sendConfigEvent(AudioSystem::INPUT_OPENED);
     }
 }
 
 void AudioFlinger::binderDied(const wp<IBinder>& who) {
-    
+
     LOGV("binderDied() %p, tid %d, calling tid %d", who.unsafe_get(), gettid(), IPCThreadState::self()->getCallingPid());
     Mutex::Autolock _l(mLock);
 
@@ -801,156 +673,242 @@
     }
 }
 
-void AudioFlinger::removeClient(pid_t pid)
+// audioConfigChanged_l() must be called with AudioFlinger::mLock held
+void AudioFlinger::audioConfigChanged_l(int event, const sp<ThreadBase>& thread, void *param2) {
+    int ioHandle = 0;
+
+    for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
+        if (mPlaybackThreads.valueAt(i) == thread) {
+            ioHandle = mPlaybackThreads.keyAt(i);
+            break;
+        }
+    }
+    if (ioHandle == 0) {
+        for (size_t i = 0; i < mRecordThreads.size(); i++) {
+            if (mRecordThreads.valueAt(i) == thread) {
+                ioHandle = mRecordThreads.keyAt(i);
+                break;
+            }
+        }
+    }
+
+    if (ioHandle != 0) {
+        size_t size = mNotificationClients.size();
+        for (size_t i = 0; i < size; i++) {
+            sp<IBinder> binder = mNotificationClients.itemAt(i);
+            LOGV("audioConfigChanged_l() Notifying change to client %p", binder.get());
+            sp<IAudioFlingerClient> client = interface_cast<IAudioFlingerClient> (binder);
+            client->ioConfigChanged(event, ioHandle, param2);
+        }
+    }
+}
+
+// removeClient_l() must be called with AudioFlinger::mLock held
+void AudioFlinger::removeClient_l(pid_t pid)
 {
-    LOGV("removeClient() pid %d, tid %d, calling tid %d", pid, gettid(), IPCThreadState::self()->getCallingPid());
-    Mutex::Autolock _l(mLock);
+    LOGV("removeClient_l() pid %d, tid %d, calling tid %d", pid, gettid(), IPCThreadState::self()->getCallingPid());
     mClients.removeItem(pid);
 }
 
-bool AudioFlinger::isA2dpEnabled() const
+// ----------------------------------------------------------------------------
+
+AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger)
+    :   Thread(false),
+        mAudioFlinger(audioFlinger), mSampleRate(0), mFrameCount(0), mChannelCount(0),
+        mFormat(0), mFrameSize(1), mStandby(false)
 {
-    return mA2dpEnabled;
 }
 
-void AudioFlinger::handleForcedSpeakerRoute(int command)
+AudioFlinger::ThreadBase::~ThreadBase()
 {
-    switch(command) {
-    case ACTIVE_TRACK_ADDED:
-        {
-            AutoMutex lock(mHardwareLock);
-            if (mForcedSpeakerCount++ == 0) {
-                if (mForcedRoute == 0) {
-                    mMusicMuteSaved = mHardwareMixerThread->streamMute(AudioSystem::MUSIC);
-                    LOGV("++mForcedSpeakerCount == 0, mMusicMuteSaved = %d, mRouteRestoreTime = %d", mMusicMuteSaved, mRouteRestoreTime);
-                    if (!(mSavedRoute & AudioSystem::ROUTE_SPEAKER)) {
-                        LOGV("Route forced to Speaker ON %08x", mSavedRoute | AudioSystem::ROUTE_SPEAKER);
-                        mHardwareMixerThread->setStreamMute(AudioSystem::MUSIC, true);
-                        usleep(mHardwareMixerThread->latency()*1000);
-                        mHardwareStatus = AUDIO_HW_SET_ROUTING;
-                        mAudioHardware->setRouting(AudioSystem::MODE_NORMAL, mSavedRoute | AudioSystem::ROUTE_SPEAKER);
-                        mHardwareStatus = AUDIO_HW_IDLE;
-                        // delay track start so that audio hardware has time to siwtch routes
-                        usleep(kStartSleepTime);
-                    }
-                }
-                mForcedRoute = AudioSystem::ROUTE_SPEAKER;
-                mRouteRestoreTime = 0;
-            }
-            LOGV("mForcedSpeakerCount incremented to %d", mForcedSpeakerCount);
-        }
-        break;
-    case ACTIVE_TRACK_REMOVED:
-        {
-            AutoMutex lock(mHardwareLock);
-            if (mForcedSpeakerCount > 0){
-                if (--mForcedSpeakerCount == 0) {
-                    mRouteRestoreTime = systemTime() + milliseconds(kStopSleepTime/1000);
-                }
-                LOGV("mForcedSpeakerCount decremented to %d", mForcedSpeakerCount);
-            } else {
-                LOGE("mForcedSpeakerCount is already zero");
-            }
-        }
-        break;
-    case CHECK_ROUTE_RESTORE_TIME:
-    case FORCE_ROUTE_RESTORE:
-        if (mRouteRestoreTime) {
-            AutoMutex lock(mHardwareLock);
-            if (mRouteRestoreTime && 
-               (systemTime() > mRouteRestoreTime || command == FORCE_ROUTE_RESTORE)) {
-                mHardwareMixerThread->setStreamMute(AudioSystem::MUSIC, mMusicMuteSaved);
-                mForcedRoute = 0;
-                if (!(mSavedRoute & AudioSystem::ROUTE_SPEAKER)) {
-                    mHardwareStatus = AUDIO_HW_SET_ROUTING;
-                    mAudioHardware->setRouting(AudioSystem::MODE_NORMAL, mSavedRoute);
-                    mHardwareStatus = AUDIO_HW_IDLE;
-                    LOGV("Route forced to Speaker OFF %08x", mSavedRoute);
-                }
-                mRouteRestoreTime = 0;
-            }
-        }
-        break;
-    }
+    mParamCond.broadcast();
+    mNewParameters.clear();
 }
 
-#ifdef WITH_A2DP
-// handleRouteDisablesA2dp_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::handleRouteDisablesA2dp_l(int routes)
+void AudioFlinger::ThreadBase::exit()
 {
-   if (routes & AudioSystem::ROUTE_BLUETOOTH_SCO) {
-        if (mA2dpDisableCount++ == 0) {
-            if (mA2dpEnabled) {
-                setA2dpEnabled_l(false);
-                mA2dpSuppressed = true;
-            }
-        }
-        LOGV("mA2dpDisableCount incremented to %d", mA2dpDisableCount);
-   } else {
-        if (mA2dpDisableCount > 0) {
-            if (--mA2dpDisableCount == 0) {
-                if (mA2dpSuppressed) {
-                    setA2dpEnabled_l(true);
-                    mA2dpSuppressed = false;
-                }
-            }
-            LOGV("mA2dpDisableCount decremented to %d", mA2dpDisableCount);
-        } else {
-            LOGV("mA2dpDisableCount is already zero");
-        }
+    // keep a strong ref on ourself so that we wont get
+    // destroyed in the middle of requestExitAndWait()
+    sp <ThreadBase> strongMe = this;
+
+    LOGV("ThreadBase::exit");
+    {
+        AutoMutex lock(&mLock);
+        requestExit();
+        mWaitWorkCV.signal();
     }
+    requestExitAndWait();
 }
-#endif
+
+uint32_t AudioFlinger::ThreadBase::sampleRate() const
+{
+    return mSampleRate;
+}
+
+int AudioFlinger::ThreadBase::channelCount() const
+{
+    return mChannelCount;
+}
+
+int AudioFlinger::ThreadBase::format() const
+{
+    return mFormat;
+}
+
+size_t AudioFlinger::ThreadBase::frameCount() const
+{
+    return mFrameCount;
+}
+
+status_t AudioFlinger::ThreadBase::setParameters(const String8& keyValuePairs)
+{
+    status_t status;
+
+    LOGV("ThreadBase::setParameters() %s", keyValuePairs.string());
+    Mutex::Autolock _l(mLock);
+
+    mNewParameters.add(keyValuePairs);
+    mWaitWorkCV.signal();
+    // wait condition with timeout in case the thread loop has exited
+    // before the request could be processed
+    if (mParamCond.waitRelative(mLock, seconds(2)) == NO_ERROR) {
+        status = mParamStatus;
+        mWaitWorkCV.signal();
+    } else {
+        status = TIMED_OUT;
+    }
+    return status;
+}
+
+void AudioFlinger::ThreadBase::sendConfigEvent(int event, int param)
+{
+    Mutex::Autolock _l(mLock);
+    sendConfigEvent_l(event, param);
+}
+
+// sendConfigEvent_l() must be called with ThreadBase::mLock held
+void AudioFlinger::ThreadBase::sendConfigEvent_l(int event, int param)
+{
+    ConfigEvent *configEvent = new ConfigEvent();
+    configEvent->mEvent = event;
+    configEvent->mParam = param;
+    mConfigEvents.add(configEvent);
+    LOGV("sendConfigEvent() num events %d event %d, param %d", mConfigEvents.size(), event, param);
+    mWaitWorkCV.signal();
+}
+
+void AudioFlinger::ThreadBase::processConfigEvents()
+{
+    mLock.lock();
+    while(!mConfigEvents.isEmpty()) {
+        LOGV("processConfigEvents() remaining events %d", mConfigEvents.size());
+        ConfigEvent *configEvent = mConfigEvents[0];
+        mConfigEvents.removeAt(0);
+        // release mLock because audioConfigChanged() will lock AudioFlinger mLock
+        // before calling Audioflinger::audioConfigChanged_l() thus creating
+        // potential cross deadlock between AudioFlinger::mLock and mLock
+        mLock.unlock();
+        audioConfigChanged(configEvent->mEvent, configEvent->mParam);
+        delete configEvent;
+        mLock.lock();
+    }
+    mLock.unlock();
+}
+
+status_t AudioFlinger::ThreadBase::dumpBase(int fd, const Vector<String16>& args)
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+
+    bool locked = tryLock(mLock);
+    if (!locked) {
+        snprintf(buffer, SIZE, "thread %p maybe dead locked\n", this);
+        write(fd, buffer, strlen(buffer));
+    }
+
+    snprintf(buffer, SIZE, "standby: %d\n", mStandby);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "Sample rate: %d\n", mSampleRate);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "Frame count: %d\n", mFrameCount);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "Channel Count: %d\n", mChannelCount);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "Format: %d\n", mFormat);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "Frame size: %d\n", mFrameSize);
+    result.append(buffer);
+
+    snprintf(buffer, SIZE, "\nPending setParameters commands: \n");
+    result.append(buffer);
+    result.append(" Index Command");
+    for (size_t i = 0; i < mNewParameters.size(); ++i) {
+        snprintf(buffer, SIZE, "\n %02d    ", i);
+        result.append(buffer);
+        result.append(mNewParameters[i]);
+    }
+
+    snprintf(buffer, SIZE, "\n\nPending config events: \n");
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Index event param\n");
+    result.append(buffer);
+    for (size_t i = 0; i < mConfigEvents.size(); i++) {
+        snprintf(buffer, SIZE, " %02d    %02d    %d\n", i, mConfigEvents[i]->mEvent, mConfigEvents[i]->mParam);
+        result.append(buffer);
+    }
+    result.append("\n");
+
+    write(fd, result.string(), result.size());
+
+    if (locked) {
+        mLock.unlock();
+    }
+    return NO_ERROR;
+}
+
 
 // ----------------------------------------------------------------------------
 
-AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int outputType)
-    :   Thread(false),
-        mAudioFlinger(audioFlinger), mAudioMixer(0), mOutput(output), mOutputType(outputType), 
-        mSampleRate(0), mFrameCount(0), mChannelCount(0), mFormat(0), mMixBuffer(0),
-        mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mStandby(false),
-        mInWrite(false)
+AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output)
+    :   ThreadBase(audioFlinger),
+        mMixBuffer(0), mSuspended(0), mBytesWritten(0), mOutput(output),
+        mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mInWrite(false)
 {
-    mSampleRate = output->sampleRate();
-    mChannelCount = output->channelCount();
+    readOutputParameters();
 
-    // FIXME - Current mixer implementation only supports stereo output
-    if (mChannelCount == 1) {
-        LOGE("Invalid audio hardware channel count");
+    mMasterVolume = mAudioFlinger->masterVolume();
+    mMasterMute = mAudioFlinger->masterMute();
+
+    for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) {
+        mStreamTypes[stream].volume = mAudioFlinger->streamVolumeInternal(stream);
+        mStreamTypes[stream].mute = mAudioFlinger->streamMute(stream);
     }
-
-    mFormat = output->format();
-    mFrameCount = output->bufferSize() / output->channelCount() / sizeof(int16_t);
-    mAudioMixer = new AudioMixer(mFrameCount, output->sampleRate());
-
-    // FIXME - Current mixer implementation only supports stereo output: Always
-    // Allocate a stereo buffer even if HW output is mono.
-    mMixBuffer = new int16_t[mFrameCount * 2];
-    memset(mMixBuffer, 0, mFrameCount * 2 * sizeof(int16_t));
+    // notify client processes that a new input has been opened
+    sendConfigEvent(AudioSystem::OUTPUT_OPENED);
 }
 
-AudioFlinger::MixerThread::~MixerThread()
+AudioFlinger::PlaybackThread::~PlaybackThread()
 {
     delete [] mMixBuffer;
-    delete mAudioMixer;
 }
 
-status_t AudioFlinger::MixerThread::dump(int fd, const Vector<String16>& args)
+status_t AudioFlinger::PlaybackThread::dump(int fd, const Vector<String16>& args)
 {
     dumpInternals(fd, args);
     dumpTracks(fd, args);
     return NO_ERROR;
 }
 
-status_t AudioFlinger::MixerThread::dumpTracks(int fd, const Vector<String16>& args)
+status_t AudioFlinger::PlaybackThread::dumpTracks(int fd, const Vector<String16>& args)
 {
     const size_t SIZE = 256;
     char buffer[SIZE];
     String8 result;
 
-    snprintf(buffer, SIZE, "Output %d mixer thread tracks\n", mOutputType);
+    snprintf(buffer, SIZE, "Output thread %p tracks\n", this);
     result.append(buffer);
-    result.append("   Name Clien Typ Fmt Chn Buf S M F SRate LeftV RighV Serv User\n");
+    result.append("   Name Clien Typ Fmt Chn Buf  S M F SRate  LeftV RighV Serv     User\n");
     for (size_t i = 0; i < mTracks.size(); ++i) {
         sp<Track> track = mTracks[i];
         if (track != 0) {
@@ -959,9 +917,9 @@
         }
     }
 
-    snprintf(buffer, SIZE, "Output %d mixer thread active tracks\n", mOutputType);
+    snprintf(buffer, SIZE, "Output thread %p active tracks\n", this);
     result.append(buffer);
-    result.append("   Name Clien Typ Fmt Chn Buf S M F SRate LeftV RighV Serv User\n");
+    result.append("   Name Clien Typ Fmt Chn Buf  S M F SRate  LeftV RighV Serv     User\n");
     for (size_t i = 0; i < mActiveTracks.size(); ++i) {
         wp<Track> wTrack = mActiveTracks[i];
         if (wTrack != 0) {
@@ -976,15 +934,13 @@
     return NO_ERROR;
 }
 
-status_t AudioFlinger::MixerThread::dumpInternals(int fd, const Vector<String16>& args)
+status_t AudioFlinger::PlaybackThread::dumpInternals(int fd, const Vector<String16>& args)
 {
     const size_t SIZE = 256;
     char buffer[SIZE];
     String8 result;
 
-    snprintf(buffer, SIZE, "Output %d mixer thread internals\n", mOutputType);
-    result.append(buffer);
-    snprintf(buffer, SIZE, "AudioMixer tracks: %08x\n", mAudioMixer->trackNames());
+    snprintf(buffer, SIZE, "\nOutput thread %p internals\n", this);
     result.append(buffer);
     snprintf(buffer, SIZE, "last write occurred (msecs): %llu\n", ns2ms(systemTime() - mLastWriteTime));
     result.append(buffer);
@@ -994,282 +950,36 @@
     result.append(buffer);
     snprintf(buffer, SIZE, "blocked in write: %d\n", mInWrite);
     result.append(buffer);
-    snprintf(buffer, SIZE, "standby: %d\n", mStandby);
-    result.append(buffer);
     write(fd, result.string(), result.size());
+
+    dumpBase(fd, args);
+
     return NO_ERROR;
 }
 
 // Thread virtuals
-bool AudioFlinger::MixerThread::threadLoop()
-{
-    unsigned long sleepTime = kBufferRecoveryInUsecs;
-    int16_t* curBuf = mMixBuffer;
-    Vector< sp<Track> > tracksToRemove;
-    size_t enabledTracks = 0;
-    nsecs_t standbyTime = systemTime();   
-    size_t mixBufferSize = mFrameCount*mChannelCount*sizeof(int16_t);
-    nsecs_t maxPeriod = seconds(mFrameCount) / mSampleRate * 2;
-
-#ifdef WITH_A2DP
-    bool outputTrackActive = false;
-#endif
-
-    do {
-        enabledTracks = 0;
-        { // scope for the AudioFlinger::mLock
-        
-            Mutex::Autolock _l(mAudioFlinger->mLock);
-
-#ifdef WITH_A2DP
-            if (mOutputTrack != NULL && !mAudioFlinger->isA2dpEnabled()) {
-                if (outputTrackActive) {
-                    mAudioFlinger->mLock.unlock();
-                    mOutputTrack->stop();
-                    mAudioFlinger->mLock.lock();
-                    outputTrackActive = false;
-                }
-            }
-            mAudioFlinger->checkA2dpEnabledChange_l();
-#endif
-
-            const SortedVector< wp<Track> >& activeTracks = mActiveTracks;
-
-            // put audio hardware into standby after short delay
-            if UNLIKELY(!activeTracks.size() && systemTime() > standbyTime) {
-                // wait until we have something to do...
-                LOGV("Audio hardware entering standby, output %d\n", mOutputType);
-                if (!mStandby) {
-                    mOutput->standby();
-                    mStandby = true;
-                }
-                
-#ifdef WITH_A2DP
-                if (outputTrackActive) {
-                    mAudioFlinger->mLock.unlock();
-                    mOutputTrack->stop();
-                    mAudioFlinger->mLock.lock();
-                    outputTrackActive = false;
-                }
-#endif
-                if (mOutputType == AudioSystem::AUDIO_OUTPUT_HARDWARE) {
-                    mAudioFlinger->handleForcedSpeakerRoute(FORCE_ROUTE_RESTORE);
-                }                
-                // we're about to wait, flush the binder command buffer
-                IPCThreadState::self()->flushCommands();
-                mAudioFlinger->mWaitWorkCV.wait(mAudioFlinger->mLock);
-                LOGV("Audio hardware exiting standby, output %d\n", mOutputType);
-                
-                if (mMasterMute == false) {
-                    char value[PROPERTY_VALUE_MAX];
-                    property_get("ro.audio.silent", value, "0");
-                    if (atoi(value)) {
-                        LOGD("Silence is golden");
-                        setMasterMute(true);
-                    }                    
-                }
-                
-                standbyTime = systemTime() + kStandbyTimeInNsecs;
-                continue;
-            }
-
-            // Forced route to speaker is handled by hardware mixer thread
-            if (mOutputType == AudioSystem::AUDIO_OUTPUT_HARDWARE) {
-                mAudioFlinger->handleForcedSpeakerRoute(CHECK_ROUTE_RESTORE_TIME);
-            }
-
-            // find out which tracks need to be processed
-            size_t count = activeTracks.size();
-            for (size_t i=0 ; i<count ; i++) {
-                sp<Track> t = activeTracks[i].promote();
-                if (t == 0) continue;
-
-                Track* const track = t.get();
-                audio_track_cblk_t* cblk = track->cblk();
-
-                // The first time a track is added we wait
-                // for all its buffers to be filled before processing it
-                mAudioMixer->setActiveTrack(track->name());
-                if (cblk->framesReady() && (track->isReady() || track->isStopped()) &&
-                        !track->isPaused())
-                {
-                    //LOGV("track %d u=%08x, s=%08x [OK]", track->name(), cblk->user, cblk->server);
-
-                    // compute volume for this track
-                    int16_t left, right;
-                    if (track->isMuted() || mMasterMute || track->isPausing()) {
-                        left = right = 0;
-                        if (track->isPausing()) {
-                            LOGV("paused(%d)", track->name());
-                            track->setPaused();
-                        }
-                    } else {
-                        float typeVolume = mStreamTypes[track->type()].volume;
-                        float v = mMasterVolume * typeVolume;
-                        float v_clamped = v * cblk->volume[0];
-                        if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
-                        left = int16_t(v_clamped);
-                        v_clamped = v * cblk->volume[1];
-                        if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
-                        right = int16_t(v_clamped);
-                    }
-
-                    // XXX: these things DON'T need to be done each time
-                    mAudioMixer->setBufferProvider(track);
-                    mAudioMixer->enable(AudioMixer::MIXING);
-
-                    int param;
-                    if ( track->mFillingUpStatus == Track::FS_FILLED) {
-                        // no ramp for the first volume setting
-                        track->mFillingUpStatus = Track::FS_ACTIVE;
-                        if (track->mState == TrackBase::RESUMING) {
-                            track->mState = TrackBase::ACTIVE;
-                            param = AudioMixer::RAMP_VOLUME;
-                        } else {
-                            param = AudioMixer::VOLUME;
-                        }
-                    } else {
-                        param = AudioMixer::RAMP_VOLUME;
-                    }
-                    mAudioMixer->setParameter(param, AudioMixer::VOLUME0, left);
-                    mAudioMixer->setParameter(param, AudioMixer::VOLUME1, right);
-                    mAudioMixer->setParameter(
-                        AudioMixer::TRACK,
-                        AudioMixer::FORMAT, track->format());
-                    mAudioMixer->setParameter(
-                        AudioMixer::TRACK,
-                        AudioMixer::CHANNEL_COUNT, track->channelCount());
-                    mAudioMixer->setParameter(
-                        AudioMixer::RESAMPLE,
-                        AudioMixer::SAMPLE_RATE,
-                        int(cblk->sampleRate));
-
-                    // reset retry count
-                    track->mRetryCount = kMaxTrackRetries;
-                    enabledTracks++;
-                } else {
-                    //LOGV("track %d u=%08x, s=%08x [NOT READY]", track->name(), cblk->user, cblk->server);
-                    if (track->isStopped()) {
-                        track->reset();
-                    }
-                    if (track->isTerminated() || track->isStopped() || track->isPaused()) {
-                        // We have consumed all the buffers of this track.
-                        // Remove it from the list of active tracks.
-                        LOGV("remove(%d) from active list", track->name());
-                        tracksToRemove.add(track);
-                    } else {
-                        // No buffers for this track. Give it a few chances to
-                        // fill a buffer, then remove it from active list.
-                        if (--(track->mRetryCount) <= 0) {
-                            LOGV("BUFFER TIMEOUT: remove(%d) from active list", track->name());
-                            tracksToRemove.add(track);
-                        }
-                    }
-                    // LOGV("disable(%d)", track->name());
-                    mAudioMixer->disable(AudioMixer::MIXING);
-                }
-            }
-
-            // remove all the tracks that need to be...
-            count = tracksToRemove.size();
-            if (UNLIKELY(count)) {
-                for (size_t i=0 ; i<count ; i++) {
-                    const sp<Track>& track = tracksToRemove[i];
-                    removeActiveTrack_l(track);
-                    if (track->isTerminated()) {
-                        mTracks.remove(track);
-                        deleteTrackName_l(track->mName);
-                    }
-                }
-            }
-       }
-        
-        if (LIKELY(enabledTracks)) {
-            // mix buffers...
-            mAudioMixer->process(curBuf);
-
-#ifdef WITH_A2DP
-            if (mOutputTrack != NULL && mAudioFlinger->isA2dpEnabled()) {
-                if (!outputTrackActive) {
-                    LOGV("starting output track in mixer for output %d", mOutputType);
-                    mOutputTrack->start();
-                    outputTrackActive = true;
-                }
-                mOutputTrack->write(curBuf, mFrameCount);
-            }
-#endif
-
-            // output audio to hardware
-            mLastWriteTime = systemTime();
-            mInWrite = true;
-            mOutput->write(curBuf, mixBufferSize);
-            mNumWrites++;
-            mInWrite = false;
-            mStandby = false;
-            nsecs_t temp = systemTime();
-            standbyTime = temp + kStandbyTimeInNsecs;
-            nsecs_t delta = temp - mLastWriteTime;
-            if (delta > maxPeriod) {
-                LOGW("write blocked for %llu msecs", ns2ms(delta));
-                mNumDelayedWrites++;
-            }
-            sleepTime = kBufferRecoveryInUsecs;
-        } else {         
-#ifdef WITH_A2DP
-            if (mOutputTrack != NULL && mAudioFlinger->isA2dpEnabled()) {
-                if (outputTrackActive) {
-                    mOutputTrack->write(curBuf, 0);
-                    if (mOutputTrack->bufferQueueEmpty()) {
-                        mOutputTrack->stop();
-                        outputTrackActive = false;
-                    } else {
-                        standbyTime = systemTime() + kStandbyTimeInNsecs;
-                    }
-                }
-            }
-#endif
-            // There was nothing to mix this round, which means all
-            // active tracks were late. Sleep a little bit to give
-            // them another chance. If we're too late, the audio
-            // hardware will zero-fill for us.
-            //LOGV("no buffers - usleep(%lu)", sleepTime);
-            usleep(sleepTime);
-            if (sleepTime < kMaxBufferRecoveryInUsecs) {
-                sleepTime += kBufferRecoveryInUsecs;
-            }
-        }
-
-        // finally let go of all our tracks, without the lock held
-        // since we can't guarantee the destructors won't acquire that
-        // same lock.
-        tracksToRemove.clear();
-    } while (true);
-
-    return false;
-}
-
-status_t AudioFlinger::MixerThread::readyToRun()
+status_t AudioFlinger::PlaybackThread::readyToRun()
 {
     if (mSampleRate == 0) {
         LOGE("No working audio driver found.");
         return NO_INIT;
     }
-    LOGI("AudioFlinger's thread ready to run for output %d", mOutputType);
+    LOGI("AudioFlinger's thread %p ready to run", this);
     return NO_ERROR;
 }
 
-void AudioFlinger::MixerThread::onFirstRef()
+void AudioFlinger::PlaybackThread::onFirstRef()
 {
     const size_t SIZE = 256;
     char buffer[SIZE];
 
-    snprintf(buffer, SIZE, "Mixer Thread for output %d", mOutputType);
+    snprintf(buffer, SIZE, "Playback Thread %p", this);
 
     run(buffer, ANDROID_PRIORITY_URGENT_AUDIO);
 }
 
-// MixerThread::createTrack_l() must be called with AudioFlinger::mLock held
-sp<AudioFlinger::MixerThread::Track>  AudioFlinger::MixerThread::createTrack_l(
+// PlaybackThread::createTrack_l() must be called with AudioFlinger::mLock held
+sp<AudioFlinger::PlaybackThread::Track>  AudioFlinger::PlaybackThread::createTrack_l(
         const sp<AudioFlinger::Client>& client,
         int streamType,
         uint32_t sampleRate,
@@ -1281,28 +991,39 @@
 {
     sp<Track> track;
     status_t lStatus;
-    
-    // Resampler implementation limits input sampling rate to 2 x output sampling rate.
-    if (sampleRate > mSampleRate*2) {
-        LOGE("Sample rate out of range: %d mSampleRate %d", sampleRate, mSampleRate);
-        lStatus = BAD_VALUE;
-        goto Exit;
+
+    if (mType == DIRECT) {
+        if (sampleRate != mSampleRate || format != mFormat || channelCount != mChannelCount) {
+            LOGE("createTrack_l() Bad parameter:  sampleRate %d format %d, channelCount %d for output %p",
+                 sampleRate, format, channelCount, mOutput);
+            lStatus = BAD_VALUE;
+            goto Exit;
+        }
+    } else {
+        // Resampler implementation limits input sampling rate to 2 x output sampling rate.
+        if (sampleRate > mSampleRate*2) {
+            LOGE("Sample rate out of range: %d mSampleRate %d", sampleRate, mSampleRate);
+            lStatus = BAD_VALUE;
+            goto Exit;
+        }
     }
 
-
-    if (mSampleRate == 0) {
+    if (mOutput == 0) {
         LOGE("Audio driver not initialized.");
         lStatus = NO_INIT;
         goto Exit;
     }
 
-    track = new Track(this, client, streamType, sampleRate, format,
-            channelCount, frameCount, sharedBuffer);
-    if (track->getCblk() == NULL) {
-        lStatus = NO_MEMORY;
-        goto Exit;
+    { // scope for mLock
+        Mutex::Autolock _l(mLock);
+        track = new Track(this, client, streamType, sampleRate, format,
+                channelCount, frameCount, sharedBuffer);
+        if (track->getCblk() == NULL || track->name() < 0) {
+            lStatus = NO_MEMORY;
+            goto Exit;
+        }
+        mTracks.add(track);
     }
-    mTracks.add(track);
     lStatus = NO_ERROR;
 
 Exit:
@@ -1312,87 +1033,7 @@
     return track;
 }
 
-// getTracks_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::MixerThread::getTracks_l(
-        SortedVector < sp<Track> >& tracks,
-        SortedVector < wp<Track> >& activeTracks)
-{
-    size_t size = mTracks.size();
-    LOGV ("MixerThread::getTracks_l() for output %d, mTracks.size %d, mActiveTracks.size %d", mOutputType,  mTracks.size(), mActiveTracks.size());
-    for (size_t i = 0; i < size; i++) {
-        sp<Track> t = mTracks[i];
-        if (AudioSystem::routedToA2dpOutput(t->mStreamType)) {
-            tracks.add(t);
-            int j = mActiveTracks.indexOf(t);
-            if (j >= 0) {
-                t = mActiveTracks[j].promote();
-                if (t != NULL) {
-                    activeTracks.add(t);                                    
-                }                            
-            }
-        }
-    }
-
-    size = activeTracks.size();
-    for (size_t i = 0; i < size; i++) {
-        removeActiveTrack_l(activeTracks[i]);
-    }
-    
-    size = tracks.size();
-    for (size_t i = 0; i < size; i++) {
-        sp<Track> t = tracks[i];
-        mTracks.remove(t);
-        deleteTrackName_l(t->name());
-    }
-}
-
-// putTracks_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::MixerThread::putTracks_l(
-        SortedVector < sp<Track> >& tracks,
-        SortedVector < wp<Track> >& activeTracks)
-{
-
-    LOGV ("MixerThread::putTracks_l() for output %d, tracks.size %d, activeTracks.size %d", mOutputType,  tracks.size(), activeTracks.size());
-
-    size_t size = tracks.size();
-    for (size_t i = 0; i < size ; i++) {
-        sp<Track> t = tracks[i];
-        int name = getTrackName_l();
-
-        if (name < 0) return;
-        
-        t->mName = name;
-        t->mMixerThread = this;
-        mTracks.add(t);
-
-        int j = activeTracks.indexOf(t);
-        if (j >= 0) {
-            addActiveTrack_l(t);
-        }            
-    }
-}
-
-uint32_t AudioFlinger::MixerThread::sampleRate() const
-{
-    return mSampleRate;
-}
-
-int AudioFlinger::MixerThread::channelCount() const
-{
-    return mChannelCount;
-}
-
-int AudioFlinger::MixerThread::format() const
-{
-    return mFormat;
-}
-
-size_t AudioFlinger::MixerThread::frameCount() const
-{
-    return mFrameCount;
-}
-
-uint32_t AudioFlinger::MixerThread::latency() const
+uint32_t AudioFlinger::PlaybackThread::latency() const
 {
     if (mOutput) {
         return mOutput->latency();
@@ -1402,66 +1043,66 @@
     }
 }
 
-status_t AudioFlinger::MixerThread::setMasterVolume(float value)
+status_t AudioFlinger::PlaybackThread::setMasterVolume(float value)
 {
     mMasterVolume = value;
     return NO_ERROR;
 }
 
-status_t AudioFlinger::MixerThread::setMasterMute(bool muted)
+status_t AudioFlinger::PlaybackThread::setMasterMute(bool muted)
 {
     mMasterMute = muted;
     return NO_ERROR;
 }
 
-float AudioFlinger::MixerThread::masterVolume() const
+float AudioFlinger::PlaybackThread::masterVolume() const
 {
     return mMasterVolume;
 }
 
-bool AudioFlinger::MixerThread::masterMute() const
+bool AudioFlinger::PlaybackThread::masterMute() const
 {
     return mMasterMute;
 }
 
-status_t AudioFlinger::MixerThread::setStreamVolume(int stream, float value)
+status_t AudioFlinger::PlaybackThread::setStreamVolume(int stream, float value)
 {
     mStreamTypes[stream].volume = value;
     return NO_ERROR;
 }
 
-status_t AudioFlinger::MixerThread::setStreamMute(int stream, bool muted)
+status_t AudioFlinger::PlaybackThread::setStreamMute(int stream, bool muted)
 {
     mStreamTypes[stream].mute = muted;
     return NO_ERROR;
 }
 
-float AudioFlinger::MixerThread::streamVolume(int stream) const
+float AudioFlinger::PlaybackThread::streamVolume(int stream) const
 {
     return mStreamTypes[stream].volume;
 }
 
-bool AudioFlinger::MixerThread::streamMute(int stream) const
+bool AudioFlinger::PlaybackThread::streamMute(int stream) const
 {
     return mStreamTypes[stream].mute;
 }
 
-// isMusicActive_l() must be called with AudioFlinger::mLock held
-bool AudioFlinger::MixerThread::isMusicActive_l() const
+bool AudioFlinger::PlaybackThread::isMusicActive() const
 {
+    Mutex::Autolock _l(mLock);
     size_t count = mActiveTracks.size();
     for (size_t i = 0 ; i < count ; ++i) {
         sp<Track> t = mActiveTracks[i].promote();
         if (t == 0) continue;
         Track* const track = t.get();
-        if (t->mStreamType == AudioSystem::MUSIC)
+        if (t->type() == AudioSystem::MUSIC)
             return true;
     }
     return false;
 }
 
-// addTrack_l() must be called with AudioFlinger::mLock held
-status_t AudioFlinger::MixerThread::addTrack_l(const sp<Track>& track)
+// addTrack_l() must be called with ThreadBase::mLock held
+status_t AudioFlinger::PlaybackThread::addTrack_l(const sp<Track>& track)
 {
     status_t status = ALREADY_EXISTS;
 
@@ -1469,10 +1110,10 @@
     // in both cases "unstop" the track
     if (track->isPaused()) {
         track->mState = TrackBase::RESUMING;
-        LOGV("PAUSED => RESUMING (%d)", track->name());
+        LOGV("PAUSED => RESUMING (%d) on thread %p", track->name(), this);
     } else {
         track->mState = TrackBase::ACTIVE;
-        LOGV("? => ACTIVE (%d)", track->name());
+        LOGV("? => ACTIVE (%d) on thread %p", track->name(), this);
     }
     // set retry count for buffer fill
     track->mRetryCount = kMaxTrackStartupRetries;
@@ -1482,18 +1123,18 @@
         // effectively get the latency it requested.
         track->mFillingUpStatus = Track::FS_FILLING;
         track->mResetDone = false;
-        addActiveTrack_l(track);
+        mActiveTracks.add(track);
         status = NO_ERROR;
     }
-    
+
     LOGV("mWaitWorkCV.broadcast");
-    mAudioFlinger->mWaitWorkCV.broadcast();
+    mWaitWorkCV.broadcast();
 
     return status;
 }
 
-// destroyTrack_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::MixerThread::destroyTrack_l(const sp<Track>& track)
+// destroyTrack_l() must be called with ThreadBase::mLock held
+void AudioFlinger::PlaybackThread::destroyTrack_l(const sp<Track>& track)
 {
     track->mState = TrackBase::TERMINATED;
     if (mActiveTracks.indexOf(track) < 0) {
@@ -1503,62 +1144,956 @@
     }
 }
 
-// addActiveTrack_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::MixerThread::addActiveTrack_l(const wp<Track>& t)
+String8 AudioFlinger::PlaybackThread::getParameters(const String8& keys)
 {
-    mActiveTracks.add(t);
+    return mOutput->getParameters(keys);
+}
 
-    // Force routing to speaker for certain stream types
-    // The forced routing to speaker is managed by hardware mixer
-    if (mOutputType == AudioSystem::AUDIO_OUTPUT_HARDWARE) {
-        sp<Track> track = t.promote();
-        if (track == NULL) return;
-   
-        if (streamForcedToSpeaker(track->type())) {
-            mAudioFlinger->handleForcedSpeakerRoute(ACTIVE_TRACK_ADDED);
-        }        
+void AudioFlinger::PlaybackThread::audioConfigChanged(int event, int param) {
+    AudioSystem::OutputDescriptor desc;
+    void *param2 = 0;
+
+    LOGV("PlaybackThread::audioConfigChanged, thread %p, event %d, param %d", this, event, param);
+
+    switch (event) {
+    case AudioSystem::OUTPUT_OPENED:
+    case AudioSystem::OUTPUT_CONFIG_CHANGED:
+        desc.channels = mChannelCount;
+        desc.samplingRate = mSampleRate;
+        desc.format = mFormat;
+        desc.frameCount = mFrameCount;
+        desc.latency = latency();
+        param2 = &desc;
+        break;
+
+    case AudioSystem::STREAM_CONFIG_CHANGED:
+        param2 = &param;
+    case AudioSystem::OUTPUT_CLOSED:
+    default:
+        break;
+    }
+    Mutex::Autolock _l(mAudioFlinger->mLock);
+    mAudioFlinger->audioConfigChanged_l(event, this, param2);
+}
+
+void AudioFlinger::PlaybackThread::readOutputParameters()
+{
+    mSampleRate = mOutput->sampleRate();
+    mChannelCount = AudioSystem::popCount(mOutput->channels());
+
+    mFormat = mOutput->format();
+    mFrameSize = mOutput->frameSize();
+    mFrameCount = mOutput->bufferSize() / mFrameSize;
+
+    mMinBytesToWrite = (mOutput->latency() * mSampleRate * mFrameSize) / 1000;
+    // FIXME - Current mixer implementation only supports stereo output: Always
+    // Allocate a stereo buffer even if HW output is mono.
+    if (mMixBuffer != NULL) delete mMixBuffer;
+    mMixBuffer = new int16_t[mFrameCount * 2];
+    memset(mMixBuffer, 0, mFrameCount * 2 * sizeof(int16_t));
+}
+
+// ----------------------------------------------------------------------------
+
+AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output)
+    :   PlaybackThread(audioFlinger, output),
+        mAudioMixer(0)
+{
+    mType = PlaybackThread::MIXER;
+    mAudioMixer = new AudioMixer(mFrameCount, mSampleRate);
+
+    // FIXME - Current mixer implementation only supports stereo output
+    if (mChannelCount == 1) {
+        LOGE("Invalid audio hardware channel count");
     }
 }
 
-// removeActiveTrack_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::MixerThread::removeActiveTrack_l(const wp<Track>& t)
+AudioFlinger::MixerThread::~MixerThread()
 {
-    mActiveTracks.remove(t);
+    delete mAudioMixer;
+}
 
-    // Force routing to speaker for certain stream types
-    // The forced routing to speaker is managed by hardware mixer
-    if (mOutputType == AudioSystem::AUDIO_OUTPUT_HARDWARE) {
-        sp<Track> track = t.promote();
-        if (track == NULL) return;
+bool AudioFlinger::MixerThread::threadLoop()
+{
+    uint32_t sleepTime = 1000;
+    uint32_t maxBufferRecoveryInUsecs = getMaxBufferRecoveryInUsecs();
+    int16_t* curBuf = mMixBuffer;
+    Vector< sp<Track> > tracksToRemove;
+    size_t enabledTracks = 0;
+    nsecs_t standbyTime = systemTime();
+    size_t mixBufferSize = mFrameCount * mFrameSize;
+    // FIXME: Relaxed timing because of a certain device that can't meet latency
+    // Should be reduced to 2x after the vendor fixes the driver issue
+    nsecs_t maxPeriod = seconds(mFrameCount) / mSampleRate * 3;
+    nsecs_t lastWarning = 0;
 
-        if (streamForcedToSpeaker(track->type())) {
-            mAudioFlinger->handleForcedSpeakerRoute(ACTIVE_TRACK_REMOVED);
+    while (!exitPending())
+    {
+        processConfigEvents();
+
+        enabledTracks = 0;
+        { // scope for mLock
+
+            Mutex::Autolock _l(mLock);
+
+            if (checkForNewParameters_l()) {
+                mixBufferSize = mFrameCount * mFrameSize;
+                // FIXME: Relaxed timing because of a certain device that can't meet latency
+                // Should be reduced to 2x after the vendor fixes the driver issue
+                maxPeriod = seconds(mFrameCount) / mSampleRate * 3;
+                maxBufferRecoveryInUsecs = getMaxBufferRecoveryInUsecs();
+            }
+
+            const SortedVector< wp<Track> >& activeTracks = mActiveTracks;
+
+            // put audio hardware into standby after short delay
+            if UNLIKELY((!activeTracks.size() && systemTime() > standbyTime) ||
+                        mSuspended) {
+                if (!mStandby) {
+                    LOGV("Audio hardware entering standby, mixer %p, mSuspended %d\n", this, mSuspended);
+                    mOutput->standby();
+                    mStandby = true;
+                    mBytesWritten = 0;
+                }
+
+                if (!activeTracks.size() && mConfigEvents.isEmpty()) {
+                    // we're about to wait, flush the binder command buffer
+                    IPCThreadState::self()->flushCommands();
+
+                    if (exitPending()) break;
+
+                    // wait until we have something to do...
+                    LOGV("MixerThread %p TID %d going to sleep\n", this, gettid());
+                    mWaitWorkCV.wait(mLock);
+                    LOGV("MixerThread %p TID %d waking up\n", this, gettid());
+
+                    if (mMasterMute == false) {
+                        char value[PROPERTY_VALUE_MAX];
+                        property_get("ro.audio.silent", value, "0");
+                        if (atoi(value)) {
+                            LOGD("Silence is golden");
+                            setMasterMute(true);
+                        }
+                    }
+
+                    standbyTime = systemTime() + kStandbyTimeInNsecs;
+                    sleepTime = 1000;
+                    continue;
+                }
+            }
+
+            enabledTracks = prepareTracks_l(activeTracks, &tracksToRemove);
+       }
+
+        if (LIKELY(enabledTracks)) {
+            // mix buffers...
+            mAudioMixer->process(curBuf);
+            sleepTime = 0;
+            standbyTime = systemTime() + kStandbyTimeInNsecs;
+        } else {
+            // If no tracks are ready, sleep once for the duration of an output
+            // buffer size, then write 0s to the output
+            if (sleepTime == 0) {
+                sleepTime = maxBufferRecoveryInUsecs;
+            } else if (mBytesWritten != 0) {
+                memset (curBuf, 0, mixBufferSize);
+                sleepTime = 0;
+            }
+        }
+
+        if (mSuspended) {
+            sleepTime = maxBufferRecoveryInUsecs;
+        }
+        // sleepTime == 0 means we must write to audio hardware
+        if (sleepTime == 0) {
+            mLastWriteTime = systemTime();
+            mInWrite = true;
+            int bytesWritten = (int)mOutput->write(curBuf, mixBufferSize);
+            if (bytesWritten > 0) mBytesWritten += bytesWritten;
+            mNumWrites++;
+            mInWrite = false;
+            mStandby = false;
+            nsecs_t now = systemTime();
+            nsecs_t delta = now - mLastWriteTime;
+            if (delta > maxPeriod) {
+                mNumDelayedWrites++;
+                if ((now - lastWarning) > kWarningThrottle) {
+                    LOGW("write blocked for %llu msecs, %d delayed writes, thread %p",
+                            ns2ms(delta), mNumDelayedWrites, this);
+                    lastWarning = now;
+                }
+            }
+        } else {
+            usleep(sleepTime);
+        }
+
+        // finally let go of all our tracks, without the lock held
+        // since we can't guarantee the destructors won't acquire that
+        // same lock.
+        tracksToRemove.clear();
+    }
+
+    if (!mStandby) {
+        mOutput->standby();
+    }
+
+    LOGV("MixerThread %p exiting", this);
+    return false;
+}
+
+// prepareTracks_l() must be called with ThreadBase::mLock held
+size_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track> >& activeTracks, Vector< sp<Track> > *tracksToRemove)
+{
+
+    size_t enabledTracks = 0;
+    // find out which tracks need to be processed
+    size_t count = activeTracks.size();
+    for (size_t i=0 ; i<count ; i++) {
+        sp<Track> t = activeTracks[i].promote();
+        if (t == 0) continue;
+
+        Track* const track = t.get();
+        audio_track_cblk_t* cblk = track->cblk();
+
+        // The first time a track is added we wait
+        // for all its buffers to be filled before processing it
+        mAudioMixer->setActiveTrack(track->name());
+        if (cblk->framesReady() && (track->isReady() || track->isStopped()) &&
+                !track->isPaused())
+        {
+            //LOGV("track %d u=%08x, s=%08x [OK]", track->name(), cblk->user, cblk->server);
+
+            // compute volume for this track
+            int16_t left, right;
+            if (track->isMuted() || mMasterMute || track->isPausing() ||
+                mStreamTypes[track->type()].mute) {
+                left = right = 0;
+                if (track->isPausing()) {
+                    track->setPaused();
+                }
+            } else {
+                float typeVolume = mStreamTypes[track->type()].volume;
+                float v = mMasterVolume * typeVolume;
+                float v_clamped = v * cblk->volume[0];
+                if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
+                left = int16_t(v_clamped);
+                v_clamped = v * cblk->volume[1];
+                if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
+                right = int16_t(v_clamped);
+            }
+
+            // XXX: these things DON'T need to be done each time
+            mAudioMixer->setBufferProvider(track);
+            mAudioMixer->enable(AudioMixer::MIXING);
+
+            int param = AudioMixer::VOLUME;
+            if (track->mFillingUpStatus == Track::FS_FILLED) {
+                // no ramp for the first volume setting
+                track->mFillingUpStatus = Track::FS_ACTIVE;
+                if (track->mState == TrackBase::RESUMING) {
+                    track->mState = TrackBase::ACTIVE;
+                    param = AudioMixer::RAMP_VOLUME;
+                }
+            } else if (cblk->server != 0) {
+                // If the track is stopped before the first frame was mixed,
+                // do not apply ramp
+                param = AudioMixer::RAMP_VOLUME;
+            }
+
+            mAudioMixer->setParameter(param, AudioMixer::VOLUME0, left);
+            mAudioMixer->setParameter(param, AudioMixer::VOLUME1, right);
+            mAudioMixer->setParameter(
+                AudioMixer::TRACK,
+                AudioMixer::FORMAT, track->format());
+            mAudioMixer->setParameter(
+                AudioMixer::TRACK,
+                AudioMixer::CHANNEL_COUNT, track->channelCount());
+            mAudioMixer->setParameter(
+                AudioMixer::RESAMPLE,
+                AudioMixer::SAMPLE_RATE,
+                int(cblk->sampleRate));
+
+            // reset retry count
+            track->mRetryCount = kMaxTrackRetries;
+            enabledTracks++;
+        } else {
+            //LOGV("track %d u=%08x, s=%08x [NOT READY]", track->name(), cblk->user, cblk->server);
+            if (track->isStopped()) {
+                track->reset();
+            }
+            if (track->isTerminated() || track->isStopped() || track->isPaused()) {
+                // We have consumed all the buffers of this track.
+                // Remove it from the list of active tracks.
+                tracksToRemove->add(track);
+                mAudioMixer->disable(AudioMixer::MIXING);
+            } else {
+                // No buffers for this track. Give it a few chances to
+                // fill a buffer, then remove it from active list.
+                if (--(track->mRetryCount) <= 0) {
+                    LOGV("BUFFER TIMEOUT: remove(%d) from active list on thread %p", track->name(), this);
+                    tracksToRemove->add(track);
+                }
+                // For tracks using static shared memory buffer, make sure that we have
+                // written enough data to audio hardware before disabling the track
+                // NOTE: this condition with arrive before track->mRetryCount <= 0 so we
+                // don't care about code removing track from active list above.
+                if ((track->mSharedBuffer == 0) || (mBytesWritten >= mMinBytesToWrite)) {
+                    mAudioMixer->disable(AudioMixer::MIXING);
+                } else {
+                    enabledTracks++;
+                }
+            }
+        }
+    }
+
+    // remove all the tracks that need to be...
+    count = tracksToRemove->size();
+    if (UNLIKELY(count)) {
+        for (size_t i=0 ; i<count ; i++) {
+            const sp<Track>& track = tracksToRemove->itemAt(i);
+            mActiveTracks.remove(track);
+            if (track->isTerminated()) {
+                mTracks.remove(track);
+                deleteTrackName_l(track->mName);
+            }
+        }
+    }
+
+    return enabledTracks;
+}
+
+void AudioFlinger::MixerThread::getTracks(
+        SortedVector < sp<Track> >& tracks,
+        SortedVector < wp<Track> >& activeTracks,
+        int streamType)
+{
+    LOGV ("MixerThread::getTracks() mixer %p, mTracks.size %d, mActiveTracks.size %d", this,  mTracks.size(), mActiveTracks.size());
+    Mutex::Autolock _l(mLock);
+    size_t size = mTracks.size();
+    for (size_t i = 0; i < size; i++) {
+        sp<Track> t = mTracks[i];
+        if (t->type() == streamType) {
+            tracks.add(t);
+            int j = mActiveTracks.indexOf(t);
+            if (j >= 0) {
+                t = mActiveTracks[j].promote();
+                if (t != NULL) {
+                    activeTracks.add(t);
+                }
+            }
+        }
+    }
+
+    size = activeTracks.size();
+    for (size_t i = 0; i < size; i++) {
+        mActiveTracks.remove(activeTracks[i]);
+    }
+
+    size = tracks.size();
+    for (size_t i = 0; i < size; i++) {
+        sp<Track> t = tracks[i];
+        mTracks.remove(t);
+        deleteTrackName_l(t->name());
+    }
+}
+
+void AudioFlinger::MixerThread::putTracks(
+        SortedVector < sp<Track> >& tracks,
+        SortedVector < wp<Track> >& activeTracks)
+{
+    LOGV ("MixerThread::putTracks() mixer %p, tracks.size %d, activeTracks.size %d", this,  tracks.size(), activeTracks.size());
+    Mutex::Autolock _l(mLock);
+    size_t size = tracks.size();
+    for (size_t i = 0; i < size ; i++) {
+        sp<Track> t = tracks[i];
+        int name = getTrackName_l();
+
+        if (name < 0) return;
+
+        t->mName = name;
+        t->mThread = this;
+        mTracks.add(t);
+
+        int j = activeTracks.indexOf(t);
+        if (j >= 0) {
+            mActiveTracks.add(t);
+            // force buffer refilling and no ramp volume when the track is mixed for the first time
+            t->mFillingUpStatus = Track::FS_FILLING;
         }
     }
 }
 
-// getTrackName_l() must be called with AudioFlinger::mLock held
+// getTrackName_l() must be called with ThreadBase::mLock held
 int AudioFlinger::MixerThread::getTrackName_l()
 {
     return mAudioMixer->getTrackName();
 }
 
-// deleteTrackName_l() must be called with AudioFlinger::mLock held
+// deleteTrackName_l() must be called with ThreadBase::mLock held
 void AudioFlinger::MixerThread::deleteTrackName_l(int name)
 {
     mAudioMixer->deleteTrackName(name);
 }
 
-size_t AudioFlinger::MixerThread::getOutputFrameCount() 
+// checkForNewParameters_l() must be called with ThreadBase::mLock held
+bool AudioFlinger::MixerThread::checkForNewParameters_l()
 {
-    return mOutput->bufferSize() / mOutput->channelCount() / sizeof(int16_t);
+    bool reconfig = false;
+
+    while (!mNewParameters.isEmpty()) {
+        status_t status = NO_ERROR;
+        String8 keyValuePair = mNewParameters[0];
+        AudioParameter param = AudioParameter(keyValuePair);
+        int value;
+
+        if (param.getInt(String8(AudioParameter::keySamplingRate), value) == NO_ERROR) {
+            reconfig = true;
+        }
+        if (param.getInt(String8(AudioParameter::keyFormat), value) == NO_ERROR) {
+            if (value != AudioSystem::PCM_16_BIT) {
+                status = BAD_VALUE;
+            } else {
+                reconfig = true;
+            }
+        }
+        if (param.getInt(String8(AudioParameter::keyChannels), value) == NO_ERROR) {
+            if (value != AudioSystem::CHANNEL_OUT_STEREO) {
+                status = BAD_VALUE;
+            } else {
+                reconfig = true;
+            }
+        }
+        if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
+            // do not accept frame count changes if tracks are open as the track buffer
+            // size depends on frame count and correct behavior would not be garantied
+            // if frame count is changed after track creation
+            if (!mTracks.isEmpty()) {
+                status = INVALID_OPERATION;
+            } else {
+                reconfig = true;
+            }
+        }
+        if (status == NO_ERROR) {
+            status = mOutput->setParameters(keyValuePair);
+            if (!mStandby && status == INVALID_OPERATION) {
+               mOutput->standby();
+               mStandby = true;
+               mBytesWritten = 0;
+               status = mOutput->setParameters(keyValuePair);
+            }
+            if (status == NO_ERROR && reconfig) {
+                delete mAudioMixer;
+                readOutputParameters();
+                mAudioMixer = new AudioMixer(mFrameCount, mSampleRate);
+                for (size_t i = 0; i < mTracks.size() ; i++) {
+                    int name = getTrackName_l();
+                    if (name < 0) break;
+                    mTracks[i]->mName = name;
+                    // limit track sample rate to 2 x new output sample rate
+                    if (mTracks[i]->mCblk->sampleRate > 2 * sampleRate()) {
+                        mTracks[i]->mCblk->sampleRate = 2 * sampleRate();
+                    }
+                }
+                sendConfigEvent_l(AudioSystem::OUTPUT_CONFIG_CHANGED);
+            }
+        }
+
+        mNewParameters.removeAt(0);
+
+        mParamStatus = status;
+        mParamCond.signal();
+        mWaitWorkCV.wait(mLock);
+    }
+    return reconfig;
+}
+
+status_t AudioFlinger::MixerThread::dumpInternals(int fd, const Vector<String16>& args)
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+
+    PlaybackThread::dumpInternals(fd, args);
+
+    snprintf(buffer, SIZE, "AudioMixer tracks: %08x\n", mAudioMixer->trackNames());
+    result.append(buffer);
+    write(fd, result.string(), result.size());
+    return NO_ERROR;
+}
+
+uint32_t AudioFlinger::MixerThread::getMaxBufferRecoveryInUsecs()
+{
+    uint32_t time = ((mFrameCount * 1000) / mSampleRate) * 1000;
+    // Add some margin with regard to scheduling precision
+    if (time > 10000) {
+        time -= 10000;
+    }
+    return time;
+}
+
+// ----------------------------------------------------------------------------
+AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output)
+    :   PlaybackThread(audioFlinger, output),
+    mLeftVolume (1.0), mRightVolume(1.0)
+{
+    mType = PlaybackThread::DIRECT;
+}
+
+AudioFlinger::DirectOutputThread::~DirectOutputThread()
+{
+}
+
+
+bool AudioFlinger::DirectOutputThread::threadLoop()
+{
+    uint32_t sleepTime = 1000;
+    uint32_t maxBufferRecoveryInUsecs = getMaxBufferRecoveryInUsecs();
+    sp<Track> trackToRemove;
+    sp<Track> activeTrack;
+    nsecs_t standbyTime = systemTime();
+    int8_t *curBuf;
+    size_t mixBufferSize = mFrameCount*mFrameSize;
+
+    while (!exitPending())
+    {
+        processConfigEvents();
+
+        { // scope for the mLock
+
+            Mutex::Autolock _l(mLock);
+
+            if (checkForNewParameters_l()) {
+                mixBufferSize = mFrameCount*mFrameSize;
+                maxBufferRecoveryInUsecs = getMaxBufferRecoveryInUsecs();
+            }
+
+            // put audio hardware into standby after short delay
+            if UNLIKELY((!mActiveTracks.size() && systemTime() > standbyTime) ||
+                        mSuspended) {
+                // wait until we have something to do...
+                if (!mStandby) {
+                    LOGV("Audio hardware entering standby, mixer %p\n", this);
+                    mOutput->standby();
+                    mStandby = true;
+                    mBytesWritten = 0;
+                }
+
+                if (!mActiveTracks.size() && mConfigEvents.isEmpty()) {
+                    // we're about to wait, flush the binder command buffer
+                    IPCThreadState::self()->flushCommands();
+
+                    if (exitPending()) break;
+
+                    LOGV("DirectOutputThread %p TID %d going to sleep\n", this, gettid());
+                    mWaitWorkCV.wait(mLock);
+                    LOGV("DirectOutputThread %p TID %d waking up in active mode\n", this, gettid());
+
+                    if (mMasterMute == false) {
+                        char value[PROPERTY_VALUE_MAX];
+                        property_get("ro.audio.silent", value, "0");
+                        if (atoi(value)) {
+                            LOGD("Silence is golden");
+                            setMasterMute(true);
+                        }
+                    }
+
+                    standbyTime = systemTime() + kStandbyTimeInNsecs;
+                    sleepTime = 1000;
+                    continue;
+                }
+            }
+
+            // find out which tracks need to be processed
+            if (mActiveTracks.size() != 0) {
+                sp<Track> t = mActiveTracks[0].promote();
+                if (t == 0) continue;
+
+                Track* const track = t.get();
+                audio_track_cblk_t* cblk = track->cblk();
+
+                // The first time a track is added we wait
+                // for all its buffers to be filled before processing it
+                if (cblk->framesReady() && (track->isReady() || track->isStopped()) &&
+                        !track->isPaused())
+                {
+                    //LOGV("track %d u=%08x, s=%08x [OK]", track->name(), cblk->user, cblk->server);
+
+                    // compute volume for this track
+                    float left, right;
+                    if (track->isMuted() || mMasterMute || track->isPausing() ||
+                        mStreamTypes[track->type()].mute) {
+                        left = right = 0;
+                        if (track->isPausing()) {
+                            track->setPaused();
+                        }
+                    } else {
+                        float typeVolume = mStreamTypes[track->type()].volume;
+                        float v = mMasterVolume * typeVolume;
+                        float v_clamped = v * cblk->volume[0];
+                        if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
+                        left = v_clamped/MAX_GAIN;
+                        v_clamped = v * cblk->volume[1];
+                        if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
+                        right = v_clamped/MAX_GAIN;
+                    }
+
+                    if (left != mLeftVolume || right != mRightVolume) {
+                        mOutput->setVolume(left, right);
+                        left = mLeftVolume;
+                        right = mRightVolume;
+                    }
+
+                    if (track->mFillingUpStatus == Track::FS_FILLED) {
+                        track->mFillingUpStatus = Track::FS_ACTIVE;
+                        if (track->mState == TrackBase::RESUMING) {
+                            track->mState = TrackBase::ACTIVE;
+                        }
+                    }
+
+                    // reset retry count
+                    track->mRetryCount = kMaxTrackRetries;
+                    activeTrack = t;
+                } else {
+                    //LOGV("track %d u=%08x, s=%08x [NOT READY]", track->name(), cblk->user, cblk->server);
+                    if (track->isStopped()) {
+                        track->reset();
+                    }
+                    if (track->isTerminated() || track->isStopped() || track->isPaused()) {
+                        // We have consumed all the buffers of this track.
+                        // Remove it from the list of active tracks.
+                        trackToRemove = track;
+                    } else {
+                        // No buffers for this track. Give it a few chances to
+                        // fill a buffer, then remove it from active list.
+                        if (--(track->mRetryCount) <= 0) {
+                            LOGV("BUFFER TIMEOUT: remove(%d) from active list", track->name());
+                            trackToRemove = track;
+                        }
+
+                        // For tracks using static shared memry buffer, make sure that we have
+                        // written enough data to audio hardware before disabling the track
+                        // NOTE: this condition with arrive before track->mRetryCount <= 0 so we
+                        // don't care about code removing track from active list above.
+                        if ((track->mSharedBuffer != 0) && (mBytesWritten < mMinBytesToWrite)) {
+                            activeTrack = t;
+                        }
+                     }
+                }
+            }
+
+            // remove all the tracks that need to be...
+            if (UNLIKELY(trackToRemove != 0)) {
+                mActiveTracks.remove(trackToRemove);
+                if (trackToRemove->isTerminated()) {
+                    mTracks.remove(trackToRemove);
+                    deleteTrackName_l(trackToRemove->mName);
+                }
+            }
+       }
+
+        if (activeTrack != 0) {
+            AudioBufferProvider::Buffer buffer;
+            size_t frameCount = mFrameCount;
+            curBuf = (int8_t *)mMixBuffer;
+            // output audio to hardware
+            while(frameCount) {
+                buffer.frameCount = frameCount;
+                activeTrack->getNextBuffer(&buffer);
+                if (UNLIKELY(buffer.raw == 0)) {
+                    memset(curBuf, 0, frameCount * mFrameSize);
+                    break;
+                }
+                memcpy(curBuf, buffer.raw, buffer.frameCount * mFrameSize);
+                frameCount -= buffer.frameCount;
+                curBuf += buffer.frameCount * mFrameSize;
+                activeTrack->releaseBuffer(&buffer);
+            }
+            sleepTime = 0;
+            standbyTime = systemTime() + kStandbyTimeInNsecs;
+        } else {
+            if (sleepTime == 0) {
+                sleepTime = maxBufferRecoveryInUsecs;
+            } else if (mBytesWritten != 0 && AudioSystem::isLinearPCM(mFormat)) {
+                memset (mMixBuffer, 0, mFrameCount * mFrameSize);
+                sleepTime = 0;
+            }
+        }
+
+        if (mSuspended) {
+            sleepTime = maxBufferRecoveryInUsecs;
+        }
+        // sleepTime == 0 means we must write to audio hardware
+        if (sleepTime == 0) {
+            mLastWriteTime = systemTime();
+            mInWrite = true;
+            int bytesWritten = (int)mOutput->write(mMixBuffer, mixBufferSize);
+            if (bytesWritten) mBytesWritten += bytesWritten;
+            mNumWrites++;
+            mInWrite = false;
+            mStandby = false;
+        } else {
+            usleep(sleepTime);
+        }
+
+        // finally let go of removed track, without the lock held
+        // since we can't guarantee the destructors won't acquire that
+        // same lock.
+        trackToRemove.clear();
+        activeTrack.clear();
+    }
+
+    if (!mStandby) {
+        mOutput->standby();
+    }
+
+    LOGV("DirectOutputThread %p exiting", this);
+    return false;
+}
+
+// getTrackName_l() must be called with ThreadBase::mLock held
+int AudioFlinger::DirectOutputThread::getTrackName_l()
+{
+    return 0;
+}
+
+// deleteTrackName_l() must be called with ThreadBase::mLock held
+void AudioFlinger::DirectOutputThread::deleteTrackName_l(int name)
+{
+}
+
+// checkForNewParameters_l() must be called with ThreadBase::mLock held
+bool AudioFlinger::DirectOutputThread::checkForNewParameters_l()
+{
+    bool reconfig = false;
+
+    while (!mNewParameters.isEmpty()) {
+        status_t status = NO_ERROR;
+        String8 keyValuePair = mNewParameters[0];
+        AudioParameter param = AudioParameter(keyValuePair);
+        int value;
+
+        if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
+            // do not accept frame count changes if tracks are open as the track buffer
+            // size depends on frame count and correct behavior would not be garantied
+            // if frame count is changed after track creation
+            if (!mTracks.isEmpty()) {
+                status = INVALID_OPERATION;
+            } else {
+                reconfig = true;
+            }
+        }
+        if (status == NO_ERROR) {
+            status = mOutput->setParameters(keyValuePair);
+            if (!mStandby && status == INVALID_OPERATION) {
+               mOutput->standby();
+               mStandby = true;
+               mBytesWritten = 0;
+               status = mOutput->setParameters(keyValuePair);
+            }
+            if (status == NO_ERROR && reconfig) {
+                readOutputParameters();
+                sendConfigEvent_l(AudioSystem::OUTPUT_CONFIG_CHANGED);
+            }
+        }
+
+        mNewParameters.removeAt(0);
+
+        mParamStatus = status;
+        mParamCond.signal();
+        mWaitWorkCV.wait(mLock);
+    }
+    return reconfig;
+}
+
+uint32_t AudioFlinger::DirectOutputThread::getMaxBufferRecoveryInUsecs()
+{
+    uint32_t time;
+    if (AudioSystem::isLinearPCM(mFormat)) {
+        time = ((mFrameCount * 1000) / mSampleRate) * 1000;
+        // Add some margin with regard to scheduling precision
+        if (time > 10000) {
+            time -= 10000;
+        }
+    } else {
+        time = 10000;
+    }
+    return time;
+}
+
+// ----------------------------------------------------------------------------
+
+AudioFlinger::DuplicatingThread::DuplicatingThread(const sp<AudioFlinger>& audioFlinger, AudioFlinger::MixerThread* mainThread)
+    :   MixerThread(audioFlinger, mainThread->getOutput())
+{
+    mType = PlaybackThread::DUPLICATING;
+    addOutputTrack(mainThread);
+}
+
+AudioFlinger::DuplicatingThread::~DuplicatingThread()
+{
+    mOutputTracks.clear();
+}
+
+bool AudioFlinger::DuplicatingThread::threadLoop()
+{
+    uint32_t sleepTime = 1000;
+    uint32_t maxBufferRecoveryInUsecs = getMaxBufferRecoveryInUsecs();
+    int16_t* curBuf = mMixBuffer;
+    Vector< sp<Track> > tracksToRemove;
+    size_t enabledTracks = 0;
+    nsecs_t standbyTime = systemTime();
+    size_t mixBufferSize = mFrameCount*mFrameSize;
+    SortedVector< sp<OutputTrack> > outputTracks;
+    uint32_t writeFrames = 0;
+
+    while (!exitPending())
+    {
+        processConfigEvents();
+
+        enabledTracks = 0;
+        { // scope for the mLock
+
+            Mutex::Autolock _l(mLock);
+
+            if (checkForNewParameters_l()) {
+                mixBufferSize = mFrameCount*mFrameSize;
+                maxBufferRecoveryInUsecs = getMaxBufferRecoveryInUsecs();
+            }
+
+            const SortedVector< wp<Track> >& activeTracks = mActiveTracks;
+
+            for (size_t i = 0; i < mOutputTracks.size(); i++) {
+                outputTracks.add(mOutputTracks[i]);
+            }
+
+            // put audio hardware into standby after short delay
+            if UNLIKELY((!activeTracks.size() && systemTime() > standbyTime) ||
+                         mSuspended) {
+                if (!mStandby) {
+                    for (size_t i = 0; i < outputTracks.size(); i++) {
+                        outputTracks[i]->stop();
+                    }
+                    mStandby = true;
+                    mBytesWritten = 0;
+                }
+
+                if (!activeTracks.size() && mConfigEvents.isEmpty()) {
+                    // we're about to wait, flush the binder command buffer
+                    IPCThreadState::self()->flushCommands();
+                    outputTracks.clear();
+
+                    if (exitPending()) break;
+
+                    LOGV("DuplicatingThread %p TID %d going to sleep\n", this, gettid());
+                    mWaitWorkCV.wait(mLock);
+                    LOGV("DuplicatingThread %p TID %d waking up\n", this, gettid());
+                    if (mMasterMute == false) {
+                        char value[PROPERTY_VALUE_MAX];
+                        property_get("ro.audio.silent", value, "0");
+                        if (atoi(value)) {
+                            LOGD("Silence is golden");
+                            setMasterMute(true);
+                        }
+                    }
+
+                    standbyTime = systemTime() + kStandbyTimeInNsecs;
+                    sleepTime = 1000;
+                    continue;
+                }
+            }
+
+            enabledTracks = prepareTracks_l(activeTracks, &tracksToRemove);
+        }
+
+        if (LIKELY(enabledTracks)) {
+            // mix buffers...
+            mAudioMixer->process(curBuf);
+            sleepTime = 0;
+            writeFrames = mFrameCount;
+        } else {
+            if (sleepTime == 0) {
+                sleepTime = maxBufferRecoveryInUsecs;
+            } else if (mBytesWritten != 0) {
+                // flush remaining overflow buffers in output tracks
+                for (size_t i = 0; i < outputTracks.size(); i++) {
+                    if (outputTracks[i]->isActive()) {
+                        sleepTime = 0;
+                        writeFrames = 0;
+                        break;
+                    }
+                }
+            }
+        }
+
+        if (mSuspended) {
+            sleepTime = maxBufferRecoveryInUsecs;
+        }
+        // sleepTime == 0 means we must write to audio hardware
+        if (sleepTime == 0) {
+            standbyTime = systemTime() + kStandbyTimeInNsecs;
+            for (size_t i = 0; i < outputTracks.size(); i++) {
+                outputTracks[i]->write(curBuf, writeFrames);
+            }
+            mStandby = false;
+            mBytesWritten += mixBufferSize;
+        } else {
+            usleep(sleepTime);
+        }
+
+        // finally let go of all our tracks, without the lock held
+        // since we can't guarantee the destructors won't acquire that
+        // same lock.
+        tracksToRemove.clear();
+        outputTracks.clear();
+    }
+
+    { // scope for the mLock
+
+        Mutex::Autolock _l(mLock);
+        if (!mStandby) {
+            LOGV("DuplicatingThread() exiting out of standby");
+            for (size_t i = 0; i < mOutputTracks.size(); i++) {
+                mOutputTracks[i]->destroy();
+            }
+        }
+    }
+
+    return false;
+}
+
+void AudioFlinger::DuplicatingThread::addOutputTrack(MixerThread *thread)
+{
+    int frameCount = (3 * mFrameCount * mSampleRate) / thread->sampleRate();
+    OutputTrack *outputTrack = new OutputTrack((ThreadBase *)thread,
+                                            mSampleRate,
+                                            mFormat,
+                                            mChannelCount,
+                                            frameCount);
+    if (outputTrack->cblk() != NULL) {
+        thread->setStreamVolume(AudioSystem::NUM_STREAM_TYPES, 1.0f);
+        mOutputTracks.add(outputTrack);
+        LOGV("addOutputTrack() track %p, on thread %p", outputTrack, thread);
+    }
+}
+
+void AudioFlinger::DuplicatingThread::removeOutputTrack(MixerThread *thread)
+{
+    Mutex::Autolock _l(mLock);
+    for (size_t i = 0; i < mOutputTracks.size(); i++) {
+        if (mOutputTracks[i]->thread() == (ThreadBase *)thread) {
+            mOutputTracks[i]->destroy();
+            mOutputTracks.removeAt(i);
+            return;
+        }
+    }
+    LOGV("removeOutputTrack(): unkonwn thread: %p", thread);
 }
 
 // ----------------------------------------------------------------------------
 
 // TrackBase constructor must be called with AudioFlinger::mLock held
-AudioFlinger::MixerThread::TrackBase::TrackBase(
-            const sp<MixerThread>& mixerThread,
+AudioFlinger::ThreadBase::TrackBase::TrackBase(
+            const wp<ThreadBase>& thread,
             const sp<Client>& client,
             uint32_t sampleRate,
             int format,
@@ -1567,21 +2102,15 @@
             uint32_t flags,
             const sp<IMemory>& sharedBuffer)
     :   RefBase(),
-        mMixerThread(mixerThread),
+        mThread(thread),
         mClient(client),
+        mCblk(0),
         mFrameCount(0),
         mState(IDLE),
         mClientTid(-1),
         mFormat(format),
         mFlags(flags & ~SYSTEM_FLAGS_MASK)
 {
-    mName = mixerThread->getTrackName_l();
-    LOGV("TrackBase contructor name %d, calling thread %d", mName, IPCThreadState::self()->getCallingPid());
-    if (mName < 0) {
-        LOGE("no more track names availlable");
-        return;
-    }
-
     LOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(), sharedBuffer->size());
 
     // LOGD("Creating track with %d buffers @ %d bytes", bufferCount, bufferSize);
@@ -1635,16 +2164,22 @@
    }
 }
 
-AudioFlinger::MixerThread::TrackBase::~TrackBase()
+AudioFlinger::ThreadBase::TrackBase::~TrackBase()
 {
     if (mCblk) {
-        mCblk->~audio_track_cblk_t();   // destroy our shared-structure.        
+        mCblk->~audio_track_cblk_t();   // destroy our shared-structure.
+        if (mClient == NULL) {
+            delete mCblk;
+        }
     }
     mCblkMemory.clear();            // and free the shared memory
-    mClient.clear();
+    if (mClient != NULL) {
+        Mutex::Autolock _l(mClient->audioFlinger()->mLock);
+        mClient.clear();
+    }
 }
 
-void AudioFlinger::MixerThread::TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
+void AudioFlinger::ThreadBase::TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
 {
     buffer->raw = 0;
     mFrameCount = buffer->frameCount;
@@ -1652,7 +2187,7 @@
     buffer->frameCount = 0;
 }
 
-bool AudioFlinger::MixerThread::TrackBase::step() {
+bool AudioFlinger::ThreadBase::TrackBase::step() {
     bool result;
     audio_track_cblk_t* cblk = this->cblk();
 
@@ -1664,7 +2199,7 @@
     return result;
 }
 
-void AudioFlinger::MixerThread::TrackBase::reset() {
+void AudioFlinger::ThreadBase::TrackBase::reset() {
     audio_track_cblk_t* cblk = this->cblk();
 
     cblk->user = 0;
@@ -1675,27 +2210,27 @@
     LOGV("TrackBase::reset");
 }
 
-sp<IMemory> AudioFlinger::MixerThread::TrackBase::getCblk() const
+sp<IMemory> AudioFlinger::ThreadBase::TrackBase::getCblk() const
 {
     return mCblkMemory;
 }
 
-int AudioFlinger::MixerThread::TrackBase::sampleRate() const {
+int AudioFlinger::ThreadBase::TrackBase::sampleRate() const {
     return (int)mCblk->sampleRate;
 }
 
-int AudioFlinger::MixerThread::TrackBase::channelCount() const {
+int AudioFlinger::ThreadBase::TrackBase::channelCount() const {
     return (int)mCblk->channels;
 }
 
-void* AudioFlinger::MixerThread::TrackBase::getBuffer(uint32_t offset, uint32_t frames) const {
+void* AudioFlinger::ThreadBase::TrackBase::getBuffer(uint32_t offset, uint32_t frames) const {
     audio_track_cblk_t* cblk = this->cblk();
-    int16_t *bufferStart = (int16_t *)mBuffer + (offset-cblk->serverBase)*cblk->channels;
-    int16_t *bufferEnd = bufferStart + frames * cblk->channels;
+    int8_t *bufferStart = (int8_t *)mBuffer + (offset-cblk->serverBase)*cblk->frameSize;
+    int8_t *bufferEnd = bufferStart + frames * cblk->frameSize;
 
     // Check validity of returned pointer in case the track control block would have been corrupted.
-    if (bufferStart < mBuffer || bufferStart > bufferEnd || bufferEnd > mBufferEnd || 
-        (cblk->channels == 2 && ((unsigned long)bufferStart & 3))) {
+    if (bufferStart < mBuffer || bufferStart > bufferEnd || bufferEnd > mBufferEnd ||
+        ((unsigned long)bufferStart & (unsigned long)(cblk->frameSize - 1))) {
         LOGE("TrackBase::getBuffer buffer out of range:\n    start: %p, end %p , mBuffer %p mBufferEnd %p\n    \
                 server %d, serverBase %d, user %d, userBase %d, channels %d",
                 bufferStart, bufferEnd, mBuffer, mBufferEnd,
@@ -1708,9 +2243,9 @@
 
 // ----------------------------------------------------------------------------
 
-// Track constructor must be called with AudioFlinger::mLock held
-AudioFlinger::MixerThread::Track::Track(
-            const sp<MixerThread>& mixerThread,
+// Track constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
+AudioFlinger::PlaybackThread::Track::Track(
+            const wp<ThreadBase>& thread,
             const sp<Client>& client,
             int streamType,
             uint32_t sampleRate,
@@ -1718,42 +2253,62 @@
             int channelCount,
             int frameCount,
             const sp<IMemory>& sharedBuffer)
-    :   TrackBase(mixerThread, client, sampleRate, format, channelCount, frameCount, 0, sharedBuffer)
+    :   TrackBase(thread, client, sampleRate, format, channelCount, frameCount, 0, sharedBuffer),
+    mMute(false), mSharedBuffer(sharedBuffer), mName(-1)
 {
-    mVolume[0] = 1.0f;
-    mVolume[1] = 1.0f;
-    mMute = false;
-    mSharedBuffer = sharedBuffer;
-    mStreamType = streamType;
-}
-
-AudioFlinger::MixerThread::Track::~Track()
-{
-    wp<Track> weak(this); // never create a strong ref from the dtor
-    Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock);
-    mState = TERMINATED;
-}
-
-void AudioFlinger::MixerThread::Track::destroy()
-{
-    // NOTE: destroyTrack_l() can remove a strong reference to this Track 
-    // by removing it from mTracks vector, so there is a risk that this Tracks's
-    // desctructor is called. As the destructor needs to lock AudioFlinger::mLock,
-    // we must acquire a strong reference on this Track before locking AudioFlinger::mLock
-    // here so that the destructor is called only when exiting this function.
-    // On the other hand, as long as Track::destroy() is only called by 
-    // TrackHandle destructor, the TrackHandle still holds a strong ref on 
-    // this Track with its member mTrack.
-    sp<Track> keep(this);
-    { // scope for AudioFlinger::mLock
-        Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock);
-        mMixerThread->destroyTrack_l(this);
+    if (mCblk != NULL) {
+        sp<ThreadBase> baseThread = thread.promote();
+        if (baseThread != 0) {
+            PlaybackThread *playbackThread = (PlaybackThread *)baseThread.get();
+            mName = playbackThread->getTrackName_l();
+        }
+        LOGV("Track constructor name %d, calling thread %d", mName, IPCThreadState::self()->getCallingPid());
+        if (mName < 0) {
+            LOGE("no more track names available");
+        }
+        mVolume[0] = 1.0f;
+        mVolume[1] = 1.0f;
+        mStreamType = streamType;
+        // NOTE: audio_track_cblk_t::frameSize for 8 bit PCM data is based on a sample size of
+        // 16 bit because data is converted to 16 bit before being stored in buffer by AudioTrack
+        mCblk->frameSize = AudioSystem::isLinearPCM(format) ? channelCount * sizeof(int16_t) : sizeof(int8_t);
     }
 }
 
-void AudioFlinger::MixerThread::Track::dump(char* buffer, size_t size)
+AudioFlinger::PlaybackThread::Track::~Track()
 {
-    snprintf(buffer, size, "  %5d %5d %3u %3u %3u %3u %1d %1d %1d %5u %5u %5u %04x %04x\n",
+    LOGV("PlaybackThread::Track destructor");
+    sp<ThreadBase> thread = mThread.promote();
+    if (thread != 0) {
+        Mutex::Autolock _l(thread->mLock);
+        mState = TERMINATED;
+    }
+}
+
+void AudioFlinger::PlaybackThread::Track::destroy()
+{
+    // NOTE: destroyTrack_l() can remove a strong reference to this Track
+    // by removing it from mTracks vector, so there is a risk that this Tracks's
+    // desctructor is called. As the destructor needs to lock mLock,
+    // we must acquire a strong reference on this Track before locking mLock
+    // here so that the destructor is called only when exiting this function.
+    // On the other hand, as long as Track::destroy() is only called by
+    // TrackHandle destructor, the TrackHandle still holds a strong ref on
+    // this Track with its member mTrack.
+    sp<Track> keep(this);
+    { // scope for mLock
+        sp<ThreadBase> thread = mThread.promote();
+        if (thread != 0) {
+            Mutex::Autolock _l(thread->mLock);
+            PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
+            playbackThread->destroyTrack_l(this);
+        }
+    }
+}
+
+void AudioFlinger::PlaybackThread::Track::dump(char* buffer, size_t size)
+{
+    snprintf(buffer, size, "  %5d %5d %3u %3u %3u %04u %1d %1d %1d %5u %5u %5u  %08x %08x\n",
             mName - AudioMixer::TRACK0,
             (mClient == NULL) ? getpid() : mClient->pid(),
             mStreamType,
@@ -1770,7 +2325,7 @@
             mCblk->user);
 }
 
-status_t AudioFlinger::MixerThread::Track::getNextBuffer(AudioBufferProvider::Buffer* buffer)
+status_t AudioFlinger::PlaybackThread::Track::getNextBuffer(AudioBufferProvider::Buffer* buffer)
 {
      audio_track_cblk_t* cblk = this->cblk();
      uint32_t framesReady;
@@ -1807,76 +2362,90 @@
 getNextBuffer_exit:
      buffer->raw = 0;
      buffer->frameCount = 0;
+     LOGV("getNextBuffer() no more data for track %d on thread %p", mName, mThread.unsafe_get());
      return NOT_ENOUGH_DATA;
 }
 
-bool AudioFlinger::MixerThread::Track::isReady() const {
+bool AudioFlinger::PlaybackThread::Track::isReady() const {
     if (mFillingUpStatus != FS_FILLING) return true;
 
     if (mCblk->framesReady() >= mCblk->frameCount ||
         mCblk->forceReady) {
         mFillingUpStatus = FS_FILLED;
         mCblk->forceReady = 0;
-        LOGV("Track::isReady() track %d for output %d", mName, mMixerThread->mOutputType);
         return true;
     }
     return false;
 }
 
-status_t AudioFlinger::MixerThread::Track::start()
+status_t AudioFlinger::PlaybackThread::Track::start()
 {
-    LOGV("start(%d), calling thread %d for output %d", mName, IPCThreadState::self()->getCallingPid(), mMixerThread->mOutputType);
-    Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock);
-    mMixerThread->addTrack_l(this);
+    LOGV("start(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid());
+    sp<ThreadBase> thread = mThread.promote();
+    if (thread != 0) {
+        Mutex::Autolock _l(thread->mLock);
+        PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
+        playbackThread->addTrack_l(this);
+    }
     return NO_ERROR;
 }
 
-void AudioFlinger::MixerThread::Track::stop()
+void AudioFlinger::PlaybackThread::Track::stop()
 {
-    LOGV("stop(%d), calling thread %d for output %d", mName, IPCThreadState::self()->getCallingPid(), mMixerThread->mOutputType);
-    Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock);
-    if (mState > STOPPED) {
-        mState = STOPPED;
-        // If the track is not active (PAUSED and buffers full), flush buffers
-        if (mMixerThread->mActiveTracks.indexOf(this) < 0) {
-            reset();
+    LOGV("stop(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid());
+    sp<ThreadBase> thread = mThread.promote();
+    if (thread != 0) {
+        Mutex::Autolock _l(thread->mLock);
+        if (mState > STOPPED) {
+            mState = STOPPED;
+            // If the track is not active (PAUSED and buffers full), flush buffers
+            PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
+            if (playbackThread->mActiveTracks.indexOf(this) < 0) {
+                reset();
+            }
+            LOGV("(> STOPPED) => STOPPED (%d) on thread %p", mName, playbackThread);
         }
-        LOGV("(> STOPPED) => STOPPED (%d)", mName);
     }
 }
 
-void AudioFlinger::MixerThread::Track::pause()
+void AudioFlinger::PlaybackThread::Track::pause()
 {
     LOGV("pause(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid());
-    Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock);
-    if (mState == ACTIVE || mState == RESUMING) {
-        mState = PAUSING;
-        LOGV("ACTIVE/RESUMING => PAUSING (%d)", mName);
+    sp<ThreadBase> thread = mThread.promote();
+    if (thread != 0) {
+        Mutex::Autolock _l(thread->mLock);
+        if (mState == ACTIVE || mState == RESUMING) {
+            mState = PAUSING;
+            LOGV("ACTIVE/RESUMING => PAUSING (%d) on thread %p", mName, thread.get());
+        }
     }
 }
 
-void AudioFlinger::MixerThread::Track::flush()
+void AudioFlinger::PlaybackThread::Track::flush()
 {
     LOGV("flush(%d)", mName);
-    Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock);
-    if (mState != STOPPED && mState != PAUSED && mState != PAUSING) {
-        return;
-    }
-    // No point remaining in PAUSED state after a flush => go to
-    // STOPPED state
-    mState = STOPPED;
+    sp<ThreadBase> thread = mThread.promote();
+    if (thread != 0) {
+        Mutex::Autolock _l(thread->mLock);
+        if (mState != STOPPED && mState != PAUSED && mState != PAUSING) {
+            return;
+        }
+        // No point remaining in PAUSED state after a flush => go to
+        // STOPPED state
+        mState = STOPPED;
 
-    mCblk->lock.lock();
-    // NOTE: reset() will reset cblk->user and cblk->server with
-    // the risk that at the same time, the AudioMixer is trying to read
-    // data. In this case, getNextBuffer() would return a NULL pointer
-    // as audio buffer => the AudioMixer code MUST always test that pointer
-    // returned by getNextBuffer() is not NULL!
-    reset();
-    mCblk->lock.unlock();
+        mCblk->lock.lock();
+        // NOTE: reset() will reset cblk->user and cblk->server with
+        // the risk that at the same time, the AudioMixer is trying to read
+        // data. In this case, getNextBuffer() would return a NULL pointer
+        // as audio buffer => the AudioMixer code MUST always test that pointer
+        // returned by getNextBuffer() is not NULL!
+        reset();
+        mCblk->lock.unlock();
+    }
 }
 
-void AudioFlinger::MixerThread::Track::reset()
+void AudioFlinger::PlaybackThread::Track::reset()
 {
     // Do not reset twice to avoid discarding data written just after a flush and before
     // the audioflinger thread detects the track is stopped.
@@ -1886,17 +2455,17 @@
         // written to buffer
         mCblk->flowControlFlag = 1;
         mCblk->forceReady = 0;
-        mFillingUpStatus = FS_FILLING;        
+        mFillingUpStatus = FS_FILLING;
         mResetDone = true;
     }
 }
 
-void AudioFlinger::MixerThread::Track::mute(bool muted)
+void AudioFlinger::PlaybackThread::Track::mute(bool muted)
 {
     mMute = muted;
 }
 
-void AudioFlinger::MixerThread::Track::setVolume(float left, float right)
+void AudioFlinger::PlaybackThread::Track::setVolume(float left, float right)
 {
     mVolume[0] = left;
     mVolume[1] = right;
@@ -1905,28 +2474,35 @@
 // ----------------------------------------------------------------------------
 
 // RecordTrack constructor must be called with AudioFlinger::mLock held
-AudioFlinger::MixerThread::RecordTrack::RecordTrack(
-            const sp<MixerThread>& mixerThread,
+AudioFlinger::RecordThread::RecordTrack::RecordTrack(
+            const wp<ThreadBase>& thread,
             const sp<Client>& client,
-            int inputSource,
             uint32_t sampleRate,
             int format,
             int channelCount,
             int frameCount,
             uint32_t flags)
-    :   TrackBase(mixerThread, client, sampleRate, format,
+    :   TrackBase(thread, client, sampleRate, format,
                   channelCount, frameCount, flags, 0),
-        mOverflow(false), mInputSource(inputSource)
+        mOverflow(false)
+{
+    if (mCblk != NULL) {
+       LOGV("RecordTrack constructor, size %d", (int)mBufferEnd - (int)mBuffer);
+       if (format == AudioSystem::PCM_16_BIT) {
+           mCblk->frameSize = channelCount * sizeof(int16_t);
+       } else if (format == AudioSystem::PCM_8_BIT) {
+           mCblk->frameSize = channelCount * sizeof(int8_t);
+       } else {
+           mCblk->frameSize = sizeof(int8_t);
+       }
+    }
+}
+
+AudioFlinger::RecordThread::RecordTrack::~RecordTrack()
 {
 }
 
-AudioFlinger::MixerThread::RecordTrack::~RecordTrack()
-{
-    Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock);
-    mMixerThread->deleteTrackName_l(mName);
-}
-
-status_t AudioFlinger::MixerThread::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
+status_t AudioFlinger::RecordThread::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
 {
     audio_track_cblk_t* cblk = this->cblk();
     uint32_t framesAvail;
@@ -1965,180 +2541,247 @@
     return NOT_ENOUGH_DATA;
 }
 
-status_t AudioFlinger::MixerThread::RecordTrack::start()
+status_t AudioFlinger::RecordThread::RecordTrack::start()
 {
-    return mMixerThread->mAudioFlinger->startRecord(this);
+    sp<ThreadBase> thread = mThread.promote();
+    if (thread != 0) {
+        RecordThread *recordThread = (RecordThread *)thread.get();
+        return recordThread->start(this);
+    }
+    return NO_INIT;
 }
 
-void AudioFlinger::MixerThread::RecordTrack::stop()
+void AudioFlinger::RecordThread::RecordTrack::stop()
 {
-    mMixerThread->mAudioFlinger->stopRecord(this);
-    TrackBase::reset();
-    // Force overerrun condition to avoid false overrun callback until first data is
-    // read from buffer
-    mCblk->flowControlFlag = 1;
+    sp<ThreadBase> thread = mThread.promote();
+    if (thread != 0) {
+        RecordThread *recordThread = (RecordThread *)thread.get();
+        recordThread->stop(this);
+        TrackBase::reset();
+        // Force overerrun condition to avoid false overrun callback until first data is
+        // read from buffer
+        mCblk->flowControlFlag = 1;
+    }
+}
+
+void AudioFlinger::RecordThread::RecordTrack::dump(char* buffer, size_t size)
+{
+    snprintf(buffer, size, "   %05d %03u %03u %04u %01d %05u  %08x %08x\n",
+            (mClient == NULL) ? getpid() : mClient->pid(),
+            mFormat,
+            mCblk->channels,
+            mFrameCount,
+            mState,
+            mCblk->sampleRate,
+            mCblk->server,
+            mCblk->user);
 }
 
 
 // ----------------------------------------------------------------------------
 
-AudioFlinger::MixerThread::OutputTrack::OutputTrack(
-            const sp<MixerThread>& mixerThread,
+AudioFlinger::PlaybackThread::OutputTrack::OutputTrack(
+            const wp<ThreadBase>& thread,
             uint32_t sampleRate,
             int format,
             int channelCount,
             int frameCount)
-    :   Track(mixerThread, NULL, AudioSystem::SYSTEM, sampleRate, format, channelCount, frameCount, NULL),
-    mOutputMixerThread(mixerThread)
+    :   Track(thread, NULL, AudioSystem::NUM_STREAM_TYPES, sampleRate, format, channelCount, frameCount, NULL),
+    mActive(false)
 {
-                
-    mCblk->out = 1;
-    mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
-    mCblk->volume[0] = mCblk->volume[1] = 0x1000;
-    mOutBuffer.frameCount = 0;
-    mCblk->bufferTimeoutMs = 10;
-    
-    LOGV("OutputTrack constructor mCblk %p, mBuffer %p, mCblk->buffers %p, mCblk->frameCount %d, mCblk->sampleRate %d, mCblk->channels %d mBufferEnd %p", 
-            mCblk, mBuffer, mCblk->buffers, mCblk->frameCount, mCblk->sampleRate, mCblk->channels, mBufferEnd);
-    
+
+    PlaybackThread *playbackThread = (PlaybackThread *)thread.unsafe_get();
+    if (mCblk != NULL) {
+        mCblk->out = 1;
+        mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
+        mCblk->volume[0] = mCblk->volume[1] = 0x1000;
+        mOutBuffer.frameCount = 0;
+        mWaitTimeMs = (playbackThread->frameCount() * 2 * 1000) / playbackThread->sampleRate();
+        playbackThread->mTracks.add(this);
+        LOGV("OutputTrack constructor mCblk %p, mBuffer %p, mCblk->buffers %p, mCblk->frameCount %d, mCblk->sampleRate %d, mCblk->channels %d mBufferEnd %p mWaitTimeMs %d",
+                mCblk, mBuffer, mCblk->buffers, mCblk->frameCount, mCblk->sampleRate, mCblk->channels, mBufferEnd, mWaitTimeMs);
+    } else {
+        LOGW("Error creating output track on thread %p", playbackThread);
+    }
 }
 
-AudioFlinger::MixerThread::OutputTrack::~OutputTrack()
+AudioFlinger::PlaybackThread::OutputTrack::~OutputTrack()
 {
-    stop();
+    clearBufferQueue();
 }
 
-status_t AudioFlinger::MixerThread::OutputTrack::start()
+status_t AudioFlinger::PlaybackThread::OutputTrack::start()
 {
     status_t status = Track::start();
-    
+    if (status != NO_ERROR) {
+        return status;
+    }
+
+    mActive = true;
     mRetryCount = 127;
     return status;
 }
 
-void AudioFlinger::MixerThread::OutputTrack::stop()
+void AudioFlinger::PlaybackThread::OutputTrack::stop()
 {
     Track::stop();
     clearBufferQueue();
     mOutBuffer.frameCount = 0;
+    mActive = false;
 }
 
-void AudioFlinger::MixerThread::OutputTrack::write(int16_t* data, uint32_t frames)
+bool AudioFlinger::PlaybackThread::OutputTrack::write(int16_t* data, uint32_t frames)
 {
     Buffer *pInBuffer;
     Buffer inBuffer;
     uint32_t channels = mCblk->channels;
-        
+    bool outputBufferFull = false;
     inBuffer.frameCount = frames;
     inBuffer.i16 = data;
-    
-    if (mCblk->user == 0) {
-        mOutputMixerThread->mAudioFlinger->mLock.lock();
-        bool isMusicActive = mOutputMixerThread->isMusicActive_l();
-        mOutputMixerThread->mAudioFlinger->mLock.unlock();
-        if (isMusicActive) {
-            mCblk->forceReady = 1;
-            LOGV("OutputTrack::start() force ready");
-        } else if (mCblk->frameCount > frames){
-            if (mBufferQueue.size() < kMaxOutputTrackBuffers) {
-                uint32_t startFrames = (mCblk->frameCount - frames);
-                LOGV("OutputTrack::start() write %d frames", startFrames);
-                pInBuffer = new Buffer;
-                pInBuffer->mBuffer = new int16_t[startFrames * channels];
-                pInBuffer->frameCount = startFrames;
-                pInBuffer->i16 = pInBuffer->mBuffer;
-                memset(pInBuffer->raw, 0, startFrames * channels * sizeof(int16_t));
-                mBufferQueue.add(pInBuffer);                
-            } else {
-                LOGW ("OutputTrack::write() no more buffers");
+
+    uint32_t waitTimeLeftMs = mWaitTimeMs;
+
+    if (!mActive && frames != 0) {
+        start();
+        sp<ThreadBase> thread = mThread.promote();
+        if (thread != 0) {
+            MixerThread *mixerThread = (MixerThread *)thread.get();
+            if (mCblk->frameCount > frames){
+                if (mBufferQueue.size() < kMaxOverFlowBuffers) {
+                    uint32_t startFrames = (mCblk->frameCount - frames);
+                    pInBuffer = new Buffer;
+                    pInBuffer->mBuffer = new int16_t[startFrames * channels];
+                    pInBuffer->frameCount = startFrames;
+                    pInBuffer->i16 = pInBuffer->mBuffer;
+                    memset(pInBuffer->raw, 0, startFrames * channels * sizeof(int16_t));
+                    mBufferQueue.add(pInBuffer);
+                } else {
+                    LOGW ("OutputTrack::write() %p no more buffers in queue", this);
+                }
             }
-        }        
+        }
     }
 
-    while (1) { 
+    while (waitTimeLeftMs) {
         // First write pending buffers, then new data
         if (mBufferQueue.size()) {
             pInBuffer = mBufferQueue.itemAt(0);
         } else {
             pInBuffer = &inBuffer;
         }
- 
+
         if (pInBuffer->frameCount == 0) {
             break;
         }
-        
+
         if (mOutBuffer.frameCount == 0) {
             mOutBuffer.frameCount = pInBuffer->frameCount;
-            if (obtainBuffer(&mOutBuffer) == (status_t)AudioTrack::NO_MORE_BUFFERS) {
+            nsecs_t startTime = systemTime();
+            if (obtainBuffer(&mOutBuffer, waitTimeLeftMs) == (status_t)AudioTrack::NO_MORE_BUFFERS) {
+                LOGV ("OutputTrack::write() %p no more output buffers", this);
+                outputBufferFull = true;
                 break;
             }
+            uint32_t waitTimeMs = (uint32_t)ns2ms(systemTime() - startTime);
+            LOGV("OutputTrack::write() to thread %p waitTimeMs %d waitTimeLeftMs %d", mThread.unsafe_get(), waitTimeMs, waitTimeLeftMs);
+            if (waitTimeLeftMs >= waitTimeMs) {
+                waitTimeLeftMs -= waitTimeMs;
+            } else {
+                waitTimeLeftMs = 0;
+            }
         }
-            
+
         uint32_t outFrames = pInBuffer->frameCount > mOutBuffer.frameCount ? mOutBuffer.frameCount : pInBuffer->frameCount;
         memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * channels * sizeof(int16_t));
         mCblk->stepUser(outFrames);
         pInBuffer->frameCount -= outFrames;
         pInBuffer->i16 += outFrames * channels;
         mOutBuffer.frameCount -= outFrames;
-        mOutBuffer.i16 += outFrames * channels;            
-        
+        mOutBuffer.i16 += outFrames * channels;
+
         if (pInBuffer->frameCount == 0) {
             if (mBufferQueue.size()) {
                 mBufferQueue.removeAt(0);
                 delete [] pInBuffer->mBuffer;
                 delete pInBuffer;
+                LOGV("OutputTrack::write() %p released overflow buffer %d", this, mBufferQueue.size());
             } else {
                 break;
             }
         }
     }
- 
+
     // If we could not write all frames, allocate a buffer and queue it for next time.
     if (inBuffer.frameCount) {
-        if (mBufferQueue.size() < kMaxOutputTrackBuffers) {
+        if (mBufferQueue.size() < kMaxOverFlowBuffers) {
             pInBuffer = new Buffer;
             pInBuffer->mBuffer = new int16_t[inBuffer.frameCount * channels];
             pInBuffer->frameCount = inBuffer.frameCount;
             pInBuffer->i16 = pInBuffer->mBuffer;
             memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * channels * sizeof(int16_t));
             mBufferQueue.add(pInBuffer);
+            LOGV("OutputTrack::write() %p adding overflow buffer %d", this, mBufferQueue.size());
         } else {
-            LOGW("OutputTrack::write() no more buffers");
+            LOGW("OutputTrack::write() %p no more overflow buffers", this);
         }
     }
-    
+
     // Calling write() with a 0 length buffer, means that no more data will be written:
-    // If no more buffers are pending, fill output track buffer to make sure it is started 
+    // If no more buffers are pending, fill output track buffer to make sure it is started
     // by output mixer.
-    if (frames == 0 && mBufferQueue.size() == 0 && mCblk->user < mCblk->frameCount) {
-        frames = mCblk->frameCount - mCblk->user;
-        pInBuffer = new Buffer;
-        pInBuffer->mBuffer = new int16_t[frames * channels];
-        pInBuffer->frameCount = frames;
-        pInBuffer->i16 = pInBuffer->mBuffer;
-        memset(pInBuffer->raw, 0, frames * channels * sizeof(int16_t));
-        mBufferQueue.add(pInBuffer);
+    if (frames == 0 && mBufferQueue.size() == 0) {
+        if (mCblk->user < mCblk->frameCount) {
+            frames = mCblk->frameCount - mCblk->user;
+            pInBuffer = new Buffer;
+            pInBuffer->mBuffer = new int16_t[frames * channels];
+            pInBuffer->frameCount = frames;
+            pInBuffer->i16 = pInBuffer->mBuffer;
+            memset(pInBuffer->raw, 0, frames * channels * sizeof(int16_t));
+            mBufferQueue.add(pInBuffer);
+        } else if (mActive) {
+            stop();
+        }
     }
 
+    return outputBufferFull;
 }
 
-status_t AudioFlinger::MixerThread::OutputTrack::obtainBuffer(AudioBufferProvider::Buffer* buffer)
+status_t AudioFlinger::PlaybackThread::OutputTrack::obtainBuffer(AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs)
 {
     int active;
-    int timeout = 0;
     status_t result;
     audio_track_cblk_t* cblk = mCblk;
     uint32_t framesReq = buffer->frameCount;
 
-    LOGV("OutputTrack::obtainBuffer user %d, server %d", cblk->user, cblk->server);
+//    LOGV("OutputTrack::obtainBuffer user %d, server %d", cblk->user, cblk->server);
     buffer->frameCount  = 0;
-    
+
     uint32_t framesAvail = cblk->framesAvailable();
 
+
     if (framesAvail == 0) {
-        return AudioTrack::NO_MORE_BUFFERS;
+        Mutex::Autolock _l(cblk->lock);
+        goto start_loop_here;
+        while (framesAvail == 0) {
+            active = mActive;
+            if (UNLIKELY(!active)) {
+                LOGV("Not active and NO_MORE_BUFFERS");
+                return AudioTrack::NO_MORE_BUFFERS;
+            }
+            result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs));
+            if (result != NO_ERROR) {
+                return AudioTrack::NO_MORE_BUFFERS;
+            }
+            // read the server count again
+        start_loop_here:
+            framesAvail = cblk->framesAvailable_l();
+        }
     }
 
+//    if (framesAvail < framesReq) {
+//        return AudioTrack::NO_MORE_BUFFERS;
+//    }
+
     if (framesReq > framesAvail) {
         framesReq = framesAvail;
     }
@@ -2156,11 +2799,11 @@
 }
 
 
-void AudioFlinger::MixerThread::OutputTrack::clearBufferQueue()
+void AudioFlinger::PlaybackThread::OutputTrack::clearBufferQueue()
 {
     size_t size = mBufferQueue.size();
     Buffer *pBuffer;
-    
+
     for (size_t i = 0; i < size; i++) {
         pBuffer = mBufferQueue.itemAt(i);
         delete [] pBuffer->mBuffer;
@@ -2180,9 +2823,10 @@
     // 1 MB of address space is good for 32 tracks, 8 buffers each, 4 KB/buffer
 }
 
+// Client destructor must be called with AudioFlinger::mLock held
 AudioFlinger::Client::~Client()
 {
-    mAudioFlinger->removeClient(mPid);
+    mAudioFlinger->removeClient_l(mPid);
 }
 
 const sp<MemoryDealer>& AudioFlinger::Client::heap() const
@@ -2192,7 +2836,7 @@
 
 // ----------------------------------------------------------------------------
 
-AudioFlinger::TrackHandle::TrackHandle(const sp<AudioFlinger::MixerThread::Track>& track)
+AudioFlinger::TrackHandle::TrackHandle(const sp<AudioFlinger::PlaybackThread::Track>& track)
     : BnAudioTrack(),
       mTrack(track)
 {
@@ -2244,7 +2888,7 @@
 
 sp<IAudioRecord> AudioFlinger::openRecord(
         pid_t pid,
-        int inputSource,
+        int input,
         uint32_t sampleRate,
         int format,
         int channelCount,
@@ -2252,14 +2896,13 @@
         uint32_t flags,
         status_t *status)
 {
-    sp<MixerThread::RecordTrack> recordTrack;
+    sp<RecordThread::RecordTrack> recordTrack;
     sp<RecordHandle> recordHandle;
     sp<Client> client;
     wp<Client> wclient;
-    AudioStreamIn* input = 0;
-    int inFrameCount;
-    size_t inputBufferSize;
     status_t lStatus;
+    RecordThread *thread;
+    size_t inFrameCount;
 
     // check calling permissions
     if (!recordingAllowed()) {
@@ -2267,30 +2910,15 @@
         goto Exit;
     }
 
-    if (uint32_t(inputSource) >= AudioRecord::NUM_INPUT_SOURCES) {
-        LOGE("invalid stream type");
-        lStatus = BAD_VALUE;
-        goto Exit;
-    }
-
-    if (mAudioRecordThread == 0) {
-        LOGE("Audio record thread not started");
-        lStatus = NO_INIT;
-        goto Exit;
-    }
-
-
-    // Check that audio input stream accepts requested audio parameters 
-    inputBufferSize = mAudioHardware->getInputBufferSize(sampleRate, format, channelCount);
-    if (inputBufferSize == 0) {
-        lStatus = BAD_VALUE;
-        LOGE("Bad audio input parameters: sampling rate %u, format %d, channels %d",  sampleRate, format, channelCount);
-        goto Exit;
-    }
-
     // add client to list
     { // scope for mLock
         Mutex::Autolock _l(mLock);
+        thread = checkRecordThread_l(input);
+        if (thread == NULL) {
+            lStatus = BAD_VALUE;
+            goto Exit;
+        }
+
         wclient = mClients.valueFor(pid);
         if (wclient != NULL) {
             client = wclient.promote();
@@ -2299,15 +2927,14 @@
             mClients.add(pid, client);
         }
 
-        // frameCount must be a multiple of input buffer size
-        inFrameCount = inputBufferSize/channelCount/sizeof(short);
-        frameCount = ((frameCount - 1)/inFrameCount + 1) * inFrameCount;
-    
         // create new record track. The record track uses one track in mHardwareMixerThread by convention.
-        recordTrack = new MixerThread::RecordTrack(mHardwareMixerThread, client, inputSource, sampleRate,
+        recordTrack = new RecordThread::RecordTrack(thread, client, sampleRate,
                                                    format, channelCount, frameCount, flags);
     }
     if (recordTrack->getCblk() == NULL) {
+        // remove local strong reference to Client before deleting the RecordTrack so that the Client
+        // destructor is called by the TrackBase destructor with mLock held
+        client.clear();
         recordTrack.clear();
         lStatus = NO_MEMORY;
         goto Exit;
@@ -2324,22 +2951,9 @@
     return recordHandle;
 }
 
-status_t AudioFlinger::startRecord(MixerThread::RecordTrack* recordTrack) {
-    if (mAudioRecordThread != 0) {
-        return mAudioRecordThread->start(recordTrack);        
-    }
-    return NO_INIT;
-}
-
-void AudioFlinger::stopRecord(MixerThread::RecordTrack* recordTrack) {
-    if (mAudioRecordThread != 0) {
-        mAudioRecordThread->stop(recordTrack);
-    }
-}
-
 // ----------------------------------------------------------------------------
 
-AudioFlinger::RecordHandle::RecordHandle(const sp<AudioFlinger::MixerThread::RecordTrack>& recordTrack)
+AudioFlinger::RecordHandle::RecordHandle(const sp<AudioFlinger::RecordThread::RecordTrack>& recordTrack)
     : BnAudioRecord(),
     mRecordTrack(recordTrack)
 {
@@ -2371,86 +2985,164 @@
 
 // ----------------------------------------------------------------------------
 
-AudioFlinger::AudioRecordThread::AudioRecordThread(AudioHardwareInterface* audioHardware,
-            const sp<AudioFlinger>& audioFlinger) :
-    mAudioHardware(audioHardware),
-    mAudioFlinger(audioFlinger),
-    mActive(false)
+AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger, AudioStreamIn *input, uint32_t sampleRate, uint32_t channels) :
+    ThreadBase(audioFlinger),
+    mInput(input), mResampler(0), mRsmpOutBuffer(0), mRsmpInBuffer(0)
 {
+    mReqChannelCount = AudioSystem::popCount(channels);
+    mReqSampleRate = sampleRate;
+    readInputParameters();
+    sendConfigEvent(AudioSystem::INPUT_OPENED);
 }
 
-AudioFlinger::AudioRecordThread::~AudioRecordThread()
+
+AudioFlinger::RecordThread::~RecordThread()
 {
+    delete[] mRsmpInBuffer;
+    if (mResampler != 0) {
+        delete mResampler;
+        delete[] mRsmpOutBuffer;
+    }
 }
 
-bool AudioFlinger::AudioRecordThread::threadLoop()
+void AudioFlinger::RecordThread::onFirstRef()
 {
-    LOGV("AudioRecordThread: start record loop");
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+
+    snprintf(buffer, SIZE, "Record Thread %p", this);
+
+    run(buffer, PRIORITY_URGENT_AUDIO);
+}
+bool AudioFlinger::RecordThread::threadLoop()
+{
     AudioBufferProvider::Buffer buffer;
-    int inBufferSize = 0;
-    int inFrameCount = 0;
-    AudioStreamIn* input = 0;
+    sp<RecordTrack> activeTrack;
 
-    mActive = 0;
-    
     // start recording
     while (!exitPending()) {
-        if (!mActive) {
-            mLock.lock();
-            if (!mActive && !exitPending()) {
-                LOGV("AudioRecordThread: loop stopping");
-                if (input) {
-                    delete input;
-                    input = 0;
-                }
-                mRecordTrack.clear();
-                mStopped.signal();
 
+        processConfigEvents();
+
+        { // scope for mLock
+            Mutex::Autolock _l(mLock);
+            checkForNewParameters_l();
+            if (mActiveTrack == 0 && mConfigEvents.isEmpty()) {
+                if (!mStandby) {
+                    mInput->standby();
+                    mStandby = true;
+                }
+
+                if (exitPending()) break;
+
+                LOGV("RecordThread: loop stopping");
+                // go to sleep
                 mWaitWorkCV.wait(mLock);
-               
-                LOGV("AudioRecordThread: loop starting");
-                if (mRecordTrack != 0) {
-                    input = mAudioHardware->openInputStream(
-                                    mRecordTrack->inputSource(),
-                                    mRecordTrack->format(), 
-                                    mRecordTrack->channelCount(), 
-                                    mRecordTrack->sampleRate(), 
-                                    &mStartStatus,
-                                    (AudioSystem::audio_in_acoustics)(mRecordTrack->mFlags >> 16));
-                    if (input != 0) {
-                        inBufferSize = input->bufferSize();
-                        inFrameCount = inBufferSize/input->frameSize();                        
+                LOGV("RecordThread: loop starting");
+                continue;
+            }
+            if (mActiveTrack != 0) {
+                if (mActiveTrack->mState == TrackBase::PAUSING) {
+                    mActiveTrack.clear();
+                    mStartStopCond.broadcast();
+                } else if (mActiveTrack->mState == TrackBase::RESUMING) {
+                    mRsmpInIndex = mFrameCount;
+                    if (mReqChannelCount != mActiveTrack->channelCount()) {
+                        mActiveTrack.clear();
+                    } else {
+                        mActiveTrack->mState = TrackBase::ACTIVE;
+                    }
+                    mStartStopCond.broadcast();
+                }
+                mStandby = false;
+            }
+        }
+
+        if (mActiveTrack != 0) {
+            buffer.frameCount = mFrameCount;
+            if (LIKELY(mActiveTrack->getNextBuffer(&buffer) == NO_ERROR)) {
+                size_t framesOut = buffer.frameCount;
+                if (mResampler == 0) {
+                    // no resampling
+                    while (framesOut) {
+                        size_t framesIn = mFrameCount - mRsmpInIndex;
+                        if (framesIn) {
+                            int8_t *src = (int8_t *)mRsmpInBuffer + mRsmpInIndex * mFrameSize;
+                            int8_t *dst = buffer.i8 + (buffer.frameCount - framesOut) * mActiveTrack->mCblk->frameSize;
+                            if (framesIn > framesOut)
+                                framesIn = framesOut;
+                            mRsmpInIndex += framesIn;
+                            framesOut -= framesIn;
+                            if (mChannelCount == mReqChannelCount ||
+                                mFormat != AudioSystem::PCM_16_BIT) {
+                                memcpy(dst, src, framesIn * mFrameSize);
+                            } else {
+                                int16_t *src16 = (int16_t *)src;
+                                int16_t *dst16 = (int16_t *)dst;
+                                if (mChannelCount == 1) {
+                                    while (framesIn--) {
+                                        *dst16++ = *src16;
+                                        *dst16++ = *src16++;
+                                    }
+                                } else {
+                                    while (framesIn--) {
+                                        *dst16++ = (int16_t)(((int32_t)*src16 + (int32_t)*(src16 + 1)) >> 1);
+                                        src16 += 2;
+                                    }
+                                }
+                            }
+                        }
+                        if (framesOut && mFrameCount == mRsmpInIndex) {
+                            ssize_t bytesRead;
+                            if (framesOut == mFrameCount &&
+                                (mChannelCount == mReqChannelCount || mFormat != AudioSystem::PCM_16_BIT)) {
+                                bytesRead = mInput->read(buffer.raw, mInputBytes);
+                                framesOut = 0;
+                            } else {
+                                bytesRead = mInput->read(mRsmpInBuffer, mInputBytes);
+                                mRsmpInIndex = 0;
+                            }
+                            if (bytesRead < 0) {
+                                LOGE("Error reading audio input");
+                                sleep(1);
+                                mRsmpInIndex = mFrameCount;
+                                framesOut = 0;
+                                buffer.frameCount = 0;
+                            }
+                        }
                     }
                 } else {
-                    mStartStatus = NO_INIT;
-                }
-                if (mStartStatus !=NO_ERROR) {
-                    LOGW("record start failed, status %d", mStartStatus);
-                    mActive = false;
-                    mRecordTrack.clear();                    
-                }
-                mWaitWorkCV.signal();
-            }
-            mLock.unlock();
-        } else if (mRecordTrack != 0) {
+                    // resampling
 
-            buffer.frameCount = inFrameCount;
-            if (LIKELY(mRecordTrack->getNextBuffer(&buffer) == NO_ERROR &&
-                       (int)buffer.frameCount == inFrameCount)) {
-                LOGV("AudioRecordThread read: %d frames", buffer.frameCount);
-                ssize_t bytesRead = input->read(buffer.raw, inBufferSize);
-                if (bytesRead < 0) {
-                    LOGE("Error reading audio input");
-                    sleep(1);
-                }
-                mRecordTrack->releaseBuffer(&buffer);
-                mRecordTrack->overflow();
-            }
+                    memset(mRsmpOutBuffer, 0, framesOut * 2 * sizeof(int32_t));
+                    // alter output frame count as if we were expecting stereo samples
+                    if (mChannelCount == 1 && mReqChannelCount == 1) {
+                        framesOut >>= 1;
+                    }
+                    mResampler->resample(mRsmpOutBuffer, framesOut, this);
+                    // ditherAndClamp() works as long as all buffers returned by mActiveTrack->getNextBuffer()
+                    // are 32 bit aligned which should be always true.
+                    if (mChannelCount == 2 && mReqChannelCount == 1) {
+                        AudioMixer::ditherAndClamp(mRsmpOutBuffer, mRsmpOutBuffer, framesOut);
+                        // the resampler always outputs stereo samples: do post stereo to mono conversion
+                        int16_t *src = (int16_t *)mRsmpOutBuffer;
+                        int16_t *dst = buffer.i16;
+                        while (framesOut--) {
+                            *dst++ = (int16_t)(((int32_t)*src + (int32_t)*(src + 1)) >> 1);
+                            src += 2;
+                        }
+                    } else {
+                        AudioMixer::ditherAndClamp((int32_t *)buffer.raw, mRsmpOutBuffer, framesOut);
+                    }
 
+                }
+                mActiveTrack->releaseBuffer(&buffer);
+                mActiveTrack->overflow();
+            }
             // client isn't retrieving buffers fast enough
             else {
-                if (!mRecordTrack->setOverflow())
-                    LOGW("AudioRecordThread: buffer overflow");
+                if (!mActiveTrack->setOverflow())
+                    LOGW("RecordThread: buffer overflow");
                 // Release the processor for a while before asking for a new buffer.
                 // This will give the application more chance to read from the buffer and
                 // clear the overflow.
@@ -2459,73 +3151,559 @@
         }
     }
 
-
-    if (input) {
-        delete input;
+    if (!mStandby) {
+        mInput->standby();
     }
-    mRecordTrack.clear();
-    
+    mActiveTrack.clear();
+
+    LOGV("RecordThread %p exiting", this);
     return false;
 }
 
-status_t AudioFlinger::AudioRecordThread::start(MixerThread::RecordTrack* recordTrack)
+status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrack)
 {
-    LOGV("AudioRecordThread::start");
+    LOGV("RecordThread::start");
     AutoMutex lock(&mLock);
-    mActive = true;
-    // If starting the active track, just reset mActive in case a stop
-    // was pending and exit
-    if (recordTrack == mRecordTrack.get()) return NO_ERROR;
 
-    if (mRecordTrack != 0) return -EBUSY;
+    if (mActiveTrack != 0) {
+        if (recordTrack != mActiveTrack.get()) return -EBUSY;
 
-    mRecordTrack = recordTrack;
+        if (mActiveTrack->mState == TrackBase::PAUSING) mActiveTrack->mState = TrackBase::RESUMING;
 
+        return NO_ERROR;
+    }
+
+    mActiveTrack = recordTrack;
+    mActiveTrack->mState = TrackBase::RESUMING;
     // signal thread to start
     LOGV("Signal record thread");
     mWaitWorkCV.signal();
-    mWaitWorkCV.wait(mLock);
-    LOGV("Record started, status %d", mStartStatus);
-    return mStartStatus;
+    mStartStopCond.wait(mLock);
+    if (mActiveTrack != 0) {
+        LOGV("Record started OK");
+        return NO_ERROR;
+    } else {
+        LOGV("Record failed to start");
+        return BAD_VALUE;
+    }
 }
 
-void AudioFlinger::AudioRecordThread::stop(MixerThread::RecordTrack* recordTrack) {
-    LOGV("AudioRecordThread::stop");
+void AudioFlinger::RecordThread::stop(RecordThread::RecordTrack* recordTrack) {
+    LOGV("RecordThread::stop");
     AutoMutex lock(&mLock);
-    if (mActive && (recordTrack == mRecordTrack.get())) {
-        mActive = false;
-        mStopped.wait(mLock);
+    if (mActiveTrack != 0 && recordTrack == mActiveTrack.get()) {
+        mActiveTrack->mState = TrackBase::PAUSING;
+        mStartStopCond.wait(mLock);
     }
 }
 
-void AudioFlinger::AudioRecordThread::exit()
-{
-    LOGV("AudioRecordThread::exit");
-    {
-        AutoMutex lock(&mLock);
-        requestExit();
-        mWaitWorkCV.signal();
-    }
-    requestExitAndWait();
-}
-
-status_t AudioFlinger::AudioRecordThread::dump(int fd, const Vector<String16>& args)
+status_t AudioFlinger::RecordThread::dump(int fd, const Vector<String16>& args)
 {
     const size_t SIZE = 256;
     char buffer[SIZE];
     String8 result;
     pid_t pid = 0;
 
-    if (mRecordTrack != 0 && mRecordTrack->mClient != 0) {
-        snprintf(buffer, SIZE, "Record client pid: %d\n", mRecordTrack->mClient->pid());
+    snprintf(buffer, SIZE, "\nInput thread %p internals\n", this);
+    result.append(buffer);
+
+    if (mActiveTrack != 0) {
+        result.append("Active Track:\n");
+        result.append("   Clien Fmt Chn Buf  S SRate  Serv     User\n");
+        mActiveTrack->dump(buffer, SIZE);
         result.append(buffer);
+
+        snprintf(buffer, SIZE, "In index: %d\n", mRsmpInIndex);
+        result.append(buffer);
+        snprintf(buffer, SIZE, "In size: %d\n", mInputBytes);
+        result.append(buffer);
+        snprintf(buffer, SIZE, "Resampling: %d\n", (mResampler != 0));
+        result.append(buffer);
+        snprintf(buffer, SIZE, "Out channel count: %d\n", mReqChannelCount);
+        result.append(buffer);
+        snprintf(buffer, SIZE, "Out sample rate: %d\n", mReqSampleRate);
+        result.append(buffer);
+
+
     } else {
         result.append("No record client\n");
     }
     write(fd, result.string(), result.size());
+
+    dumpBase(fd, args);
+
     return NO_ERROR;
 }
 
+status_t AudioFlinger::RecordThread::getNextBuffer(AudioBufferProvider::Buffer* buffer)
+{
+    size_t framesReq = buffer->frameCount;
+    size_t framesReady = mFrameCount - mRsmpInIndex;
+    int channelCount;
+
+    if (framesReady == 0) {
+        ssize_t bytesRead = mInput->read(mRsmpInBuffer, mInputBytes);
+        if (bytesRead < 0) {
+            LOGE("RecordThread::getNextBuffer() Error reading audio input");
+            sleep(1);
+            buffer->raw = 0;
+            buffer->frameCount = 0;
+            return NOT_ENOUGH_DATA;
+        }
+        mRsmpInIndex = 0;
+        framesReady = mFrameCount;
+    }
+
+    if (framesReq > framesReady) {
+        framesReq = framesReady;
+    }
+
+    if (mChannelCount == 1 && mReqChannelCount == 2) {
+        channelCount = 1;
+    } else {
+        channelCount = 2;
+    }
+    buffer->raw = mRsmpInBuffer + mRsmpInIndex * channelCount;
+    buffer->frameCount = framesReq;
+    return NO_ERROR;
+}
+
+void AudioFlinger::RecordThread::releaseBuffer(AudioBufferProvider::Buffer* buffer)
+{
+    mRsmpInIndex += buffer->frameCount;
+    buffer->frameCount = 0;
+}
+
+bool AudioFlinger::RecordThread::checkForNewParameters_l()
+{
+    bool reconfig = false;
+
+    while (!mNewParameters.isEmpty()) {
+        status_t status = NO_ERROR;
+        String8 keyValuePair = mNewParameters[0];
+        AudioParameter param = AudioParameter(keyValuePair);
+        int value;
+        int reqFormat = mFormat;
+        int reqSamplingRate = mReqSampleRate;
+        int reqChannelCount = mReqChannelCount;
+
+        if (param.getInt(String8(AudioParameter::keySamplingRate), value) == NO_ERROR) {
+            reqSamplingRate = value;
+            reconfig = true;
+        }
+        if (param.getInt(String8(AudioParameter::keyFormat), value) == NO_ERROR) {
+            reqFormat = value;
+            reconfig = true;
+        }
+        if (param.getInt(String8(AudioParameter::keyChannels), value) == NO_ERROR) {
+            reqChannelCount = AudioSystem::popCount(value);
+            reconfig = true;
+        }
+        if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
+            // do not accept frame count changes if tracks are open as the track buffer
+            // size depends on frame count and correct behavior would not be garantied
+            // if frame count is changed after track creation
+            if (mActiveTrack != 0) {
+                status = INVALID_OPERATION;
+            } else {
+                reconfig = true;
+            }
+        }
+        if (status == NO_ERROR) {
+            status = mInput->setParameters(keyValuePair);
+            if (status == INVALID_OPERATION) {
+               mInput->standby();
+               status = mInput->setParameters(keyValuePair);
+            }
+            if (reconfig) {
+                if (status == BAD_VALUE &&
+                    reqFormat == mInput->format() && reqFormat == AudioSystem::PCM_16_BIT &&
+                    ((int)mInput->sampleRate() <= 2 * reqSamplingRate) &&
+                    (AudioSystem::popCount(mInput->channels()) < 3) && (reqChannelCount < 3)) {
+                    status = NO_ERROR;
+                }
+                if (status == NO_ERROR) {
+                    readInputParameters();
+                    sendConfigEvent_l(AudioSystem::INPUT_CONFIG_CHANGED);
+                }
+            }
+        }
+
+        mNewParameters.removeAt(0);
+
+        mParamStatus = status;
+        mParamCond.signal();
+        mWaitWorkCV.wait(mLock);
+    }
+    return reconfig;
+}
+
+String8 AudioFlinger::RecordThread::getParameters(const String8& keys)
+{
+    return mInput->getParameters(keys);
+}
+
+void AudioFlinger::RecordThread::audioConfigChanged(int event, int param) {
+    AudioSystem::OutputDescriptor desc;
+    void *param2 = 0;
+
+    switch (event) {
+    case AudioSystem::INPUT_OPENED:
+    case AudioSystem::INPUT_CONFIG_CHANGED:
+        desc.channels = mChannelCount;
+        desc.samplingRate = mSampleRate;
+        desc.format = mFormat;
+        desc.frameCount = mFrameCount;
+        desc.latency = 0;
+        param2 = &desc;
+        break;
+
+    case AudioSystem::INPUT_CLOSED:
+    default:
+        break;
+    }
+    Mutex::Autolock _l(mAudioFlinger->mLock);
+    mAudioFlinger->audioConfigChanged_l(event, this, param2);
+}
+
+void AudioFlinger::RecordThread::readInputParameters()
+{
+    if (mRsmpInBuffer) delete mRsmpInBuffer;
+    if (mRsmpOutBuffer) delete mRsmpOutBuffer;
+    if (mResampler) delete mResampler;
+    mResampler = 0;
+
+    mSampleRate = mInput->sampleRate();
+    mChannelCount = AudioSystem::popCount(mInput->channels());
+    mFormat = mInput->format();
+    mFrameSize = mInput->frameSize();
+    mInputBytes = mInput->bufferSize();
+    mFrameCount = mInputBytes / mFrameSize;
+    mRsmpInBuffer = new int16_t[mFrameCount * mChannelCount];
+
+    if (mSampleRate != mReqSampleRate && mChannelCount < 3 && mReqChannelCount < 3)
+    {
+        int channelCount;
+         // optmization: if mono to mono, use the resampler in stereo to stereo mode to avoid
+         // stereo to mono post process as the resampler always outputs stereo.
+        if (mChannelCount == 1 && mReqChannelCount == 2) {
+            channelCount = 1;
+        } else {
+            channelCount = 2;
+        }
+        mResampler = AudioResampler::create(16, channelCount, mReqSampleRate);
+        mResampler->setSampleRate(mSampleRate);
+        mResampler->setVolume(AudioMixer::UNITY_GAIN, AudioMixer::UNITY_GAIN);
+        mRsmpOutBuffer = new int32_t[mFrameCount * 2];
+
+        // optmization: if mono to mono, alter input frame count as if we were inputing stereo samples
+        if (mChannelCount == 1 && mReqChannelCount == 1) {
+            mFrameCount >>= 1;
+        }
+
+    }
+    mRsmpInIndex = mFrameCount;
+}
+
+// ----------------------------------------------------------------------------
+
+int AudioFlinger::openOutput(uint32_t *pDevices,
+                                uint32_t *pSamplingRate,
+                                uint32_t *pFormat,
+                                uint32_t *pChannels,
+                                uint32_t *pLatencyMs,
+                                uint32_t flags)
+{
+    status_t status;
+    PlaybackThread *thread = NULL;
+    mHardwareStatus = AUDIO_HW_OUTPUT_OPEN;
+    uint32_t samplingRate = pSamplingRate ? *pSamplingRate : 0;
+    uint32_t format = pFormat ? *pFormat : 0;
+    uint32_t channels = pChannels ? *pChannels : 0;
+    uint32_t latency = pLatencyMs ? *pLatencyMs : 0;
+
+    LOGV("openOutput(), Device %x, SamplingRate %d, Format %d, Channels %x, flags %x",
+            pDevices ? *pDevices : 0,
+            samplingRate,
+            format,
+            channels,
+            flags);
+
+    if (pDevices == NULL || *pDevices == 0) {
+        return 0;
+    }
+    Mutex::Autolock _l(mLock);
+
+    AudioStreamOut *output = mAudioHardware->openOutputStream(*pDevices,
+                                                             (int *)&format,
+                                                             &channels,
+                                                             &samplingRate,
+                                                             &status);
+    LOGV("openOutput() openOutputStream returned output %p, SamplingRate %d, Format %d, Channels %x, status %d",
+            output,
+            samplingRate,
+            format,
+            channels,
+            status);
+
+    mHardwareStatus = AUDIO_HW_IDLE;
+    if (output != 0) {
+        if ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) ||
+            (format != AudioSystem::PCM_16_BIT) ||
+            (channels != AudioSystem::CHANNEL_OUT_STEREO)) {
+            thread = new DirectOutputThread(this, output);
+            LOGV("openOutput() created direct output: ID %d thread %p", (mNextThreadId + 1), thread);
+        } else {
+            thread = new MixerThread(this, output);
+            LOGV("openOutput() created mixer output: ID %d thread %p", (mNextThreadId + 1), thread);
+        }
+        mPlaybackThreads.add(++mNextThreadId, thread);
+
+        if (pSamplingRate) *pSamplingRate = samplingRate;
+        if (pFormat) *pFormat = format;
+        if (pChannels) *pChannels = channels;
+        if (pLatencyMs) *pLatencyMs = thread->latency();
+    }
+
+    return mNextThreadId;
+}
+
+int AudioFlinger::openDuplicateOutput(int output1, int output2)
+{
+    Mutex::Autolock _l(mLock);
+    MixerThread *thread1 = checkMixerThread_l(output1);
+    MixerThread *thread2 = checkMixerThread_l(output2);
+
+    if (thread1 == NULL || thread2 == NULL) {
+        LOGW("openDuplicateOutput() wrong output mixer type for output %d or %d", output1, output2);
+        return 0;
+    }
+
+
+    DuplicatingThread *thread = new DuplicatingThread(this, thread1);
+    thread->addOutputTrack(thread2);
+    mPlaybackThreads.add(++mNextThreadId, thread);
+    return mNextThreadId;
+}
+
+status_t AudioFlinger::closeOutput(int output)
+{
+    // keep strong reference on the playback thread so that
+    // it is not destroyed while exit() is executed
+    sp <PlaybackThread> thread;
+    {
+        Mutex::Autolock _l(mLock);
+        thread = checkPlaybackThread_l(output);
+        if (thread == NULL) {
+            return BAD_VALUE;
+        }
+
+        LOGV("closeOutput() %d", output);
+
+        if (thread->type() == PlaybackThread::MIXER) {
+            for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
+                if (mPlaybackThreads.valueAt(i)->type() == PlaybackThread::DUPLICATING) {
+                    DuplicatingThread *dupThread = (DuplicatingThread *)mPlaybackThreads.valueAt(i).get();
+                    dupThread->removeOutputTrack((MixerThread *)thread.get());
+                }
+            }
+        }
+        void *param2 = 0;
+        audioConfigChanged_l(AudioSystem::OUTPUT_CLOSED, thread, param2);
+        mPlaybackThreads.removeItem(output);
+    }
+    thread->exit();
+
+    if (thread->type() != PlaybackThread::DUPLICATING) {
+        mAudioHardware->closeOutputStream(thread->getOutput());
+    }
+    return NO_ERROR;
+}
+
+status_t AudioFlinger::suspendOutput(int output)
+{
+    Mutex::Autolock _l(mLock);
+    PlaybackThread *thread = checkPlaybackThread_l(output);
+
+    if (thread == NULL) {
+        return BAD_VALUE;
+    }
+
+    LOGV("suspendOutput() %d", output);
+    thread->suspend();
+
+    return NO_ERROR;
+}
+
+status_t AudioFlinger::restoreOutput(int output)
+{
+    Mutex::Autolock _l(mLock);
+    PlaybackThread *thread = checkPlaybackThread_l(output);
+
+    if (thread == NULL) {
+        return BAD_VALUE;
+    }
+
+    LOGV("restoreOutput() %d", output);
+
+    thread->restore();
+
+    return NO_ERROR;
+}
+
+int AudioFlinger::openInput(uint32_t *pDevices,
+                                uint32_t *pSamplingRate,
+                                uint32_t *pFormat,
+                                uint32_t *pChannels,
+                                uint32_t acoustics)
+{
+    status_t status;
+    RecordThread *thread = NULL;
+    uint32_t samplingRate = pSamplingRate ? *pSamplingRate : 0;
+    uint32_t format = pFormat ? *pFormat : 0;
+    uint32_t channels = pChannels ? *pChannels : 0;
+    uint32_t reqSamplingRate = samplingRate;
+    uint32_t reqFormat = format;
+    uint32_t reqChannels = channels;
+
+    if (pDevices == NULL || *pDevices == 0) {
+        return 0;
+    }
+    Mutex::Autolock _l(mLock);
+
+    AudioStreamIn *input = mAudioHardware->openInputStream(*pDevices,
+                                                             (int *)&format,
+                                                             &channels,
+                                                             &samplingRate,
+                                                             &status,
+                                                             (AudioSystem::audio_in_acoustics)acoustics);
+    LOGV("openInput() openInputStream returned input %p, SamplingRate %d, Format %d, Channels %x, acoustics %x, status %d",
+            input,
+            samplingRate,
+            format,
+            channels,
+            acoustics,
+            status);
+
+    // If the input could not be opened with the requested parameters and we can handle the conversion internally,
+    // try to open again with the proposed parameters. The AudioFlinger can resample the input and do mono to stereo
+    // or stereo to mono conversions on 16 bit PCM inputs.
+    if (input == 0 && status == BAD_VALUE &&
+        reqFormat == format && format == AudioSystem::PCM_16_BIT &&
+        (samplingRate <= 2 * reqSamplingRate) &&
+        (AudioSystem::popCount(channels) < 3) && (AudioSystem::popCount(reqChannels) < 3)) {
+        LOGV("openInput() reopening with proposed sampling rate and channels");
+        input = mAudioHardware->openInputStream(*pDevices,
+                                                 (int *)&format,
+                                                 &channels,
+                                                 &samplingRate,
+                                                 &status,
+                                                 (AudioSystem::audio_in_acoustics)acoustics);
+    }
+
+    if (input != 0) {
+         // Start record thread
+        thread = new RecordThread(this, input, reqSamplingRate, reqChannels);
+        mRecordThreads.add(++mNextThreadId, thread);
+        LOGV("openInput() created record thread: ID %d thread %p", mNextThreadId, thread);
+        if (pSamplingRate) *pSamplingRate = reqSamplingRate;
+        if (pFormat) *pFormat = format;
+        if (pChannels) *pChannels = reqChannels;
+
+        input->standby();
+    }
+
+    return mNextThreadId;
+}
+
+status_t AudioFlinger::closeInput(int input)
+{
+    // keep strong reference on the record thread so that
+    // it is not destroyed while exit() is executed
+    sp <RecordThread> thread;
+    {
+        Mutex::Autolock _l(mLock);
+        thread = checkRecordThread_l(input);
+        if (thread == NULL) {
+            return BAD_VALUE;
+        }
+
+        LOGV("closeInput() %d", input);
+        void *param2 = 0;
+        audioConfigChanged_l(AudioSystem::INPUT_CLOSED, thread, param2);
+        mRecordThreads.removeItem(input);
+    }
+    thread->exit();
+
+    mAudioHardware->closeInputStream(thread->getInput());
+
+    return NO_ERROR;
+}
+
+status_t AudioFlinger::setStreamOutput(uint32_t stream, int output)
+{
+    Mutex::Autolock _l(mLock);
+    MixerThread *dstThread = checkMixerThread_l(output);
+    if (dstThread == NULL) {
+        LOGW("setStreamOutput() bad output id %d", output);
+        return BAD_VALUE;
+    }
+
+    LOGV("setStreamOutput() stream %d to output %d", stream, output);
+
+    for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
+        PlaybackThread *thread = mPlaybackThreads.valueAt(i).get();
+        if (thread != dstThread &&
+            thread->type() != PlaybackThread::DIRECT) {
+            MixerThread *srcThread = (MixerThread *)thread;
+            SortedVector < sp<MixerThread::Track> > tracks;
+            SortedVector < wp<MixerThread::Track> > activeTracks;
+            srcThread->getTracks(tracks, activeTracks, stream);
+            if (tracks.size()) {
+                dstThread->putTracks(tracks, activeTracks);
+            }
+        }
+    }
+
+    dstThread->sendConfigEvent(AudioSystem::STREAM_CONFIG_CHANGED, stream);
+
+    return NO_ERROR;
+}
+
+// checkPlaybackThread_l() must be called with AudioFlinger::mLock held
+AudioFlinger::PlaybackThread *AudioFlinger::checkPlaybackThread_l(int output) const
+{
+    PlaybackThread *thread = NULL;
+    if (mPlaybackThreads.indexOfKey(output) >= 0) {
+        thread = (PlaybackThread *)mPlaybackThreads.valueFor(output).get();
+    }
+    return thread;
+}
+
+// checkMixerThread_l() must be called with AudioFlinger::mLock held
+AudioFlinger::MixerThread *AudioFlinger::checkMixerThread_l(int output) const
+{
+    PlaybackThread *thread = checkPlaybackThread_l(output);
+    if (thread != NULL) {
+        if (thread->type() == PlaybackThread::DIRECT) {
+            thread = NULL;
+        }
+    }
+    return (MixerThread *)thread;
+}
+
+// checkRecordThread_l() must be called with AudioFlinger::mLock held
+AudioFlinger::RecordThread *AudioFlinger::checkRecordThread_l(int input) const
+{
+    RecordThread *thread = NULL;
+    if (mRecordThreads.indexOfKey(input) >= 0) {
+        thread = (RecordThread *)mRecordThreads.valueFor(input).get();
+    }
+    return thread;
+}
+
+// ----------------------------------------------------------------------------
+
 status_t AudioFlinger::onTransact(
         uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
 {
@@ -2533,6 +3711,7 @@
 }
 
 // ----------------------------------------------------------------------------
+
 void AudioFlinger::instantiate() {
     defaultServiceManager()->addService(
             String16("media.audio_flinger"), new AudioFlinger());
diff --git a/libs/audioflinger/AudioFlinger.h b/libs/audioflinger/AudioFlinger.h
index 634934e..22d15c9 100644
--- a/libs/audioflinger/AudioFlinger.h
+++ b/libs/audioflinger/AudioFlinger.h
@@ -30,8 +30,7 @@
 #include <utils/Atomic.h>
 #include <utils/Errors.h>
 #include <utils/threads.h>
-#include <utils/MemoryDealer.h>
-#include <utils/KeyedVector.h>
+#include <binder/MemoryDealer.h>
 #include <utils/SortedVector.h>
 #include <utils/Vector.h>
 
@@ -44,6 +43,7 @@
 class audio_track_cblk_t;
 class AudioMixer;
 class AudioBuffer;
+class AudioResampler;
 
 
 // ----------------------------------------------------------------------------
@@ -56,7 +56,7 @@
 
 static const nsecs_t kStandbyTimeInNsecs = seconds(3);
 
-class AudioFlinger : public BnAudioFlinger, public IBinder::DeathRecipient 
+class AudioFlinger : public BnAudioFlinger, public IBinder::DeathRecipient
 {
 public:
     static void instantiate();
@@ -73,6 +73,7 @@
                                 int frameCount,
                                 uint32_t flags,
                                 const sp<IMemory>& sharedBuffer,
+                                int output,
                                 status_t *status);
 
     virtual     uint32_t    sampleRate(int output) const;
@@ -87,33 +88,53 @@
     virtual     float       masterVolume() const;
     virtual     bool        masterMute() const;
 
-    virtual     status_t    setStreamVolume(int stream, float value);
+    virtual     status_t    setStreamVolume(int stream, float value, int output);
     virtual     status_t    setStreamMute(int stream, bool muted);
 
-    virtual     float       streamVolume(int stream) const;
+    virtual     float       streamVolume(int stream, int output) const;
     virtual     bool        streamMute(int stream) const;
 
-    virtual     status_t    setRouting(int mode, uint32_t routes, uint32_t mask);
-    virtual     uint32_t    getRouting(int mode) const;
-
     virtual     status_t    setMode(int mode);
-    virtual     int         getMode() const;
 
     virtual     status_t    setMicMute(bool state);
     virtual     bool        getMicMute() const;
 
     virtual     bool        isMusicActive() const;
 
-    virtual     bool        isA2dpEnabled() const;
-
-    virtual     status_t    setParameter(const char* key, const char* value);
+    virtual     status_t    setParameters(int ioHandle, const String8& keyValuePairs);
+    virtual     String8     getParameters(int ioHandle, const String8& keys);
 
     virtual     void        registerClient(const sp<IAudioFlingerClient>& client);
-    
+
     virtual     size_t      getInputBufferSize(uint32_t sampleRate, int format, int channelCount);
-    
-    virtual     void        wakeUp()    { mWaitWorkCV.broadcast(); }
-    
+
+    virtual int openOutput(uint32_t *pDevices,
+                                    uint32_t *pSamplingRate,
+                                    uint32_t *pFormat,
+                                    uint32_t *pChannels,
+                                    uint32_t *pLatencyMs,
+                                    uint32_t flags);
+
+    virtual int openDuplicateOutput(int output1, int output2);
+
+    virtual status_t closeOutput(int output);
+
+    virtual status_t suspendOutput(int output);
+
+    virtual status_t restoreOutput(int output);
+
+    virtual int openInput(uint32_t *pDevices,
+                            uint32_t *pSamplingRate,
+                            uint32_t *pFormat,
+                            uint32_t *pChannels,
+                            uint32_t acoustics);
+
+    virtual status_t closeInput(int input);
+
+    virtual status_t setStreamOutput(uint32_t stream, int output);
+
+    virtual status_t setVoiceVolume(float volume);
+
     // IBinder::DeathRecipient
     virtual     void        binderDied(const wp<IBinder>& who);
 
@@ -139,7 +160,7 @@
     // record interface
     virtual sp<IAudioRecord> openRecord(
                                 pid_t pid,
-                                int inputSource,
+                                int input,
                                 uint32_t sampleRate,
                                 int format,
                                 int channelCount,
@@ -156,27 +177,7 @@
 private:
                             AudioFlinger();
     virtual                 ~AudioFlinger();
-    
-    void                    setOutput(int outputType);
-    void                    doSetOutput(int outputType);
 
-#ifdef WITH_A2DP
-    void                    setA2dpEnabled_l(bool enable);
-    void                    checkA2dpEnabledChange_l();
-#endif
-    static bool             streamForcedToSpeaker(int streamType);
-    
-    // Management of forced route to speaker for certain track types.
-    enum force_speaker_command {
-        ACTIVE_TRACK_ADDED = 0,
-        ACTIVE_TRACK_REMOVED,
-        CHECK_ROUTE_RESTORE_TIME,
-        FORCE_ROUTE_RESTORE
-    };
-    void                    handleForcedSpeakerRoute(int command);
-#ifdef WITH_A2DP
-    void                    handleRouteDisablesA2dp_l(int routes);
-#endif
 
     // Internal dump utilites.
     status_t dumpPermissionDenial(int fd, const Vector<String16>& args);
@@ -190,6 +191,8 @@
         virtual             ~Client();
         const sp<MemoryDealer>&     heap() const;
         pid_t               pid() const { return mPid; }
+        sp<AudioFlinger>    audioFlinger() { return mAudioFlinger; }
+
     private:
                             Client(const Client&);
                             Client& operator = (const Client&);
@@ -201,14 +204,19 @@
 
     class TrackHandle;
     class RecordHandle;
-    class AudioRecordThread;
+    class RecordThread;
+    class PlaybackThread;
+    class MixerThread;
+    class DirectOutputThread;
+    class Track;
+    class RecordTrack;
 
-    
-    // --- MixerThread ---
-    class MixerThread : public Thread {
+    class ThreadBase : public Thread {
     public:
-        
-        // --- Track ---
+        ThreadBase (const sp<AudioFlinger>& audioFlinger);
+        virtual             ~ThreadBase();
+
+        status_t dumpBase(int fd, const Vector<String16>& args);
 
         // base for record and playback
         class TrackBase : public AudioBufferProvider, public RefBase {
@@ -230,7 +238,7 @@
                 // The upper 16 bits are used for track-specific flags.
             };
 
-                                TrackBase(const sp<MixerThread>& mixerThread,
+                                TrackBase(const wp<ThreadBase>& thread,
                                         const sp<Client>& client,
                                         uint32_t sampleRate,
                                         int format,
@@ -243,11 +251,15 @@
             virtual status_t    start() = 0;
             virtual void        stop() = 0;
                     sp<IMemory> getCblk() const;
+                    audio_track_cblk_t* cblk() const { return mCblk; }
 
         protected:
-            friend class MixerThread;
+            friend class ThreadBase;
             friend class RecordHandle;
-            friend class AudioRecordThread;
+            friend class PlaybackThread;
+            friend class RecordThread;
+            friend class MixerThread;
+            friend class DirectOutputThread;
 
                                 TrackBase(const TrackBase&);
                                 TrackBase& operator = (const TrackBase&);
@@ -255,10 +267,6 @@
             virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer) = 0;
             virtual void releaseBuffer(AudioBufferProvider::Buffer* buffer);
 
-            audio_track_cblk_t* cblk() const {
-                return mCblk;
-            }
-
             int format() const {
                 return mFormat;
             }
@@ -269,10 +277,6 @@
 
             void* getBuffer(uint32_t offset, uint32_t frames) const;
 
-            int name() const {
-                return mName;
-            }
-
             bool isStopped() const {
                 return mState == STOPPED;
             }
@@ -284,14 +288,13 @@
             bool step();
             void reset();
 
-            sp<MixerThread>     mMixerThread;
+            wp<ThreadBase>      mThread;
             sp<Client>          mClient;
             sp<IMemory>         mCblkMemory;
             audio_track_cblk_t* mCblk;
             void*               mBuffer;
             void*               mBufferEnd;
             uint32_t            mFrameCount;
-            int                 mName;
             // we don't really need a lock for these
             int                 mState;
             int                 mClientTid;
@@ -299,10 +302,69 @@
             uint32_t            mFlags;
         };
 
+        class ConfigEvent {
+        public:
+            ConfigEvent() : mEvent(0), mParam(0) {}
+
+            int mEvent;
+            int mParam;
+        };
+
+                    uint32_t    sampleRate() const;
+                    int         channelCount() const;
+                    int         format() const;
+                    size_t      frameCount() const;
+                    void        wakeUp()    { mWaitWorkCV.broadcast(); }
+                    void        exit();
+        virtual     bool        checkForNewParameters_l() = 0;
+        virtual     status_t    setParameters(const String8& keyValuePairs);
+        virtual     String8     getParameters(const String8& keys) = 0;
+        virtual     void        audioConfigChanged(int event, int param = 0) = 0;
+                    void        sendConfigEvent(int event, int param = 0);
+                    void        sendConfigEvent_l(int event, int param = 0);
+                    void        processConfigEvents();
+
+        mutable     Mutex                   mLock;
+
+    protected:
+
+        friend class Track;
+        friend class TrackBase;
+        friend class PlaybackThread;
+        friend class MixerThread;
+        friend class DirectOutputThread;
+        friend class DuplicatingThread;
+        friend class RecordThread;
+        friend class RecordTrack;
+
+                    Condition               mWaitWorkCV;
+                    sp<AudioFlinger>        mAudioFlinger;
+                    uint32_t                mSampleRate;
+                    size_t                  mFrameCount;
+                    int                     mChannelCount;
+                    int                     mFormat;
+                    uint32_t                mFrameSize;
+                    Condition               mParamCond;
+                    Vector<String8>         mNewParameters;
+                    status_t                mParamStatus;
+                    Vector<ConfigEvent *>   mConfigEvents;
+                    bool                    mStandby;
+    };
+
+    // --- PlaybackThread ---
+    class PlaybackThread : public ThreadBase {
+    public:
+
+        enum type {
+            MIXER,
+            DIRECT,
+            DUPLICATING
+        };
+
         // playback track
         class Track : public TrackBase {
         public:
-                                Track(  const sp<MixerThread>& mixerThread,
+                                Track(  const wp<ThreadBase>& thread,
                                         const sp<Client>& client,
                                         int streamType,
                                         uint32_t sampleRate,
@@ -321,6 +383,9 @@
                     void        destroy();
                     void        mute(bool);
                     void        setVolume(float left, float right);
+                    int name() const {
+                        return mName;
+                    }
 
                     int type() const {
                         return mStreamType;
@@ -328,29 +393,25 @@
 
 
         protected:
-            friend class MixerThread;
+            friend class ThreadBase;
             friend class AudioFlinger;
-            friend class AudioFlinger::TrackHandle;
+            friend class TrackHandle;
+            friend class PlaybackThread;
+            friend class MixerThread;
+            friend class DirectOutputThread;
 
                                 Track(const Track&);
                                 Track& operator = (const Track&);
 
             virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer);
-
-            bool isMuted() const {
-                return (mMute || mMixerThread->mStreamTypes[mStreamType].mute);
-            }
-
+            bool isMuted() { return mMute; }
             bool isPausing() const {
                 return mState == PAUSING;
             }
-
             bool isPaused() const {
                 return mState == PAUSED;
             }
-
             bool isReady() const;
-
             void setPaused() { mState = PAUSED; }
             void reset();
 
@@ -364,54 +425,20 @@
             sp<IMemory>         mSharedBuffer;
             bool                mResetDone;
             int                 mStreamType;
+            int                 mName;
         };  // end of Track
 
-        // record track
-        class RecordTrack : public TrackBase {
-        public:
-                                RecordTrack(const sp<MixerThread>& mixerThread,
-                                        const sp<Client>& client,
-                                        int inputSource,
-                                        uint32_t sampleRate,
-                                        int format,
-                                        int channelCount,
-                                        int frameCount,
-                                        uint32_t flags);
-                                ~RecordTrack();
-
-            virtual status_t    start();
-            virtual void        stop();
-
-                    bool        overflow() { bool tmp = mOverflow; mOverflow = false; return tmp; }
-                    bool        setOverflow() { bool tmp = mOverflow; mOverflow = true; return tmp; }
-
-                    int         inputSource() const { return mInputSource; }
-
-        private:
-            friend class AudioFlinger;
-            friend class AudioFlinger::RecordHandle;
-            friend class AudioFlinger::AudioRecordThread;
-            friend class MixerThread;
-
-                                RecordTrack(const Track&);
-                                RecordTrack& operator = (const Track&);
-
-            virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer);
-
-            bool                mOverflow;
-            int                 mInputSource;
-        };
 
         // playback track
         class OutputTrack : public Track {
         public:
-            
+
             class Buffer: public AudioBufferProvider::Buffer {
             public:
                 int16_t *mBuffer;
             };
-            
-                                OutputTrack(  const sp<MixerThread>& mixerThread,
+
+                                OutputTrack(  const wp<ThreadBase>& thread,
                                         uint32_t sampleRate,
                                         int format,
                                         int channelCount,
@@ -420,35 +447,35 @@
 
             virtual status_t    start();
             virtual void        stop();
-                    void        write(int16_t* data, uint32_t frames);
+                    bool        write(int16_t* data, uint32_t frames);
                     bool        bufferQueueEmpty() { return (mBufferQueue.size() == 0) ? true : false; }
+                    bool        isActive() { return mActive; }
+            wp<ThreadBase>&     thread()  { return mThread; }
 
         private:
 
-            status_t            obtainBuffer(AudioBufferProvider::Buffer* buffer);
+            status_t            obtainBuffer(AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs);
             void                clearBufferQueue();
-            
-            sp<MixerThread>             mOutputMixerThread;
+
+            // Maximum number of pending buffers allocated by OutputTrack::write()
+            static const uint8_t kMaxOverFlowBuffers = 3;
+
             Vector < Buffer* >          mBufferQueue;
             AudioBufferProvider::Buffer mOutBuffer;
-            uint32_t                    mFramesWritten;
-            
-         };  // end of OutputTrack
+            uint32_t                    mWaitTimeMs;
+            bool                        mActive;
 
-        MixerThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int outputType);
-        virtual             ~MixerThread();
+        };  // end of OutputTrack
+
+        PlaybackThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output);
+        virtual             ~PlaybackThread();
 
         virtual     status_t    dump(int fd, const Vector<String16>& args);
 
         // Thread virtuals
-        virtual     bool        threadLoop();
         virtual     status_t    readyToRun();
         virtual     void        onFirstRef();
 
-        virtual     uint32_t    sampleRate() const;
-        virtual     int         channelCount() const;
-        virtual     int         format() const;
-        virtual     size_t      frameCount() const;
         virtual     uint32_t    latency() const;
 
         virtual     status_t    setMasterVolume(float value);
@@ -463,9 +490,8 @@
         virtual     float       streamVolume(int stream) const;
         virtual     bool        streamMute(int stream) const;
 
-                    bool        isMusicActive_l() const;
-        
-                    
+                    bool        isMusicActive() const;
+
                     sp<Track>   createTrack_l(
                                     const sp<AudioFlinger::Client>& client,
                                     int streamType,
@@ -475,13 +501,15 @@
                                     int frameCount,
                                     const sp<IMemory>& sharedBuffer,
                                     status_t *status);
-                    
-                    void        getTracks_l(SortedVector < sp<Track> >& tracks,
-                                          SortedVector < wp<Track> >& activeTracks);
-                    void        putTracks_l(SortedVector < sp<Track> >& tracks,
-                                          SortedVector < wp<Track> >& activeTracks);
-                    void        setOuputTrack(OutputTrack *track) { mOutputTrack = track; }
-                    
+
+                    AudioStreamOut* getOutput() { return mOutput; }
+
+        virtual     int         type() const { return mType; }
+                    void        suspend() { mSuspended++; }
+                    void        restore() { if (mSuspended) mSuspended--; }
+        virtual     String8     getParameters(const String8& keys);
+        virtual     void        audioConfigChanged(int event, int param = 0);
+
         struct  stream_type_t {
             stream_type_t()
                 :   volume(1.0f),
@@ -492,56 +520,122 @@
             bool        mute;
         };
 
+    protected:
+        int                             mType;
+        int16_t*                        mMixBuffer;
+        int                             mSuspended;
+        int                             mBytesWritten;
+        bool                            mMasterMute;
+        SortedVector< wp<Track> >       mActiveTracks;
+
+        virtual int             getTrackName_l() = 0;
+        virtual void            deleteTrackName_l(int name) = 0;
+        virtual uint32_t        getMaxBufferRecoveryInUsecs() = 0;
+
     private:
 
-
         friend class AudioFlinger;
+        friend class OutputTrack;
         friend class Track;
         friend class TrackBase;
-        friend class RecordTrack;
-        
-        MixerThread(const Client&);
-        MixerThread& operator = (const MixerThread&);
-  
+        friend class MixerThread;
+        friend class DirectOutputThread;
+        friend class DuplicatingThread;
+
+        PlaybackThread(const Client&);
+        PlaybackThread& operator = (const PlaybackThread&);
+
         status_t    addTrack_l(const sp<Track>& track);
         void        destroyTrack_l(const sp<Track>& track);
-        int         getTrackName_l();
-        void        deleteTrackName_l(int name);
-        void        addActiveTrack_l(const wp<Track>& t);
-        void        removeActiveTrack_l(const wp<Track>& t);
-        size_t      getOutputFrameCount();
 
-        status_t    dumpInternals(int fd, const Vector<String16>& args);
+        void        readOutputParameters();
+
+        virtual status_t    dumpInternals(int fd, const Vector<String16>& args);
         status_t    dumpTracks(int fd, const Vector<String16>& args);
-        
-        sp<AudioFlinger>                mAudioFlinger;       
-        SortedVector< wp<Track> >       mActiveTracks;
+
         SortedVector< sp<Track> >       mTracks;
-        stream_type_t                   mStreamTypes[AudioSystem::NUM_STREAM_TYPES];
-        AudioMixer*                     mAudioMixer;
+        // mStreamTypes[] uses 1 additionnal stream type internally for the OutputTrack used by DuplicatingThread
+        stream_type_t                   mStreamTypes[AudioSystem::NUM_STREAM_TYPES + 1];
         AudioStreamOut*                 mOutput;
-        int                             mOutputType;
-        uint32_t                        mSampleRate;
-        size_t                          mFrameCount;
-        int                             mChannelCount;
-        int                             mFormat;
-        int16_t*                        mMixBuffer;
         float                           mMasterVolume;
-        bool                            mMasterMute;
         nsecs_t                         mLastWriteTime;
         int                             mNumWrites;
         int                             mNumDelayedWrites;
-        bool                            mStandby;
         bool                            mInWrite;
-        sp <OutputTrack>                mOutputTrack;
+        int                             mMinBytesToWrite;
     };
 
-    
+    class MixerThread : public PlaybackThread {
+    public:
+        MixerThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output);
+        virtual             ~MixerThread();
+
+        // Thread virtuals
+        virtual     bool        threadLoop();
+
+                    void        getTracks(SortedVector < sp<Track> >& tracks,
+                                      SortedVector < wp<Track> >& activeTracks,
+                                      int streamType);
+                    void        putTracks(SortedVector < sp<Track> >& tracks,
+                                      SortedVector < wp<Track> >& activeTracks);
+        virtual     bool        checkForNewParameters_l();
+        virtual     status_t    dumpInternals(int fd, const Vector<String16>& args);
+
+    protected:
+        size_t prepareTracks_l(const SortedVector< wp<Track> >& activeTracks, Vector< sp<Track> > *tracksToRemove);
+        virtual     int         getTrackName_l();
+        virtual     void        deleteTrackName_l(int name);
+        virtual     uint32_t    getMaxBufferRecoveryInUsecs();
+
+        AudioMixer*                     mAudioMixer;
+    };
+
+    class DirectOutputThread : public PlaybackThread {
+    public:
+
+        DirectOutputThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output);
+        ~DirectOutputThread();
+
+        // Thread virtuals
+        virtual     bool        threadLoop();
+
+        virtual     bool        checkForNewParameters_l();
+
+    protected:
+        virtual     int         getTrackName_l();
+        virtual     void        deleteTrackName_l(int name);
+        virtual     uint32_t    getMaxBufferRecoveryInUsecs();
+
+    private:
+        float mLeftVolume;
+        float mRightVolume;
+    };
+
+    class DuplicatingThread : public MixerThread {
+    public:
+        DuplicatingThread (const sp<AudioFlinger>& audioFlinger, MixerThread* mainThread);
+        ~DuplicatingThread();
+
+        // Thread virtuals
+        virtual     bool        threadLoop();
+                    void        addOutputTrack(MixerThread* thread);
+                    void        removeOutputTrack(MixerThread* thread);
+
+    private:
+        SortedVector < sp<OutputTrack> >  mOutputTracks;
+    };
+
+              PlaybackThread *checkPlaybackThread_l(int output) const;
+              MixerThread *checkMixerThread_l(int output) const;
+              RecordThread *checkRecordThread_l(int input) const;
+              float streamVolumeInternal(int stream) const { return mStreamTypes[stream].volume; }
+              void audioConfigChanged_l(int event, const sp<ThreadBase>& thread, void *param2);
+
     friend class AudioBuffer;
 
     class TrackHandle : public android::BnAudioTrack {
     public:
-                            TrackHandle(const sp<MixerThread::Track>& track);
+                            TrackHandle(const sp<PlaybackThread::Track>& track);
         virtual             ~TrackHandle();
         virtual status_t    start();
         virtual void        stop();
@@ -553,20 +647,92 @@
         virtual status_t onTransact(
             uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);
     private:
-        sp<MixerThread::Track> mTrack;
+        sp<PlaybackThread::Track> mTrack;
     };
 
     friend class Client;
-    friend class MixerThread::Track;
+    friend class PlaybackThread::Track;
 
 
-                void        removeClient(pid_t pid);
+                void        removeClient_l(pid_t pid);
 
 
+    // record thread
+    class RecordThread : public ThreadBase, public AudioBufferProvider
+    {
+    public:
+
+        // record track
+        class RecordTrack : public TrackBase {
+        public:
+                                RecordTrack(const wp<ThreadBase>& thread,
+                                        const sp<Client>& client,
+                                        uint32_t sampleRate,
+                                        int format,
+                                        int channelCount,
+                                        int frameCount,
+                                        uint32_t flags);
+                                ~RecordTrack();
+
+            virtual status_t    start();
+            virtual void        stop();
+
+                    bool        overflow() { bool tmp = mOverflow; mOverflow = false; return tmp; }
+                    bool        setOverflow() { bool tmp = mOverflow; mOverflow = true; return tmp; }
+
+                    void        dump(char* buffer, size_t size);
+        private:
+            friend class AudioFlinger;
+            friend class RecordThread;
+
+                                RecordTrack(const RecordTrack&);
+                                RecordTrack& operator = (const RecordTrack&);
+
+            virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer);
+
+            bool                mOverflow;
+        };
+
+
+                RecordThread(const sp<AudioFlinger>& audioFlinger,
+                        AudioStreamIn *input,
+                        uint32_t sampleRate,
+                        uint32_t channels);
+                ~RecordThread();
+
+        virtual bool        threadLoop();
+        virtual status_t    readyToRun() { return NO_ERROR; }
+        virtual void        onFirstRef();
+
+                status_t    start(RecordTrack* recordTrack);
+                void        stop(RecordTrack* recordTrack);
+                status_t    dump(int fd, const Vector<String16>& args);
+                AudioStreamIn* getInput() { return mInput; }
+
+        virtual status_t    getNextBuffer(AudioBufferProvider::Buffer* buffer);
+        virtual void        releaseBuffer(AudioBufferProvider::Buffer* buffer);
+        virtual bool        checkForNewParameters_l();
+        virtual String8     getParameters(const String8& keys);
+        virtual void        audioConfigChanged(int event, int param = 0);
+                void        readInputParameters();
+
+    private:
+                RecordThread();
+                AudioStreamIn                       *mInput;
+                sp<RecordTrack>                     mActiveTrack;
+                Condition                           mStartStopCond;
+                AudioResampler                      *mResampler;
+                int32_t                             *mRsmpOutBuffer;
+                int16_t                             *mRsmpInBuffer;
+                size_t                              mRsmpInIndex;
+                size_t                              mInputBytes;
+                int                                 mReqChannelCount;
+                uint32_t                            mReqSampleRate;
+    };
 
     class RecordHandle : public android::BnAudioRecord {
     public:
-        RecordHandle(const sp<MixerThread::RecordTrack>& recordTrack);
+        RecordHandle(const sp<RecordThread::RecordTrack>& recordTrack);
         virtual             ~RecordHandle();
         virtual status_t    start();
         virtual void        stop();
@@ -574,66 +740,31 @@
         virtual status_t onTransact(
             uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);
     private:
-        sp<MixerThread::RecordTrack> mRecordTrack;
+        sp<RecordThread::RecordTrack> mRecordTrack;
     };
 
-    // record thread
-    class AudioRecordThread : public Thread
-    {
-    public:
-        AudioRecordThread(AudioHardwareInterface* audioHardware, const sp<AudioFlinger>& audioFlinger);
-        virtual             ~AudioRecordThread();
-        virtual bool        threadLoop();
-        virtual status_t    readyToRun() { return NO_ERROR; }
-        virtual void        onFirstRef() {}
+    friend class RecordThread;
+    friend class PlaybackThread;
 
-                status_t    start(MixerThread::RecordTrack* recordTrack);
-                void        stop(MixerThread::RecordTrack* recordTrack);
-                void        exit();
-                status_t    dump(int fd, const Vector<String16>& args);
 
-    private:
-                AudioRecordThread();
-                AudioHardwareInterface              *mAudioHardware;
-                sp<AudioFlinger>                    mAudioFlinger;
-                sp<MixerThread::RecordTrack>        mRecordTrack;
-                Mutex                               mLock;
-                Condition                           mWaitWorkCV;
-                Condition                           mStopped;
-                volatile bool                       mActive;
-                status_t                            mStartStatus;
-    };
-
-    friend class AudioRecordThread;
-    friend class MixerThread;
-
-                status_t    startRecord(MixerThread::RecordTrack* recordTrack);
-                void        stopRecord(MixerThread::RecordTrack* recordTrack);
-
-    mutable     Mutex                               mHardwareLock;
     mutable     Mutex                               mLock;
-    mutable     Condition                           mWaitWorkCV;
 
                 DefaultKeyedVector< pid_t, wp<Client> >     mClients;
 
-                sp<MixerThread>                     mA2dpMixerThread;
-                sp<MixerThread>                     mHardwareMixerThread;
+                mutable     Mutex                   mHardwareLock;
                 AudioHardwareInterface*             mAudioHardware;
-                AudioHardwareInterface*             mA2dpAudioInterface;
-                sp<AudioRecordThread>               mAudioRecordThread;
-                bool                                mA2dpEnabled;
-                bool                                mNotifyA2dpChange;
     mutable     int                                 mHardwareStatus;
-                SortedVector< wp<IBinder> >         mNotificationClients;
-                int                                 mForcedSpeakerCount;
-                int                                 mA2dpDisableCount;
 
-                // true if A2DP should resume when mA2dpDisableCount returns to zero
-                bool                                mA2dpSuppressed;
-                uint32_t                            mSavedRoute;
-                uint32_t                            mForcedRoute;
-                nsecs_t                             mRouteRestoreTime;
-                bool                                mMusicMuteSaved;
+
+                DefaultKeyedVector< int, sp<PlaybackThread> >  mPlaybackThreads;
+                PlaybackThread::stream_type_t       mStreamTypes[AudioSystem::NUM_STREAM_TYPES];
+                float                               mMasterVolume;
+                bool                                mMasterMute;
+
+                DefaultKeyedVector< int, sp<RecordThread> >    mRecordThreads;
+
+                SortedVector< sp<IBinder> >         mNotificationClients;
+                int                                 mNextThreadId;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/libs/audioflinger/AudioHardwareGeneric.cpp b/libs/audioflinger/AudioHardwareGeneric.cpp
index 1e159b8..57874f3 100644
--- a/libs/audioflinger/AudioHardwareGeneric.cpp
+++ b/libs/audioflinger/AudioHardwareGeneric.cpp
@@ -49,8 +49,8 @@
 AudioHardwareGeneric::~AudioHardwareGeneric()
 {
     if (mFd >= 0) ::close(mFd);
-    delete mOutput;
-    delete mInput;
+    closeOutputStream((AudioStreamOut *)mOutput);
+    closeInputStream((AudioStreamIn *)mInput);
 }
 
 status_t AudioHardwareGeneric::initCheck()
@@ -63,7 +63,7 @@
 }
 
 AudioStreamOut* AudioHardwareGeneric::openOutputStream(
-        int format, int channelCount, uint32_t sampleRate, status_t *status)
+        uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status)
 {
     AutoMutex lock(mLock);
 
@@ -77,7 +77,7 @@
 
     // create new output stream
     AudioStreamOutGeneric* out = new AudioStreamOutGeneric();
-    status_t lStatus = out->set(this, mFd, format, channelCount, sampleRate);
+    status_t lStatus = out->set(this, mFd, devices, format, channels, sampleRate);
     if (status) {
         *status = lStatus;
     }
@@ -89,17 +89,19 @@
     return mOutput;
 }
 
-void AudioHardwareGeneric::closeOutputStream(AudioStreamOutGeneric* out) {
-    if (out == mOutput) mOutput = 0;
+void AudioHardwareGeneric::closeOutputStream(AudioStreamOut* out) {
+    if (mOutput && out == mOutput) {
+        delete mOutput;
+        mOutput = 0;
+    }
 }
 
 AudioStreamIn* AudioHardwareGeneric::openInputStream(
-        int inputSource, int format, int channelCount, uint32_t sampleRate,
+        uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate,
         status_t *status, AudioSystem::audio_in_acoustics acoustics)
 {
     // check for valid input source
-    if ((inputSource < AudioRecord::DEFAULT_INPUT) ||
-        (inputSource >= AudioRecord::NUM_INPUT_SOURCES)) {
+    if (!AudioSystem::isInputDevice((AudioSystem::audio_devices)devices)) {
         return 0;
     }
 
@@ -115,7 +117,7 @@
 
     // create new output stream
     AudioStreamInGeneric* in = new AudioStreamInGeneric();
-    status_t lStatus = in->set(this, mFd, format, channelCount, sampleRate, acoustics);
+    status_t lStatus = in->set(this, mFd, devices, format, channels, sampleRate, acoustics);
     if (status) {
         *status = lStatus;
     }
@@ -127,8 +129,11 @@
     return mInput;
 }
 
-void AudioHardwareGeneric::closeInputStream(AudioStreamInGeneric* in) {
-    if (in == mInput) mInput = 0;
+void AudioHardwareGeneric::closeInputStream(AudioStreamIn* in) {
+    if (mInput && in == mInput) {
+        delete mInput;
+        mInput = 0;
+    }
 }
 
 status_t AudioHardwareGeneric::setVoiceVolume(float v)
@@ -185,30 +190,42 @@
 status_t AudioStreamOutGeneric::set(
         AudioHardwareGeneric *hw,
         int fd,
-        int format,
-        int channels,
-        uint32_t rate)
+        uint32_t devices,
+        int *pFormat,
+        uint32_t *pChannels,
+        uint32_t *pRate)
 {
+    int lFormat = pFormat ? *pFormat : 0;
+    uint32_t lChannels = pChannels ? *pChannels : 0;
+    uint32_t lRate = pRate ? *pRate : 0;
+
     // fix up defaults
-    if (format == 0) format = AudioSystem::PCM_16_BIT;
-    if (channels == 0) channels = channelCount();
-    if (rate == 0) rate = sampleRate();
+    if (lFormat == 0) lFormat = format();
+    if (lChannels == 0) lChannels = channels();
+    if (lRate == 0) lRate = sampleRate();
 
     // check values
-    if ((format != AudioSystem::PCM_16_BIT) ||
-            (channels != channelCount()) ||
-            (rate != sampleRate()))
+    if ((lFormat != format()) ||
+            (lChannels != channels()) ||
+            (lRate != sampleRate())) {
+        if (pFormat) *pFormat = format();
+        if (pChannels) *pChannels = channels();
+        if (pRate) *pRate = sampleRate();
         return BAD_VALUE;
+    }
+
+    if (pFormat) *pFormat = lFormat;
+    if (pChannels) *pChannels = lChannels;
+    if (pRate) *pRate = lRate;
 
     mAudioHardware = hw;
     mFd = fd;
+    mDevice = devices;
     return NO_ERROR;
 }
 
 AudioStreamOutGeneric::~AudioStreamOutGeneric()
 {
-    if (mAudioHardware)
-        mAudioHardware->closeOutputStream(this);
 }
 
 ssize_t AudioStreamOutGeneric::write(const void* buffer, size_t bytes)
@@ -234,10 +251,12 @@
     result.append(buffer);
     snprintf(buffer, SIZE, "\tbuffer size: %d\n", bufferSize());
     result.append(buffer);
-    snprintf(buffer, SIZE, "\tchannel count: %d\n", channelCount());
+    snprintf(buffer, SIZE, "\tchannels: %d\n", channels());
     result.append(buffer);
     snprintf(buffer, SIZE, "\tformat: %d\n", format());
     result.append(buffer);
+    snprintf(buffer, SIZE, "\tdevice: %d\n", mDevice);
+    result.append(buffer);
     snprintf(buffer, SIZE, "\tmAudioHardware: %p\n", mAudioHardware);
     result.append(buffer);
     snprintf(buffer, SIZE, "\tmFd: %d\n", mFd);
@@ -246,29 +265,68 @@
     return NO_ERROR;
 }
 
+status_t AudioStreamOutGeneric::setParameters(const String8& keyValuePairs)
+{
+    AudioParameter param = AudioParameter(keyValuePairs);
+    String8 key = String8(AudioParameter::keyRouting);
+    status_t status = NO_ERROR;
+    int device;
+    LOGV("setParameters() %s", keyValuePairs.string());
+
+    if (param.getInt(key, device) == NO_ERROR) {
+        mDevice = device;
+        param.remove(key);
+    }
+
+    if (param.size()) {
+        status = BAD_VALUE;
+    }
+    return status;
+}
+
+String8 AudioStreamOutGeneric::getParameters(const String8& keys)
+{
+    AudioParameter param = AudioParameter(keys);
+    String8 value;
+    String8 key = String8(AudioParameter::keyRouting);
+
+    if (param.get(key, value) == NO_ERROR) {
+        param.addInt(key, (int)mDevice);
+    }
+
+    LOGV("getParameters() %s", param.toString().string());
+    return param.toString();
+}
+
 // ----------------------------------------------------------------------------
 
 // record functions
 status_t AudioStreamInGeneric::set(
         AudioHardwareGeneric *hw,
         int fd,
-        int format,
-        int channels,
-        uint32_t rate,
+        uint32_t devices,
+        int *pFormat,
+        uint32_t *pChannels,
+        uint32_t *pRate,
         AudioSystem::audio_in_acoustics acoustics)
 {
     // FIXME: remove logging
-    LOGD("AudioStreamInGeneric::set(%p, %d, %d, %d, %u)", hw, fd, format, channels, rate);
+    if (pFormat == 0 || pChannels == 0 || pRate == 0) return BAD_VALUE;
+    LOGD("AudioStreamInGeneric::set(%p, %d, %d, %d, %u)", hw, fd, *pFormat, *pChannels, *pRate);
     // check values
-    if ((format != AudioSystem::PCM_16_BIT) ||
-            (channels != channelCount()) ||
-            (rate != sampleRate())) {
+    if ((*pFormat != format()) ||
+        (*pChannels != channels()) ||
+        (*pRate != sampleRate())) {
         LOGE("Error opening input channel");
+        *pFormat = format();
+        *pChannels = channels();
+        *pRate = sampleRate();
         return BAD_VALUE;
     }
 
     mAudioHardware = hw;
     mFd = fd;
+    mDevice = devices;
     return NO_ERROR;
 }
 
@@ -276,14 +334,12 @@
 {
     // FIXME: remove logging
     LOGD("AudioStreamInGeneric destructor");
-    if (mAudioHardware)
-        mAudioHardware->closeInputStream(this);
 }
 
 ssize_t AudioStreamInGeneric::read(void* buffer, ssize_t bytes)
 {
     // FIXME: remove logging
-    LOGD("AudioStreamInGeneric::read(%p, %d) from fd %d", buffer, bytes, mFd);
+    LOGD("AudioStreamInGeneric::read(%p, %d) from fd %d", buffer, (int)bytes, mFd);
     AutoMutex lock(mLock);
     if (mFd < 0) {
         LOGE("Attempt to read from unopened device");
@@ -303,10 +359,12 @@
     result.append(buffer);
     snprintf(buffer, SIZE, "\tbuffer size: %d\n", bufferSize());
     result.append(buffer);
-    snprintf(buffer, SIZE, "\tchannel count: %d\n", channelCount());
+    snprintf(buffer, SIZE, "\tchannels: %d\n", channels());
     result.append(buffer);
     snprintf(buffer, SIZE, "\tformat: %d\n", format());
     result.append(buffer);
+    snprintf(buffer, SIZE, "\tdevice: %d\n", mDevice);
+    result.append(buffer);
     snprintf(buffer, SIZE, "\tmAudioHardware: %p\n", mAudioHardware);
     result.append(buffer);
     snprintf(buffer, SIZE, "\tmFd: %d\n", mFd);
@@ -315,6 +373,39 @@
     return NO_ERROR;
 }
 
+status_t AudioStreamInGeneric::setParameters(const String8& keyValuePairs)
+{
+    AudioParameter param = AudioParameter(keyValuePairs);
+    String8 key = String8(AudioParameter::keyRouting);
+    status_t status = NO_ERROR;
+    int device;
+    LOGV("setParameters() %s", keyValuePairs.string());
+
+    if (param.getInt(key, device) == NO_ERROR) {
+        mDevice = device;
+        param.remove(key);
+    }
+
+    if (param.size()) {
+        status = BAD_VALUE;
+    }
+    return status;
+}
+
+String8 AudioStreamInGeneric::getParameters(const String8& keys)
+{
+    AudioParameter param = AudioParameter(keys);
+    String8 value;
+    String8 key = String8(AudioParameter::keyRouting);
+
+    if (param.get(key, value) == NO_ERROR) {
+        param.addInt(key, (int)mDevice);
+    }
+
+    LOGV("getParameters() %s", param.toString().string());
+    return param.toString();
+}
+
 // ----------------------------------------------------------------------------
 
 }; // namespace android
diff --git a/libs/audioflinger/AudioHardwareGeneric.h b/libs/audioflinger/AudioHardwareGeneric.h
index c89df87..42da413 100644
--- a/libs/audioflinger/AudioHardwareGeneric.h
+++ b/libs/audioflinger/AudioHardwareGeneric.h
@@ -39,24 +39,28 @@
     virtual status_t    set(
             AudioHardwareGeneric *hw,
             int mFd,
-            int format,
-            int channelCount,
-            uint32_t sampleRate);
+            uint32_t devices,
+            int *pFormat,
+            uint32_t *pChannels,
+            uint32_t *pRate);
 
     virtual uint32_t    sampleRate() const { return 44100; }
     virtual size_t      bufferSize() const { return 4096; }
-    virtual int         channelCount() const { return 2; }
+    virtual uint32_t    channels() const { return AudioSystem::CHANNEL_OUT_STEREO; }
     virtual int         format() const { return AudioSystem::PCM_16_BIT; }
     virtual uint32_t    latency() const { return 20; }
-    virtual status_t    setVolume(float volume) { return INVALID_OPERATION; }
+    virtual status_t    setVolume(float left, float right) { return INVALID_OPERATION; }
     virtual ssize_t     write(const void* buffer, size_t bytes);
     virtual status_t    standby();
     virtual status_t    dump(int fd, const Vector<String16>& args);
+    virtual status_t    setParameters(const String8& keyValuePairs);
+    virtual String8     getParameters(const String8& keys);
 
 private:
     AudioHardwareGeneric *mAudioHardware;
     Mutex   mLock;
     int     mFd;
+    uint32_t mDevice;
 };
 
 class AudioStreamInGeneric : public AudioStreamIn {
@@ -67,24 +71,28 @@
     virtual status_t    set(
             AudioHardwareGeneric *hw,
             int mFd,
-            int format,
-            int channelCount,
-            uint32_t sampleRate,
+            uint32_t devices,
+            int *pFormat,
+            uint32_t *pChannels,
+            uint32_t *pRate,
             AudioSystem::audio_in_acoustics acoustics);
 
-    uint32_t    sampleRate() const { return 8000; }
+    virtual uint32_t    sampleRate() const { return 8000; }
     virtual size_t      bufferSize() const { return 320; }
-    virtual int         channelCount() const { return 1; }
+    virtual uint32_t    channels() const { return AudioSystem::CHANNEL_IN_MONO; }
     virtual int         format() const { return AudioSystem::PCM_16_BIT; }
     virtual status_t    setGain(float gain) { return INVALID_OPERATION; }
     virtual ssize_t     read(void* buffer, ssize_t bytes);
     virtual status_t    dump(int fd, const Vector<String16>& args);
     virtual status_t    standby() { return NO_ERROR; }
+    virtual status_t    setParameters(const String8& keyValuePairs);
+    virtual String8     getParameters(const String8& keys);
 
 private:
     AudioHardwareGeneric *mAudioHardware;
     Mutex   mLock;
     int     mFd;
+    uint32_t mDevice;
 };
 
 
@@ -101,28 +109,27 @@
     virtual status_t    setMicMute(bool state);
     virtual status_t    getMicMute(bool* state);
 
-    virtual status_t    setParameter(const char* key, const char* value)
-            { return NO_ERROR; }
-
     // create I/O streams
     virtual AudioStreamOut* openOutputStream(
-            int format=0,
-            int channelCount=0,
-            uint32_t sampleRate=0,
+            uint32_t devices,
+            int *format=0,
+            uint32_t *channels=0,
+            uint32_t *sampleRate=0,
             status_t *status=0);
+    virtual    void        closeOutputStream(AudioStreamOut* out);
 
     virtual AudioStreamIn* openInputStream(
-            int inputSource,
-            int format,
-            int channelCount,
-            uint32_t sampleRate,
+            uint32_t devices,
+            int *format,
+            uint32_t *channels,
+            uint32_t *sampleRate,
             status_t *status,
             AudioSystem::audio_in_acoustics acoustics);
+    virtual    void        closeInputStream(AudioStreamIn* in);
 
             void            closeOutputStream(AudioStreamOutGeneric* out);
             void            closeInputStream(AudioStreamInGeneric* in);
 protected:
-    virtual status_t        doRouting() { return NO_ERROR; }
     virtual status_t        dump(int fd, const Vector<String16>& args);
 
 private:
diff --git a/libs/audioflinger/AudioHardwareInterface.cpp b/libs/audioflinger/AudioHardwareInterface.cpp
index cc1bd8f..9a4a7f9 100644
--- a/libs/audioflinger/AudioHardwareInterface.cpp
+++ b/libs/audioflinger/AudioHardwareInterface.cpp
@@ -18,6 +18,7 @@
 #include <cutils/properties.h>
 #include <string.h>
 #include <unistd.h>
+//#define LOG_NDEBUG 0
 
 #define LOG_TAG "AudioHardwareInterface"
 #include <utils/Log.h>
@@ -25,15 +26,17 @@
 
 #include "AudioHardwareStub.h"
 #include "AudioHardwareGeneric.h"
+#ifdef WITH_A2DP
+#include "A2dpAudioInterface.h"
+#endif
 
-//#define DUMP_FLINGER_OUT        // if defined allows recording samples in a file
-#ifdef DUMP_FLINGER_OUT
+#ifdef ENABLE_AUDIO_DUMP
 #include "AudioDumpInterface.h"
 #endif
 
 
 // change to 1 to log routing calls
-#define LOG_ROUTING_CALLS 0
+#define LOG_ROUTING_CALLS 1
 
 namespace android {
 
@@ -48,14 +51,6 @@
     "IN_CALL"
 };
 
-static const char* routeStrings[] =
-{
-    "EARPIECE ",
-    "SPEAKER ",
-    "BLUETOOTH ",
-    "HEADSET ",
-    "BLUETOOTH_A2DP "
-};
 static const char* routeNone = "NONE";
 
 static const char* displayMode(int mode)
@@ -64,22 +59,6 @@
         return routingModeStrings[0];
     return routingModeStrings[mode+3];
 }
-
-static const char* displayRoutes(uint32_t routes)
-{
-    static char routeStr[80];
-    if (routes == 0)
-        return routeNone;
-    routeStr[0] = 0;
-    int bitMask = 1;
-    for (int i = 0; i < 4; ++i, bitMask <<= 1) {
-        if (routes & bitMask) {
-            strcat(routeStr, routeStrings[i]);
-        }
-    }
-    routeStr[strlen(routeStr)-1] = 0;
-    return routeStr;
-}
 #endif
 
 // ----------------------------------------------------------------------------
@@ -112,13 +91,17 @@
         hw = new AudioHardwareStub();
     }
     
-#ifdef DUMP_FLINGER_OUT
+#ifdef WITH_A2DP
+    hw = new A2dpAudioInterface(hw);
+#endif
+
+#ifdef ENABLE_AUDIO_DUMP
     // This code adds a record of buffers in a file to write calls made by AudioFlinger.
     // It replaces the current AudioHardwareInterface object by an intermediate one which
     // will record buffers in a file (after sending them to hardware) for testing purpose.
-    // This feature is enabled by defining symbol DUMP_FLINGER_OUT.
-    // The output file is FLINGER_DUMP_NAME. Pause are not recorded in the file.
-    
+    // This feature is enabled by defining symbol ENABLE_AUDIO_DUMP.
+    // The output file is set with setParameters("test_cmd_file_name=<name>"). Pause are not recorded in the file.
+    LOGV("opening PCM dump interface");
     hw = new AudioDumpInterface(hw);    // replace interface
 #endif
     return hw;
@@ -132,48 +115,9 @@
 
 AudioHardwareBase::AudioHardwareBase()
 {
-    // force a routing update on initialization
-    memset(&mRoutes, 0, sizeof(mRoutes));
     mMode = 0;
 }
 
-// generics for audio routing - the real work is done in doRouting
-status_t AudioHardwareBase::setRouting(int mode, uint32_t routes)
-{
-#if LOG_ROUTING_CALLS
-    LOGD("setRouting: mode=%s, routes=[%s]", displayMode(mode), displayRoutes(routes));
-#endif
-    if (mode == AudioSystem::MODE_CURRENT)
-        mode = mMode;
-    if ((mode < 0) || (mode >= AudioSystem::NUM_MODES))
-        return BAD_VALUE;
-    uint32_t old = mRoutes[mode];
-    mRoutes[mode] = routes;
-    if ((mode != mMode) || (old == routes))
-        return NO_ERROR;
-#if LOG_ROUTING_CALLS
-    const char* oldRouteStr = strdup(displayRoutes(old));
-    LOGD("doRouting: mode=%s, old route=[%s], new route=[%s]",
-           displayMode(mode), oldRouteStr, displayRoutes(routes));
-    delete oldRouteStr;
-#endif
-    return doRouting();
-}
-
-status_t AudioHardwareBase::getRouting(int mode, uint32_t* routes)
-{
-    if (mode == AudioSystem::MODE_CURRENT)
-        mode = mMode;
-    if ((mode < 0) || (mode >= AudioSystem::NUM_MODES))
-        return BAD_VALUE;
-    *routes = mRoutes[mode];
-#if LOG_ROUTING_CALLS
-    LOGD("getRouting: mode=%s, routes=[%s]",
-           displayMode(mode), displayRoutes(*routes));
-#endif
-    return NO_ERROR;
-}
-
 status_t AudioHardwareBase::setMode(int mode)
 {
 #if LOG_ROUTING_CALLS
@@ -182,28 +126,23 @@
     if ((mode < 0) || (mode >= AudioSystem::NUM_MODES))
         return BAD_VALUE;
     if (mMode == mode)
-        return NO_ERROR;
-#if LOG_ROUTING_CALLS
-    LOGD("doRouting: old mode=%s, new mode=%s route=[%s]",
-            displayMode(mMode), displayMode(mode), displayRoutes(mRoutes[mode]));
-#endif
+        return ALREADY_EXISTS;
     mMode = mode;
-    return doRouting();
-}
-
-status_t AudioHardwareBase::getMode(int* mode)
-{
-    // Implement: set audio routing
-    *mode = mMode;
     return NO_ERROR;
 }
 
-status_t AudioHardwareBase::setParameter(const char* key, const char* value)
+// default implementation
+status_t AudioHardwareBase::setParameters(const String8& keyValuePairs)
 {
-    // default implementation is to ignore
     return NO_ERROR;
 }
 
+// default implementation
+String8 AudioHardwareBase::getParameters(const String8& keys)
+{
+    AudioParameter param = AudioParameter(keys);
+    return param.toString();
+}
 
 // default implementation
 size_t AudioHardwareBase::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
@@ -233,10 +172,6 @@
     result.append(buffer);
     snprintf(buffer, SIZE, "\tmMode: %d\n", mMode);
     result.append(buffer);
-    for (int i = 0, n = AudioSystem::NUM_MODES; i < n; ++i) {
-        snprintf(buffer, SIZE, "\tmRoutes[%d]: %d\n", i, mRoutes[i]);
-        result.append(buffer);
-    }
     ::write(fd, result.string(), result.size());
     dump(fd, args);  // Dump the state of the concrete child.
     return NO_ERROR;
diff --git a/libs/audioflinger/AudioHardwareStub.cpp b/libs/audioflinger/AudioHardwareStub.cpp
index 0ab4c60..ae391ee 100644
--- a/libs/audioflinger/AudioHardwareStub.cpp
+++ b/libs/audioflinger/AudioHardwareStub.cpp
@@ -43,10 +43,10 @@
 }
 
 AudioStreamOut* AudioHardwareStub::openOutputStream(
-        int format, int channelCount, uint32_t sampleRate, status_t *status)
+        uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status)
 {
     AudioStreamOutStub* out = new AudioStreamOutStub();
-    status_t lStatus = out->set(format, channelCount, sampleRate);
+    status_t lStatus = out->set(format, channels, sampleRate);
     if (status) {
         *status = lStatus;
     }
@@ -56,18 +56,22 @@
     return 0;
 }
 
+void AudioHardwareStub::closeOutputStream(AudioStreamOut* out)
+{
+    delete out;
+}
+
 AudioStreamIn* AudioHardwareStub::openInputStream(
-        int inputSource, int format, int channelCount, uint32_t sampleRate,
+        uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate,
         status_t *status, AudioSystem::audio_in_acoustics acoustics)
 {
     // check for valid input source
-    if ((inputSource < AudioRecord::DEFAULT_INPUT) ||
-        (inputSource >= AudioRecord::NUM_INPUT_SOURCES)) {
+    if (!AudioSystem::isInputDevice((AudioSystem::audio_devices)devices)) {
         return 0;
     }
 
     AudioStreamInStub* in = new AudioStreamInStub();
-    status_t lStatus = in->set(format, channelCount, sampleRate, acoustics);
+    status_t lStatus = in->set(format, channels, sampleRate, acoustics);
     if (status) {
         *status = lStatus;
     }
@@ -77,6 +81,11 @@
     return 0;
 }
 
+void AudioHardwareStub::closeInputStream(AudioStreamIn* in)
+{
+    delete in;
+}
+
 status_t AudioHardwareStub::setVoiceVolume(float volume)
 {
     return NO_ERROR;
@@ -107,24 +116,19 @@
 
 // ----------------------------------------------------------------------------
 
-status_t AudioStreamOutStub::set(int format, int channels, uint32_t rate)
+status_t AudioStreamOutStub::set(int *pFormat, uint32_t *pChannels, uint32_t *pRate)
 {
-    // fix up defaults
-    if (format == 0) format = AudioSystem::PCM_16_BIT;
-    if (channels == 0) channels = channelCount();
-    if (rate == 0) rate = sampleRate();
+    if (pFormat) *pFormat = format();
+    if (pChannels) *pChannels = channels();
+    if (pRate) *pRate = sampleRate();
 
-    if ((format == AudioSystem::PCM_16_BIT) &&
-            (channels == channelCount()) &&
-            (rate == sampleRate()))
-        return NO_ERROR;
-    return BAD_VALUE;
+    return NO_ERROR;
 }
 
 ssize_t AudioStreamOutStub::write(const void* buffer, size_t bytes)
 {
     // fake timing for audio output
-    usleep(bytes * 1000000 / sizeof(int16_t) / channelCount() / sampleRate());
+    usleep(bytes * 1000000 / sizeof(int16_t) / AudioSystem::popCount(channels()) / sampleRate());
     return bytes;
 }
 
@@ -141,29 +145,31 @@
     snprintf(buffer, SIZE, "AudioStreamOutStub::dump\n");
     snprintf(buffer, SIZE, "\tsample rate: %d\n", sampleRate());
     snprintf(buffer, SIZE, "\tbuffer size: %d\n", bufferSize());
-    snprintf(buffer, SIZE, "\tchannel count: %d\n", channelCount());
+    snprintf(buffer, SIZE, "\tchannels: %d\n", channels());
     snprintf(buffer, SIZE, "\tformat: %d\n", format());
     result.append(buffer);
     ::write(fd, result.string(), result.size());
     return NO_ERROR;
 }
 
+String8 AudioStreamOutStub::getParameters(const String8& keys)
+{
+    AudioParameter param = AudioParameter(keys);
+    return param.toString();
+}
+
 // ----------------------------------------------------------------------------
 
-status_t AudioStreamInStub::set(int format, int channels, uint32_t rate,
+status_t AudioStreamInStub::set(int *pFormat, uint32_t *pChannels, uint32_t *pRate,
 				AudioSystem::audio_in_acoustics acoustics)
 {
-    if ((format == AudioSystem::PCM_16_BIT) &&
-            (channels == channelCount()) &&
-            (rate == sampleRate()))
-        return NO_ERROR;
-    return BAD_VALUE;
+    return NO_ERROR;
 }
 
 ssize_t AudioStreamInStub::read(void* buffer, ssize_t bytes)
 {
     // fake timing for audio input
-    usleep(bytes * 1000000 / sizeof(int16_t) / channelCount() / sampleRate());
+    usleep(bytes * 1000000 / sizeof(int16_t) / AudioSystem::popCount(channels()) / sampleRate());
     memset(buffer, 0, bytes);
     return bytes;
 }
@@ -179,7 +185,7 @@
     result.append(buffer);
     snprintf(buffer, SIZE, "\tbuffer size: %d\n", bufferSize());
     result.append(buffer);
-    snprintf(buffer, SIZE, "\tchannel count: %d\n", channelCount());
+    snprintf(buffer, SIZE, "\tchannels: %d\n", channels());
     result.append(buffer);
     snprintf(buffer, SIZE, "\tformat: %d\n", format());
     result.append(buffer);
@@ -187,6 +193,12 @@
     return NO_ERROR;
 }
 
+String8 AudioStreamInStub::getParameters(const String8& keys)
+{
+    AudioParameter param = AudioParameter(keys);
+    return param.toString();
+}
+
 // ----------------------------------------------------------------------------
 
 }; // namespace android
diff --git a/libs/audioflinger/AudioHardwareStub.h b/libs/audioflinger/AudioHardwareStub.h
index bf63cc5..583f852 100644
--- a/libs/audioflinger/AudioHardwareStub.h
+++ b/libs/audioflinger/AudioHardwareStub.h
@@ -29,29 +29,33 @@
 
 class AudioStreamOutStub : public AudioStreamOut {
 public:
-    virtual status_t    set(int format, int channelCount, uint32_t sampleRate);
+    virtual status_t    set(int *pFormat, uint32_t *pChannels, uint32_t *pRate);
     virtual uint32_t    sampleRate() const { return 44100; }
     virtual size_t      bufferSize() const { return 4096; }
-    virtual int         channelCount() const { return 2; }
+    virtual uint32_t    channels() const { return AudioSystem::CHANNEL_OUT_STEREO; }
     virtual int         format() const { return AudioSystem::PCM_16_BIT; }
     virtual uint32_t    latency() const { return 0; }
-    virtual status_t    setVolume(float volume) { return NO_ERROR; }
+    virtual status_t    setVolume(float left, float right) { return NO_ERROR; }
     virtual ssize_t     write(const void* buffer, size_t bytes);
     virtual status_t    standby();
     virtual status_t    dump(int fd, const Vector<String16>& args);
+    virtual status_t    setParameters(const String8& keyValuePairs) { return NO_ERROR;}
+    virtual String8     getParameters(const String8& keys);
 };
 
 class AudioStreamInStub : public AudioStreamIn {
 public:
-    virtual status_t    set(int format, int channelCount, uint32_t sampleRate, AudioSystem::audio_in_acoustics acoustics);
+    virtual status_t    set(int *pFormat, uint32_t *pChannels, uint32_t *pRate, AudioSystem::audio_in_acoustics acoustics);
     virtual uint32_t    sampleRate() const { return 8000; }
     virtual size_t      bufferSize() const { return 320; }
-    virtual int         channelCount() const { return 1; }
+    virtual uint32_t    channels() const { return AudioSystem::CHANNEL_IN_MONO; }
     virtual int         format() const { return AudioSystem::PCM_16_BIT; }
     virtual status_t    setGain(float gain) { return NO_ERROR; }
     virtual ssize_t     read(void* buffer, ssize_t bytes);
     virtual status_t    dump(int fd, const Vector<String16>& args);
     virtual status_t    standby() { return NO_ERROR; }
+    virtual status_t    setParameters(const String8& keyValuePairs) { return NO_ERROR;}
+    virtual String8     getParameters(const String8& keys);
 };
 
 class AudioHardwareStub : public  AudioHardwareBase
@@ -67,26 +71,25 @@
     virtual status_t    setMicMute(bool state) { mMicMute = state;  return  NO_ERROR; }
     virtual status_t    getMicMute(bool* state) { *state = mMicMute ; return NO_ERROR; }
 
-    virtual status_t    setParameter(const char* key, const char* value)
-            { return NO_ERROR; }
-
     // create I/O streams
     virtual AudioStreamOut* openOutputStream(
-                                int format=0,
-                                int channelCount=0,
-                                uint32_t sampleRate=0,
+                                uint32_t devices,
+                                int *format=0,
+                                uint32_t *channels=0,
+                                uint32_t *sampleRate=0,
                                 status_t *status=0);
+    virtual    void        closeOutputStream(AudioStreamOut* out);
 
     virtual AudioStreamIn* openInputStream(
-                                int inputSource,
-                                int format,
-                                int channelCount,
-                                uint32_t sampleRate,
+                                uint32_t devices,
+                                int *format,
+                                uint32_t *channels,
+                                uint32_t *sampleRate,
                                 status_t *status,
-				AudioSystem::audio_in_acoustics acoustics);
+                                AudioSystem::audio_in_acoustics acoustics);
+    virtual    void        closeInputStream(AudioStreamIn* in);
 
 protected:
-    virtual status_t    doRouting() { return NO_ERROR; }
     virtual status_t    dump(int fd, const Vector<String16>& args);
 
             bool        mMicMute;
diff --git a/libs/audioflinger/AudioMixer.cpp b/libs/audioflinger/AudioMixer.cpp
index b02efcc..19a442a 100644
--- a/libs/audioflinger/AudioMixer.cpp
+++ b/libs/audioflinger/AudioMixer.cpp
@@ -610,7 +610,6 @@
     t->in = in;
 }
 
-inline
 void AudioMixer::ditherAndClamp(int32_t* out, int32_t const *sums, size_t c)
 {
     for (size_t i=0 ; i<c ; i++) {
diff --git a/libs/audioflinger/AudioMixer.h b/libs/audioflinger/AudioMixer.h
index 72ca28a..15766cd 100644
--- a/libs/audioflinger/AudioMixer.h
+++ b/libs/audioflinger/AudioMixer.h
@@ -85,6 +85,8 @@
 
     uint32_t    trackNames() const { return mTrackNames; }
 
+    static void ditherAndClamp(int32_t* out, int32_t const *sums, size_t c);
+
 private:
 
     enum {
@@ -176,7 +178,6 @@
     static void volumeRampStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp);
     static void track__16BitsStereo(track_t* t, int32_t* out, size_t numFrames, int32_t* temp);
     static void track__16BitsMono(track_t* t, int32_t* out, size_t numFrames, int32_t* temp);
-    static void ditherAndClamp(int32_t* out, int32_t const *sums, size_t c);
 
     static void process__validate(state_t* state, void* output);
     static void process__nop(state_t* state, void* output);
diff --git a/libs/audioflinger/AudioPolicyManagerGeneric.cpp b/libs/audioflinger/AudioPolicyManagerGeneric.cpp
new file mode 100644
index 0000000..8cfc204
--- /dev/null
+++ b/libs/audioflinger/AudioPolicyManagerGeneric.cpp
@@ -0,0 +1,945 @@
+/*
+ * Copyright (C) 2009 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 "AudioPolicyManagerGeneric"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+#include "AudioPolicyManagerGeneric.h"
+#include <media/mediarecorder.h>
+
+namespace android {
+
+
+// ----------------------------------------------------------------------------
+// AudioPolicyInterface implementation
+// ----------------------------------------------------------------------------
+
+
+status_t AudioPolicyManagerGeneric::setDeviceConnectionState(AudioSystem::audio_devices device,
+                                                  AudioSystem::device_connection_state state,
+                                                  const char *device_address)
+{
+
+    LOGV("setDeviceConnectionState() device: %x, state %d, address %s", device, state, device_address);
+
+    // connect/disconnect only 1 device at a time
+    if (AudioSystem::popCount(device) != 1) return BAD_VALUE;
+
+    if (strlen(device_address) >= MAX_DEVICE_ADDRESS_LEN) {
+        LOGE("setDeviceConnectionState() invalid address: %s", device_address);
+        return BAD_VALUE;
+    }
+
+    // handle output devices
+    if (AudioSystem::isOutputDevice(device)) {
+        switch (state)
+        {
+        // handle output device connection
+        case AudioSystem::DEVICE_STATE_AVAILABLE:
+            if (mAvailableOutputDevices & device) {
+                LOGW("setDeviceConnectionState() device already connected: %x", device);
+                return INVALID_OPERATION;
+            }
+            LOGV("setDeviceConnectionState() connecting device %x", device);
+
+            // register new device as available
+            mAvailableOutputDevices |= device;
+            break;
+        // handle output device disconnection
+        case AudioSystem::DEVICE_STATE_UNAVAILABLE:
+            if (!(mAvailableOutputDevices & device)) {
+                LOGW("setDeviceConnectionState() device not connected: %x", device);
+                return INVALID_OPERATION;
+            }
+            LOGV("setDeviceConnectionState() disconnecting device %x", device);
+            // remove device from available output devices
+            mAvailableOutputDevices &= ~device;
+            break;
+
+        default:
+            LOGE("setDeviceConnectionState() invalid state: %x", state);
+            return BAD_VALUE;
+        }
+        return NO_ERROR;
+    }
+    // handle input devices
+    if (AudioSystem::isInputDevice(device)) {
+        switch (state)
+        {
+        // handle input device connection
+        case AudioSystem::DEVICE_STATE_AVAILABLE:
+            if (mAvailableInputDevices & device) {
+                LOGW("setDeviceConnectionState() device already connected: %d", device);
+                return INVALID_OPERATION;
+            }
+            mAvailableInputDevices |= device;
+            break;
+
+        // handle input device disconnection
+        case AudioSystem::DEVICE_STATE_UNAVAILABLE:
+            if (!(mAvailableInputDevices & device)) {
+                LOGW("setDeviceConnectionState() device not connected: %d", device);
+                return INVALID_OPERATION;
+            }
+            mAvailableInputDevices &= ~device;
+            break;
+
+        default:
+            LOGE("setDeviceConnectionState() invalid state: %x", state);
+            return BAD_VALUE;
+        }
+        return NO_ERROR;
+    }
+
+    LOGW("setDeviceConnectionState() invalid device: %x", device);
+    return BAD_VALUE;
+}
+
+AudioSystem::device_connection_state AudioPolicyManagerGeneric::getDeviceConnectionState(AudioSystem::audio_devices device,
+                                                  const char *device_address)
+{
+    AudioSystem::device_connection_state state = AudioSystem::DEVICE_STATE_UNAVAILABLE;
+    String8 address = String8(device_address);
+    if (AudioSystem::isOutputDevice(device)) {
+        if (device & mAvailableOutputDevices) {
+            state = AudioSystem::DEVICE_STATE_AVAILABLE;
+        }
+    } else if (AudioSystem::isInputDevice(device)) {
+        if (device & mAvailableInputDevices) {
+            state = AudioSystem::DEVICE_STATE_AVAILABLE;
+        }
+    }
+
+    return state;
+}
+
+void AudioPolicyManagerGeneric::setPhoneState(int state)
+{
+    LOGV("setPhoneState() state %d", state);
+    uint32_t newDevice = 0;
+    if (state < 0 || state >= AudioSystem::NUM_MODES) {
+        LOGW("setPhoneState() invalid state %d", state);
+        return;
+    }
+
+    if (state == mPhoneState ) {
+        LOGW("setPhoneState() setting same state %d", state);
+        return;
+    }
+    // store previous phone state for management of sonification strategy below
+    int oldState = mPhoneState;
+    mPhoneState = state;
+
+    // if leaving or entering in call state, handle special case of active streams
+    // pertaining to sonification strategy see handleIncallSonification()
+    if (state == AudioSystem::MODE_IN_CALL ||
+        oldState == AudioSystem::MODE_IN_CALL) {
+        bool starting = (state == AudioSystem::MODE_IN_CALL) ? true : false;
+        LOGV("setPhoneState() in call state management: new state is %d", state);
+        for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) {
+            handleIncallSonification(stream, starting);
+        }
+    }
+}
+
+void AudioPolicyManagerGeneric::setRingerMode(uint32_t mode, uint32_t mask)
+{
+    LOGV("setRingerMode() mode %x, mask %x", mode, mask);
+
+    mRingerMode = mode;
+}
+
+void AudioPolicyManagerGeneric::setForceUse(AudioSystem::force_use usage, AudioSystem::forced_config config)
+{
+    LOGV("setForceUse) usage %d, config %d, mPhoneState %d", usage, config, mPhoneState);
+    mForceUse[usage] = config;
+}
+
+AudioSystem::forced_config AudioPolicyManagerGeneric::getForceUse(AudioSystem::force_use usage)
+{
+    return mForceUse[usage];
+}
+
+void AudioPolicyManagerGeneric::setSystemProperty(const char* property, const char* value)
+{
+    LOGV("setSystemProperty() property %s, value %s", property, value);
+    if (strcmp(property, "ro.camera.sound.forced") == 0) {
+        if (atoi(value)) {
+            LOGV("ENFORCED_AUDIBLE cannot be muted");
+            mStreams[AudioSystem::ENFORCED_AUDIBLE].mCanBeMuted = false;
+        } else {
+            LOGV("ENFORCED_AUDIBLE can be muted");
+            mStreams[AudioSystem::ENFORCED_AUDIBLE].mCanBeMuted = true;
+        }
+    }
+}
+
+audio_io_handle_t AudioPolicyManagerGeneric::getOutput(AudioSystem::stream_type stream,
+                                    uint32_t samplingRate,
+                                    uint32_t format,
+                                    uint32_t channels,
+                                    AudioSystem::output_flags flags)
+{
+    LOGV("getOutput() stream %d, samplingRate %d, format %d, channels %x, flags %x", stream, samplingRate, format, channels, flags);
+
+#ifdef AUDIO_POLICY_TEST
+    if (mCurOutput != 0) {
+        LOGV("getOutput() test output mCurOutput %d, samplingRate %d, format %d, channels %x, mDirectOutput %d",
+                mCurOutput, mTestSamplingRate, mTestFormat, mTestChannels, mDirectOutput);
+
+        if (mTestOutputs[mCurOutput] == 0) {
+            LOGV("getOutput() opening test output");
+            AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor();
+            outputDesc->mDevice = mTestDevice;
+            outputDesc->mSamplingRate = mTestSamplingRate;
+            outputDesc->mFormat = mTestFormat;
+            outputDesc->mChannels = mTestChannels;
+            outputDesc->mLatency = mTestLatencyMs;
+            outputDesc->mFlags = (AudioSystem::output_flags)(mDirectOutput ? AudioSystem::OUTPUT_FLAG_DIRECT : 0);
+            outputDesc->mRefCount[stream] = 0;
+            mTestOutputs[mCurOutput] = mpClientInterface->openOutput(&outputDesc->mDevice,
+                                            &outputDesc->mSamplingRate,
+                                            &outputDesc->mFormat,
+                                            &outputDesc->mChannels,
+                                            &outputDesc->mLatency,
+                                            outputDesc->mFlags);
+            if (mTestOutputs[mCurOutput]) {
+                AudioParameter outputCmd = AudioParameter();
+                outputCmd.addInt(String8("set_id"),mCurOutput);
+                mpClientInterface->setParameters(mTestOutputs[mCurOutput],outputCmd.toString());
+                mOutputs.add(mTestOutputs[mCurOutput], outputDesc);
+            }
+        }
+        return mTestOutputs[mCurOutput];
+    }
+#endif //AUDIO_POLICY_TEST
+    if ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) ||
+        (format != 0 && !AudioSystem::isLinearPCM(format)) ||
+        (channels != 0 && channels != AudioSystem::CHANNEL_OUT_MONO && channels != AudioSystem::CHANNEL_OUT_STEREO)) {
+        return 0;
+    }
+
+    return mHardwareOutput;
+}
+
+status_t AudioPolicyManagerGeneric::startOutput(audio_io_handle_t output, AudioSystem::stream_type stream)
+{
+    LOGV("startOutput() output %d, stream %d", output, stream);
+    ssize_t index = mOutputs.indexOfKey(output);
+    if (index < 0) {
+        LOGW("startOutput() unknow output %d", output);
+        return BAD_VALUE;
+    }
+
+    AudioOutputDescriptor *outputDesc = mOutputs.valueAt(index);
+
+    // handle special case for sonification while in call
+    if (mPhoneState == AudioSystem::MODE_IN_CALL) {
+        handleIncallSonification(stream, true);
+    }
+
+    // incremenent usage count for this stream on the requested output:
+    outputDesc->changeRefCount(stream, 1);
+    return NO_ERROR;
+}
+
+status_t AudioPolicyManagerGeneric::stopOutput(audio_io_handle_t output, AudioSystem::stream_type stream)
+{
+    LOGV("stopOutput() output %d, stream %d", output, stream);
+    ssize_t index = mOutputs.indexOfKey(output);
+    if (index < 0) {
+        LOGW("stopOutput() unknow output %d", output);
+        return BAD_VALUE;
+    }
+
+    AudioOutputDescriptor *outputDesc = mOutputs.valueAt(index);
+
+    // handle special case for sonification while in call
+    if (mPhoneState == AudioSystem::MODE_IN_CALL) {
+        handleIncallSonification(stream, false);
+    }
+
+    if (outputDesc->isUsedByStream(stream)) {
+        // decrement usage count of this stream on the output
+        outputDesc->changeRefCount(stream, -1);
+        return NO_ERROR;
+    } else {
+        LOGW("stopOutput() refcount is already 0 for output %d", output);
+        return INVALID_OPERATION;
+    }
+}
+
+void AudioPolicyManagerGeneric::releaseOutput(audio_io_handle_t output)
+{
+    LOGV("releaseOutput() %d", output);
+    ssize_t index = mOutputs.indexOfKey(output);
+    if (index < 0) {
+        LOGW("releaseOutput() releasing unknown output %d", output);
+        return;
+    }
+
+#ifdef AUDIO_POLICY_TEST
+    int testIndex = testOutputIndex(output);
+    if (testIndex != 0) {
+        AudioOutputDescriptor *outputDesc = mOutputs.valueAt(index);
+        if (outputDesc->refCount() == 0) {
+            mpClientInterface->closeOutput(output);
+            delete mOutputs.valueAt(index);
+            mOutputs.removeItem(output);
+            mTestOutputs[testIndex] = 0;
+        }
+    }
+#endif //AUDIO_POLICY_TEST
+}
+
+audio_io_handle_t AudioPolicyManagerGeneric::getInput(int inputSource,
+                                    uint32_t samplingRate,
+                                    uint32_t format,
+                                    uint32_t channels,
+                                    AudioSystem::audio_in_acoustics acoustics)
+{
+    audio_io_handle_t input = 0;
+    uint32_t device;
+
+    LOGV("getInput() inputSource %d, samplingRate %d, format %d, channels %x, acoustics %x", inputSource, samplingRate, format, channels, acoustics);
+
+    AudioInputDescriptor *inputDesc = new AudioInputDescriptor();
+    inputDesc->mDevice = AudioSystem::DEVICE_IN_BUILTIN_MIC;
+    inputDesc->mSamplingRate = samplingRate;
+    inputDesc->mFormat = format;
+    inputDesc->mChannels = channels;
+    inputDesc->mAcoustics = acoustics;
+    inputDesc->mRefCount = 0;
+    input = mpClientInterface->openInput(&inputDesc->mDevice,
+                                    &inputDesc->mSamplingRate,
+                                    &inputDesc->mFormat,
+                                    &inputDesc->mChannels,
+                                    inputDesc->mAcoustics);
+
+    // only accept input with the exact requested set of parameters
+    if ((samplingRate != inputDesc->mSamplingRate) ||
+        (format != inputDesc->mFormat) ||
+        (channels != inputDesc->mChannels)) {
+        LOGV("getOutput() failed opening input: samplingRate %d, format %d, channels %d",
+                samplingRate, format, channels);
+        mpClientInterface->closeInput(input);
+        delete inputDesc;
+        return 0;
+    }
+    mInputs.add(input, inputDesc);
+    return input;
+}
+
+status_t AudioPolicyManagerGeneric::startInput(audio_io_handle_t input)
+{
+    LOGV("startInput() input %d", input);
+    ssize_t index = mInputs.indexOfKey(input);
+    if (index < 0) {
+        LOGW("startInput() unknow input %d", input);
+        return BAD_VALUE;
+    }
+    AudioInputDescriptor *inputDesc = mInputs.valueAt(index);
+
+#ifdef AUDIO_POLICY_TEST
+    if (mTestInput == 0)
+#endif //AUDIO_POLICY_TEST
+    {
+        // refuse 2 active AudioRecord clients at the same time
+        for (size_t i = 0; i < mInputs.size(); i++) {
+            if (mInputs.valueAt(i)->mRefCount > 0) {
+                LOGW("startInput() input %d, other input %d already started", input, mInputs.keyAt(i));
+                return INVALID_OPERATION;
+            }
+        }
+    }
+
+    inputDesc->mRefCount = 1;
+    return NO_ERROR;
+}
+
+status_t AudioPolicyManagerGeneric::stopInput(audio_io_handle_t input)
+{
+    LOGV("stopInput() input %d", input);
+    ssize_t index = mInputs.indexOfKey(input);
+    if (index < 0) {
+        LOGW("stopInput() unknow input %d", input);
+        return BAD_VALUE;
+    }
+    AudioInputDescriptor *inputDesc = mInputs.valueAt(index);
+
+    if (inputDesc->mRefCount == 0) {
+        LOGW("stopInput() input %d already stopped", input);
+        return INVALID_OPERATION;
+    } else {
+        inputDesc->mRefCount = 0;
+        return NO_ERROR;
+    }
+}
+
+void AudioPolicyManagerGeneric::releaseInput(audio_io_handle_t input)
+{
+    LOGV("releaseInput() %d", input);
+    ssize_t index = mInputs.indexOfKey(input);
+    if (index < 0) {
+        LOGW("releaseInput() releasing unknown input %d", input);
+        return;
+    }
+    mpClientInterface->closeInput(input);
+    delete mInputs.valueAt(index);
+    mInputs.removeItem(input);
+}
+
+
+
+void AudioPolicyManagerGeneric::initStreamVolume(AudioSystem::stream_type stream,
+                                            int indexMin,
+                                            int indexMax)
+{
+    LOGV("initStreamVolume() stream %d, min %d, max %d", stream , indexMin, indexMax);
+    mStreams[stream].mIndexMin = indexMin;
+    mStreams[stream].mIndexMax = indexMax;
+}
+
+status_t AudioPolicyManagerGeneric::setStreamVolumeIndex(AudioSystem::stream_type stream, int index)
+{
+
+    if ((index < mStreams[stream].mIndexMin) || (index > mStreams[stream].mIndexMax)) {
+        return BAD_VALUE;
+    }
+
+    LOGV("setStreamVolumeIndex() stream %d, index %d", stream, index);
+    mStreams[stream].mIndexCur = index;
+
+    // do not change actual stream volume if the stream is muted
+    if (mStreams[stream].mMuteCount != 0) {
+        return NO_ERROR;
+    }
+
+    // Do not changed in call volume if bluetooth is connected and vice versa
+    if ((stream == AudioSystem::VOICE_CALL && mForceUse[AudioSystem::FOR_COMMUNICATION] == AudioSystem::FORCE_BT_SCO) ||
+        (stream == AudioSystem::BLUETOOTH_SCO && mForceUse[AudioSystem::FOR_COMMUNICATION] != AudioSystem::FORCE_BT_SCO)) {
+        LOGV("setStreamVolumeIndex() cannot set stream %d volume with force use = %d for comm",
+             stream, mForceUse[AudioSystem::FOR_COMMUNICATION]);
+        return INVALID_OPERATION;
+    }
+
+    // compute and apply stream volume on all outputs according to connected device
+    for (size_t i = 0; i < mOutputs.size(); i++) {
+        AudioOutputDescriptor *outputDesc = mOutputs.valueAt(i);
+        uint32_t device = outputDesc->device();
+
+        float volume = computeVolume((int)stream, index, device);
+
+        LOGV("setStreamVolume() for output %d stream %d, volume %f", mOutputs.keyAt(i), stream, volume);
+        mpClientInterface->setStreamVolume(stream, volume, mOutputs.keyAt(i));
+    }
+    return NO_ERROR;
+}
+
+status_t AudioPolicyManagerGeneric::getStreamVolumeIndex(AudioSystem::stream_type stream, int *index)
+{
+    if (index == 0) {
+        return BAD_VALUE;
+    }
+    LOGV("getStreamVolumeIndex() stream %d", stream);
+    *index =  mStreams[stream].mIndexCur;
+    return NO_ERROR;
+}
+
+status_t AudioPolicyManagerGeneric::dump(int fd)
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+
+    snprintf(buffer, SIZE, "\nAudioPolicyManager Dump: %p\n", this);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Hardware Output: %d\n", mHardwareOutput);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Output devices: %08x\n", mAvailableOutputDevices);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Input devices: %08x\n", mAvailableInputDevices);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Phone state: %d\n", mPhoneState);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Ringer mode: %d\n", mRingerMode);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Force use for communications %d\n", mForceUse[AudioSystem::FOR_COMMUNICATION]);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Force use for media %d\n", mForceUse[AudioSystem::FOR_MEDIA]);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Force use for record %d\n", mForceUse[AudioSystem::FOR_RECORD]);
+    result.append(buffer);
+    write(fd, result.string(), result.size());
+
+    snprintf(buffer, SIZE, "\nOutputs dump:\n");
+    write(fd, buffer, strlen(buffer));
+    for (size_t i = 0; i < mOutputs.size(); i++) {
+        snprintf(buffer, SIZE, "- Output %d dump:\n", mOutputs.keyAt(i));
+        write(fd, buffer, strlen(buffer));
+        mOutputs.valueAt(i)->dump(fd);
+    }
+
+    snprintf(buffer, SIZE, "\nInputs dump:\n");
+    write(fd, buffer, strlen(buffer));
+    for (size_t i = 0; i < mInputs.size(); i++) {
+        snprintf(buffer, SIZE, "- Input %d dump:\n", mInputs.keyAt(i));
+        write(fd, buffer, strlen(buffer));
+        mInputs.valueAt(i)->dump(fd);
+    }
+
+    snprintf(buffer, SIZE, "\nStreams dump:\n");
+    write(fd, buffer, strlen(buffer));
+    snprintf(buffer, SIZE, " Stream  Index Min  Index Max  Index Cur  Mute Count  Can be muted\n");
+    write(fd, buffer, strlen(buffer));
+    for (size_t i = 0; i < AudioSystem::NUM_STREAM_TYPES; i++) {
+        snprintf(buffer, SIZE, " %02d", i);
+        mStreams[i].dump(buffer + 3, SIZE);
+        write(fd, buffer, strlen(buffer));
+    }
+
+    return NO_ERROR;
+}
+
+// ----------------------------------------------------------------------------
+// AudioPolicyManagerGeneric
+// ----------------------------------------------------------------------------
+
+// ---  class factory
+
+AudioPolicyManagerGeneric::AudioPolicyManagerGeneric(AudioPolicyClientInterface *clientInterface)
+    :
+#ifdef AUDIO_POLICY_TEST
+    Thread(false),
+#endif //AUDIO_POLICY_TEST
+    mPhoneState(AudioSystem::MODE_NORMAL), mRingerMode(0)
+{
+    mpClientInterface = clientInterface;
+
+    for (int i = 0; i < AudioSystem::NUM_FORCE_USE; i++) {
+        mForceUse[i] = AudioSystem::FORCE_NONE;
+    }
+
+    // devices available by default are speaker, ear piece and microphone
+    mAvailableOutputDevices = AudioSystem::DEVICE_OUT_SPEAKER;
+    mAvailableInputDevices = AudioSystem::DEVICE_IN_BUILTIN_MIC;
+
+    // open hardware output
+    AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor();
+    outputDesc->mDevice = (uint32_t)AudioSystem::DEVICE_OUT_SPEAKER;
+    mHardwareOutput = mpClientInterface->openOutput(&outputDesc->mDevice,
+                                    &outputDesc->mSamplingRate,
+                                    &outputDesc->mFormat,
+                                    &outputDesc->mChannels,
+                                    &outputDesc->mLatency,
+                                    outputDesc->mFlags);
+
+    if (mHardwareOutput == 0) {
+        LOGE("Failed to initialize hardware output stream, samplingRate: %d, format %d, channels %d",
+                outputDesc->mSamplingRate, outputDesc->mFormat, outputDesc->mChannels);
+    } else {
+        mOutputs.add(mHardwareOutput, outputDesc);
+    }
+
+#ifdef AUDIO_POLICY_TEST
+    AudioParameter outputCmd = AudioParameter();
+    outputCmd.addInt(String8("set_id"), 0);
+    mpClientInterface->setParameters(mHardwareOutput, outputCmd.toString());
+
+    mTestDevice = AudioSystem::DEVICE_OUT_SPEAKER;
+    mTestSamplingRate = 44100;
+    mTestFormat = AudioSystem::PCM_16_BIT;
+    mTestChannels =  AudioSystem::CHANNEL_OUT_STEREO;
+    mTestLatencyMs = 0;
+    mCurOutput = 0;
+    mDirectOutput = false;
+    for (int i = 0; i < NUM_TEST_OUTPUTS; i++) {
+        mTestOutputs[i] = 0;
+    }
+
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    snprintf(buffer, SIZE, "AudioPolicyManagerTest");
+    run(buffer, ANDROID_PRIORITY_AUDIO);
+#endif //AUDIO_POLICY_TEST
+}
+
+AudioPolicyManagerGeneric::~AudioPolicyManagerGeneric()
+{
+#ifdef AUDIO_POLICY_TEST
+    exit();
+#endif //AUDIO_POLICY_TEST
+
+   for (size_t i = 0; i < mOutputs.size(); i++) {
+        mpClientInterface->closeOutput(mOutputs.keyAt(i));
+        delete mOutputs.valueAt(i);
+   }
+   mOutputs.clear();
+   for (size_t i = 0; i < mInputs.size(); i++) {
+        mpClientInterface->closeInput(mInputs.keyAt(i));
+        delete mInputs.valueAt(i);
+   }
+   mInputs.clear();
+}
+
+#ifdef AUDIO_POLICY_TEST
+bool AudioPolicyManagerGeneric::threadLoop()
+{
+    LOGV("entering threadLoop()");
+    while (!exitPending())
+    {
+        String8 command;
+        int valueInt;
+        String8 value;
+
+        Mutex::Autolock _l(mLock);
+        mWaitWorkCV.waitRelative(mLock, milliseconds(50));
+
+        command = mpClientInterface->getParameters(0, String8("test_cmd_policy"));
+        AudioParameter param = AudioParameter(command);
+
+        if (param.getInt(String8("test_cmd_policy"), valueInt) == NO_ERROR &&
+            valueInt != 0) {
+            LOGV("Test command %s received", command.string());
+            String8 target;
+            if (param.get(String8("target"), target) != NO_ERROR) {
+                target = "Manager";
+            }
+            if (param.getInt(String8("test_cmd_policy_output"), valueInt) == NO_ERROR) {
+                param.remove(String8("test_cmd_policy_output"));
+                mCurOutput = valueInt;
+            }
+            if (param.get(String8("test_cmd_policy_direct"), value) == NO_ERROR) {
+                param.remove(String8("test_cmd_policy_direct"));
+                if (value == "false") {
+                    mDirectOutput = false;
+                } else if (value == "true") {
+                    mDirectOutput = true;
+                }
+            }
+            if (param.getInt(String8("test_cmd_policy_input"), valueInt) == NO_ERROR) {
+                param.remove(String8("test_cmd_policy_input"));
+                mTestInput = valueInt;
+            }
+
+            if (param.get(String8("test_cmd_policy_format"), value) == NO_ERROR) {
+                param.remove(String8("test_cmd_policy_format"));
+                int format = AudioSystem::INVALID_FORMAT;
+                if (value == "PCM 16 bits") {
+                    format = AudioSystem::PCM_16_BIT;
+                } else if (value == "PCM 8 bits") {
+                    format = AudioSystem::PCM_8_BIT;
+                } else if (value == "Compressed MP3") {
+                    format = AudioSystem::MP3;
+                }
+                if (format != AudioSystem::INVALID_FORMAT) {
+                    if (target == "Manager") {
+                        mTestFormat = format;
+                    } else if (mTestOutputs[mCurOutput] != 0) {
+                        AudioParameter outputParam = AudioParameter();
+                        outputParam.addInt(String8("format"), format);
+                        mpClientInterface->setParameters(mTestOutputs[mCurOutput], outputParam.toString());
+                    }
+                }
+            }
+            if (param.get(String8("test_cmd_policy_channels"), value) == NO_ERROR) {
+                param.remove(String8("test_cmd_policy_channels"));
+                int channels = 0;
+
+                if (value == "Channels Stereo") {
+                    channels =  AudioSystem::CHANNEL_OUT_STEREO;
+                } else if (value == "Channels Mono") {
+                    channels =  AudioSystem::CHANNEL_OUT_MONO;
+                }
+                if (channels != 0) {
+                    if (target == "Manager") {
+                        mTestChannels = channels;
+                    } else if (mTestOutputs[mCurOutput] != 0) {
+                        AudioParameter outputParam = AudioParameter();
+                        outputParam.addInt(String8("channels"), channels);
+                        mpClientInterface->setParameters(mTestOutputs[mCurOutput], outputParam.toString());
+                    }
+                }
+            }
+            if (param.getInt(String8("test_cmd_policy_sampleRate"), valueInt) == NO_ERROR) {
+                param.remove(String8("test_cmd_policy_sampleRate"));
+                if (valueInt >= 0 && valueInt <= 96000) {
+                    int samplingRate = valueInt;
+                    if (target == "Manager") {
+                        mTestSamplingRate = samplingRate;
+                    } else if (mTestOutputs[mCurOutput] != 0) {
+                        AudioParameter outputParam = AudioParameter();
+                        outputParam.addInt(String8("sampling_rate"), samplingRate);
+                        mpClientInterface->setParameters(mTestOutputs[mCurOutput], outputParam.toString());
+                    }
+                }
+            }
+
+            if (param.get(String8("test_cmd_policy_reopen"), value) == NO_ERROR) {
+                param.remove(String8("test_cmd_policy_reopen"));
+
+                mpClientInterface->closeOutput(mHardwareOutput);
+                delete mOutputs.valueFor(mHardwareOutput);
+                mOutputs.removeItem(mHardwareOutput);
+
+                AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor();
+                outputDesc->mDevice = (uint32_t)AudioSystem::DEVICE_OUT_SPEAKER;
+                mHardwareOutput = mpClientInterface->openOutput(&outputDesc->mDevice,
+                                                &outputDesc->mSamplingRate,
+                                                &outputDesc->mFormat,
+                                                &outputDesc->mChannels,
+                                                &outputDesc->mLatency,
+                                                outputDesc->mFlags);
+                if (mHardwareOutput == 0) {
+                    LOGE("Failed to reopen hardware output stream, samplingRate: %d, format %d, channels %d",
+                            outputDesc->mSamplingRate, outputDesc->mFormat, outputDesc->mChannels);
+                } else {
+                    AudioParameter outputCmd = AudioParameter();
+                    outputCmd.addInt(String8("set_id"), 0);
+                    mpClientInterface->setParameters(mHardwareOutput, outputCmd.toString());
+                    mOutputs.add(mHardwareOutput, outputDesc);
+                }
+            }
+
+
+            mpClientInterface->setParameters(0, String8("test_cmd_policy="));
+        }
+    }
+    return false;
+}
+
+void AudioPolicyManagerGeneric::exit()
+{
+    {
+        AutoMutex _l(mLock);
+        requestExit();
+        mWaitWorkCV.signal();
+    }
+    requestExitAndWait();
+}
+
+int AudioPolicyManagerGeneric::testOutputIndex(audio_io_handle_t output)
+{
+    for (int i = 0; i < NUM_TEST_OUTPUTS; i++) {
+        if (output == mTestOutputs[i]) return i;
+    }
+    return 0;
+}
+#endif //AUDIO_POLICY_TEST
+
+// ---
+
+AudioPolicyManagerGeneric::routing_strategy AudioPolicyManagerGeneric::getStrategy(AudioSystem::stream_type stream)
+{
+    // stream to strategy mapping
+    switch (stream) {
+    case AudioSystem::VOICE_CALL:
+    case AudioSystem::BLUETOOTH_SCO:
+        return STRATEGY_PHONE;
+    case AudioSystem::RING:
+    case AudioSystem::NOTIFICATION:
+    case AudioSystem::ALARM:
+    case AudioSystem::ENFORCED_AUDIBLE:
+        return STRATEGY_SONIFICATION;
+    case AudioSystem::DTMF:
+        return STRATEGY_DTMF;
+    default:
+        LOGE("unknown stream type");
+    case AudioSystem::SYSTEM:
+        // NOTE: SYSTEM stream uses MEDIA strategy because muting music and switching outputs
+        // while key clicks are played produces a poor result
+    case AudioSystem::TTS:
+    case AudioSystem::MUSIC:
+        return STRATEGY_MEDIA;
+    }
+}
+
+
+float AudioPolicyManagerGeneric::computeVolume(int stream, int index, uint32_t device)
+{
+    float volume = 1.0;
+
+    StreamDescriptor &streamDesc = mStreams[stream];
+
+    // Force max volume if stream cannot be muted
+    if (!streamDesc.mCanBeMuted) index = streamDesc.mIndexMax;
+
+    int volInt = (100 * (index - streamDesc.mIndexMin)) / (streamDesc.mIndexMax - streamDesc.mIndexMin);
+    volume = AudioSystem::linearToLog(volInt);
+
+    return volume;
+}
+
+void AudioPolicyManagerGeneric::setStreamMute(int stream, bool on, audio_io_handle_t output)
+{
+    LOGV("setStreamMute() stream %d, mute %d, output %d", stream, on, output);
+
+    StreamDescriptor &streamDesc = mStreams[stream];
+
+    if (on) {
+        if (streamDesc.mMuteCount++ == 0) {
+            if (streamDesc.mCanBeMuted) {
+                mpClientInterface->setStreamVolume((AudioSystem::stream_type)stream, 0, output);
+            }
+        }
+    } else {
+        if (streamDesc.mMuteCount == 0) {
+            LOGW("setStreamMute() unmuting non muted stream!");
+            return;
+        }
+        if (--streamDesc.mMuteCount == 0) {
+            uint32_t device = mOutputs.valueFor(output)->mDevice;
+            float volume = computeVolume(stream, streamDesc.mIndexCur, device);
+            mpClientInterface->setStreamVolume((AudioSystem::stream_type)stream, volume, output);
+        }
+    }
+}
+
+void AudioPolicyManagerGeneric::handleIncallSonification(int stream, bool starting)
+{
+    // if the stream pertains to sonification strategy and we are in call we must
+    // mute the stream if it is low visibility. If it is high visibility, we must play a tone
+    // in the device used for phone strategy and play the tone if the selected device does not
+    // interfere with the device used for phone strategy
+    if (getStrategy((AudioSystem::stream_type)stream) == STRATEGY_SONIFICATION) {
+        AudioOutputDescriptor *outputDesc = mOutputs.valueFor(mHardwareOutput);
+        LOGV("handleIncallSonification() stream %d starting %d device %x", stream, starting, outputDesc->mDevice);
+        if (outputDesc->isUsedByStream((AudioSystem::stream_type)stream)) {
+            if (AudioSystem::isLowVisibility((AudioSystem::stream_type)stream)) {
+                LOGV("handleIncallSonification() low visibility");
+                setStreamMute(stream, starting, mHardwareOutput);
+            } else {
+                if (starting) {
+                    mpClientInterface->startTone(ToneGenerator::TONE_SUP_CALL_WAITING, AudioSystem::VOICE_CALL);
+                } else {
+                    mpClientInterface->stopTone();
+                }
+            }
+        }
+    }
+}
+
+
+// --- AudioOutputDescriptor class implementation
+
+AudioPolicyManagerGeneric::AudioOutputDescriptor::AudioOutputDescriptor()
+    : mSamplingRate(0), mFormat(0), mChannels(0), mLatency(0),
+    mFlags((AudioSystem::output_flags)0), mDevice(0)
+{
+    // clear usage count for all stream types
+    for (int i = 0; i < AudioSystem::NUM_STREAM_TYPES; i++) {
+        mRefCount[i] = 0;
+    }
+}
+
+uint32_t AudioPolicyManagerGeneric::AudioOutputDescriptor::device()
+{
+    return mDevice;
+}
+
+void AudioPolicyManagerGeneric::AudioOutputDescriptor::changeRefCount(AudioSystem::stream_type stream, int delta)
+{
+    if ((delta + (int)mRefCount[stream]) < 0) {
+        LOGW("changeRefCount() invalid delta %d for stream %d, refCount %d", delta, stream, mRefCount[stream]);
+        mRefCount[stream] = 0;
+        return;
+    }
+    mRefCount[stream] += delta;
+    LOGV("changeRefCount() stream %d, count %d", stream, mRefCount[stream]);
+}
+
+uint32_t AudioPolicyManagerGeneric::AudioOutputDescriptor::refCount()
+{
+    uint32_t refcount = 0;
+    for (int i = 0; i < (int)AudioSystem::NUM_STREAM_TYPES; i++) {
+        refcount += mRefCount[i];
+    }
+    return refcount;
+}
+
+status_t AudioPolicyManagerGeneric::AudioOutputDescriptor::dump(int fd)
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+
+    snprintf(buffer, SIZE, " Sampling rate: %d\n", mSamplingRate);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Format: %d\n", mFormat);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Channels: %08x\n", mChannels);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Latency: %d\n", mLatency);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Flags %08x\n", mFlags);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Devices %08x\n", mDevice);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Stream refCount\n");
+    result.append(buffer);
+    for (int i = 0; i < AudioSystem::NUM_STREAM_TYPES; i++) {
+        snprintf(buffer, SIZE, " %02d     %d\n", i, mRefCount[i]);
+        result.append(buffer);
+    }
+    write(fd, result.string(), result.size());
+
+    return NO_ERROR;
+}
+
+// --- AudioInputDescriptor class implementation
+
+AudioPolicyManagerGeneric::AudioInputDescriptor::AudioInputDescriptor()
+    : mSamplingRate(0), mFormat(0), mChannels(0),
+     mAcoustics((AudioSystem::audio_in_acoustics)0), mDevice(0), mRefCount(0)
+{
+}
+
+status_t AudioPolicyManagerGeneric::AudioInputDescriptor::dump(int fd)
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+
+    snprintf(buffer, SIZE, " Sampling rate: %d\n", mSamplingRate);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Format: %d\n", mFormat);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Channels: %08x\n", mChannels);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Acoustics %08x\n", mAcoustics);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Devices %08x\n", mDevice);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Ref Count %d\n", mRefCount);
+    result.append(buffer);
+    write(fd, result.string(), result.size());
+
+    return NO_ERROR;
+}
+
+// --- StreamDescriptor class implementation
+
+void AudioPolicyManagerGeneric::StreamDescriptor::dump(char* buffer, size_t size)
+{
+    snprintf(buffer, size, "      %02d         %02d         %02d         %02d          %d\n",
+            mIndexMin,
+            mIndexMax,
+            mIndexCur,
+            mMuteCount,
+            mCanBeMuted);
+}
+
+}; // namespace android
diff --git a/libs/audioflinger/AudioPolicyManagerGeneric.h b/libs/audioflinger/AudioPolicyManagerGeneric.h
new file mode 100644
index 0000000..4997cdf
--- /dev/null
+++ b/libs/audioflinger/AudioPolicyManagerGeneric.h
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2009 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/Errors.h>
+#include <utils/KeyedVector.h>
+#include <hardware_legacy/AudioPolicyInterface.h>
+#include <utils/threads.h>
+
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+#define MAX_DEVICE_ADDRESS_LEN 20
+#define NUM_TEST_OUTPUTS 5
+
+class AudioPolicyManagerGeneric: public AudioPolicyInterface
+#ifdef AUDIO_POLICY_TEST
+    , public Thread
+#endif //AUDIO_POLICY_TEST
+{
+
+public:
+                AudioPolicyManagerGeneric(AudioPolicyClientInterface *clientInterface);
+        virtual ~AudioPolicyManagerGeneric();
+
+        // AudioPolicyInterface
+        virtual status_t setDeviceConnectionState(AudioSystem::audio_devices device,
+                                                          AudioSystem::device_connection_state state,
+                                                          const char *device_address);
+        virtual AudioSystem::device_connection_state getDeviceConnectionState(AudioSystem::audio_devices device,
+                                                                              const char *device_address);
+        virtual void setPhoneState(int state);
+        virtual void setRingerMode(uint32_t mode, uint32_t mask);
+        virtual void setForceUse(AudioSystem::force_use usage, AudioSystem::forced_config config);
+        virtual AudioSystem::forced_config getForceUse(AudioSystem::force_use usage);
+        virtual void setSystemProperty(const char* property, const char* value);
+        virtual audio_io_handle_t getOutput(AudioSystem::stream_type stream,
+                                            uint32_t samplingRate,
+                                            uint32_t format,
+                                            uint32_t channels,
+                                            AudioSystem::output_flags flags);
+        virtual status_t startOutput(audio_io_handle_t output, AudioSystem::stream_type stream);
+        virtual status_t stopOutput(audio_io_handle_t output, AudioSystem::stream_type stream);
+        virtual void releaseOutput(audio_io_handle_t output);
+        virtual audio_io_handle_t getInput(int inputSource,
+                                            uint32_t samplingRate,
+                                            uint32_t format,
+                                            uint32_t channels,
+                                            AudioSystem::audio_in_acoustics acoustics);
+        // indicates to the audio policy manager that the input starts being used.
+        virtual status_t startInput(audio_io_handle_t input);
+        // indicates to the audio policy manager that the input stops being used.
+        virtual status_t stopInput(audio_io_handle_t input);
+        virtual void releaseInput(audio_io_handle_t input);
+        virtual void initStreamVolume(AudioSystem::stream_type stream,
+                                                    int indexMin,
+                                                    int indexMax);
+        virtual status_t setStreamVolumeIndex(AudioSystem::stream_type stream, int index);
+        virtual status_t getStreamVolumeIndex(AudioSystem::stream_type stream, int *index);
+
+        virtual status_t dump(int fd);
+
+private:
+
+        enum routing_strategy {
+            STRATEGY_MEDIA,
+            STRATEGY_PHONE,
+            STRATEGY_SONIFICATION,
+            STRATEGY_DTMF,
+            NUM_STRATEGIES
+        };
+
+        // descriptor for audio outputs. Used to maintain current configuration of each opened audio output
+        // and keep track of the usage of this output by each audio stream type.
+        class AudioOutputDescriptor
+        {
+        public:
+            AudioOutputDescriptor();
+
+            status_t    dump(int fd);
+
+            uint32_t device();
+            void changeRefCount(AudioSystem::stream_type, int delta);
+            bool isUsedByStream(AudioSystem::stream_type stream) { return mRefCount[stream] > 0 ? true : false; }
+            uint32_t refCount();
+
+            uint32_t mSamplingRate;             //
+            uint32_t mFormat;                   //
+            uint32_t mChannels;                 // output configuration
+            uint32_t mLatency;                  //
+            AudioSystem::output_flags mFlags;   //
+            uint32_t mDevice;                   // current device this output is routed to
+            uint32_t mRefCount[AudioSystem::NUM_STREAM_TYPES]; // number of streams of each type using this output
+        };
+
+        // descriptor for audio inputs. Used to maintain current configuration of each opened audio input
+        // and keep track of the usage of this input.
+        class AudioInputDescriptor
+        {
+        public:
+            AudioInputDescriptor();
+
+            status_t    dump(int fd);
+
+            uint32_t mSamplingRate;                     //
+            uint32_t mFormat;                           // input configuration
+            uint32_t mChannels;                         //
+            AudioSystem::audio_in_acoustics mAcoustics; //
+            uint32_t mDevice;                           // current device this input is routed to
+            uint32_t mRefCount;                         // number of AudioRecord clients using this output
+        };
+
+        // stream descriptor used for volume control
+        class StreamDescriptor
+        {
+        public:
+            StreamDescriptor()
+            :   mIndexMin(0), mIndexMax(1), mIndexCur(1), mMuteCount(0), mCanBeMuted(true) {}
+
+            void dump(char* buffer, size_t size);
+
+            int mIndexMin;      // min volume index
+            int mIndexMax;      // max volume index
+            int mIndexCur;      // current volume index
+            int mMuteCount;     // mute request counter
+            bool mCanBeMuted;   // true is the stream can be muted
+        };
+
+        // return the strategy corresponding to a given stream type
+        static routing_strategy getStrategy(AudioSystem::stream_type stream);
+        // return the output handle of an output routed to the specified device, 0 if no output
+        // is routed to the device
+        float computeVolume(int stream, int index, uint32_t device);
+        // Mute or unmute the stream on the specified output
+        void setStreamMute(int stream, bool on, audio_io_handle_t output);
+        // handle special cases for sonification strategy while in call: mute streams or replace by
+        // a special tone in the device used for communication
+        void handleIncallSonification(int stream, bool starting);
+
+
+#ifdef AUDIO_POLICY_TEST
+        virtual     bool        threadLoop();
+                    void        exit();
+        int testOutputIndex(audio_io_handle_t output);
+#endif //AUDIO_POLICY_TEST
+
+
+        AudioPolicyClientInterface *mpClientInterface;  // audio policy client interface
+        audio_io_handle_t mHardwareOutput;              // hardware output handler
+
+        KeyedVector<audio_io_handle_t, AudioOutputDescriptor *> mOutputs;   // list ot output descritors
+        KeyedVector<audio_io_handle_t, AudioInputDescriptor *> mInputs;     // list of input descriptors
+        uint32_t mAvailableOutputDevices;                                   // bit field of all available output devices
+        uint32_t mAvailableInputDevices;                                    // bit field of all available input devices
+        int mPhoneState;                                                    // current phone state
+        uint32_t                 mRingerMode;                               // current ringer mode
+        AudioSystem::forced_config mForceUse[AudioSystem::NUM_FORCE_USE];   // current forced use configuration
+
+        StreamDescriptor mStreams[AudioSystem::NUM_STREAM_TYPES];           // stream descriptors for volume control
+
+#ifdef AUDIO_POLICY_TEST
+        Mutex   mLock;
+        Condition mWaitWorkCV;
+
+        int             mCurOutput;
+        bool            mDirectOutput;
+        audio_io_handle_t mTestOutputs[NUM_TEST_OUTPUTS];
+        int             mTestInput;
+        uint32_t        mTestDevice;
+        uint32_t        mTestSamplingRate;
+        uint32_t        mTestFormat;
+        uint32_t        mTestChannels;
+        uint32_t        mTestLatencyMs;
+#endif //AUDIO_POLICY_TEST
+
+};
+
+};
diff --git a/libs/audioflinger/AudioPolicyService.cpp b/libs/audioflinger/AudioPolicyService.cpp
new file mode 100644
index 0000000..aa48019
--- /dev/null
+++ b/libs/audioflinger/AudioPolicyService.cpp
@@ -0,0 +1,911 @@
+/*
+ * Copyright (C) 2009 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 "AudioPolicyService"
+//#define LOG_NDEBUG 0
+
+#undef __STRICT_ANSI__
+#define __STDINT_LIMITS
+#define __STDC_LIMIT_MACROS
+#include <stdint.h>
+
+#include <sys/time.h>
+#include <binder/IServiceManager.h>
+#include <utils/Log.h>
+#include <cutils/properties.h>
+#include <binder/IPCThreadState.h>
+#include <utils/String16.h>
+#include <utils/threads.h>
+#include "AudioPolicyService.h"
+#include "AudioPolicyManagerGeneric.h"
+#include <cutils/properties.h>
+#include <dlfcn.h>
+
+// ----------------------------------------------------------------------------
+// the sim build doesn't have gettid
+
+#ifndef HAVE_GETTID
+# define gettid getpid
+#endif
+
+namespace android {
+
+static const char* kDeadlockedString = "AudioPolicyService may be deadlocked\n";
+static const char* kCmdDeadlockedString = "AudioPolicyService command thread may be deadlocked\n";
+
+static const int kDumpLockRetries = 50;
+static const int kDumpLockSleep = 20000;
+
+static bool checkPermission() {
+#ifndef HAVE_ANDROID_OS
+    return true;
+#endif
+    if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
+    bool ok = checkCallingPermission(String16("android.permission.MODIFY_AUDIO_SETTINGS"));
+    if (!ok) LOGE("Request requires android.permission.MODIFY_AUDIO_SETTINGS");
+    return ok;
+}
+
+// ----------------------------------------------------------------------------
+
+AudioPolicyService::AudioPolicyService()
+    : BnAudioPolicyService() , mpPolicyManager(NULL)
+{
+    char value[PROPERTY_VALUE_MAX];
+
+    // start tone playback thread
+    mTonePlaybackThread = new AudioCommandThread();
+    // start audio commands thread
+    mAudioCommandThread = new AudioCommandThread();
+
+#if (defined GENERIC_AUDIO) || (defined AUDIO_POLICY_TEST)
+    mpPolicyManager = new AudioPolicyManagerGeneric(this);
+    LOGV("build for GENERIC_AUDIO - using generic audio policy");
+#else
+    // if running in emulation - use the emulator driver
+    if (property_get("ro.kernel.qemu", value, 0)) {
+        LOGV("Running in emulation - using generic audio policy");
+        mpPolicyManager = new AudioPolicyManagerGeneric(this);
+    }
+    else {
+        LOGV("Using hardware specific audio policy");
+        mpPolicyManager = createAudioPolicyManager(this);
+    }
+#endif
+
+    // load properties
+    property_get("ro.camera.sound.forced", value, "0");
+    mpPolicyManager->setSystemProperty("ro.camera.sound.forced", value);
+}
+
+AudioPolicyService::~AudioPolicyService()
+{
+    mTonePlaybackThread->exit();
+    mTonePlaybackThread.clear();
+    mAudioCommandThread->exit();
+    mAudioCommandThread.clear();
+
+    if (mpPolicyManager) {
+        delete mpPolicyManager;
+    }
+}
+
+
+status_t AudioPolicyService::setDeviceConnectionState(AudioSystem::audio_devices device,
+                                                  AudioSystem::device_connection_state state,
+                                                  const char *device_address)
+{
+    if (mpPolicyManager == NULL) {
+        return NO_INIT;
+    }
+    if (!checkPermission()) {
+        return PERMISSION_DENIED;
+    }
+    if (!AudioSystem::isOutputDevice(device) && !AudioSystem::isInputDevice(device)) {
+        return BAD_VALUE;
+    }
+    if (state != AudioSystem::DEVICE_STATE_AVAILABLE && state != AudioSystem::DEVICE_STATE_UNAVAILABLE) {
+        return BAD_VALUE;
+    }
+
+    LOGV("setDeviceConnectionState() tid %d", gettid());
+    Mutex::Autolock _l(mLock);
+    return mpPolicyManager->setDeviceConnectionState(device, state, device_address);
+}
+
+AudioSystem::device_connection_state AudioPolicyService::getDeviceConnectionState(AudioSystem::audio_devices device,
+                                                  const char *device_address)
+{
+    if (mpPolicyManager == NULL) {
+        return AudioSystem::DEVICE_STATE_UNAVAILABLE;
+    }
+    if (!checkPermission()) {
+        return AudioSystem::DEVICE_STATE_UNAVAILABLE;
+    }
+    return mpPolicyManager->getDeviceConnectionState(device, device_address);
+}
+
+status_t AudioPolicyService::setPhoneState(int state)
+{
+    if (mpPolicyManager == NULL) {
+        return NO_INIT;
+    }
+    if (!checkPermission()) {
+        return PERMISSION_DENIED;
+    }
+    if (state < 0 || state >= AudioSystem::NUM_MODES) {
+        return BAD_VALUE;
+    }
+
+    LOGV("setPhoneState() tid %d", gettid());
+
+    // TODO: check if it is more appropriate to do it in platform specific policy manager
+    AudioSystem::setMode(state);
+
+    Mutex::Autolock _l(mLock);
+    mpPolicyManager->setPhoneState(state);
+    return NO_ERROR;
+}
+
+status_t AudioPolicyService::setRingerMode(uint32_t mode, uint32_t mask)
+{
+    if (mpPolicyManager == NULL) {
+        return NO_INIT;
+    }
+    if (!checkPermission()) {
+        return PERMISSION_DENIED;
+    }
+
+    mpPolicyManager->setRingerMode(mode, mask);
+    return NO_ERROR;
+}
+
+status_t AudioPolicyService::setForceUse(AudioSystem::force_use usage, AudioSystem::forced_config config)
+{
+    if (mpPolicyManager == NULL) {
+        return NO_INIT;
+    }
+    if (!checkPermission()) {
+        return PERMISSION_DENIED;
+    }
+    if (usage < 0 || usage >= AudioSystem::NUM_FORCE_USE) {
+        return BAD_VALUE;
+    }
+    if (config < 0 || config >= AudioSystem::NUM_FORCE_CONFIG) {
+        return BAD_VALUE;
+    }
+    LOGV("setForceUse() tid %d", gettid());
+    Mutex::Autolock _l(mLock);
+    mpPolicyManager->setForceUse(usage, config);
+    return NO_ERROR;
+}
+
+AudioSystem::forced_config AudioPolicyService::getForceUse(AudioSystem::force_use usage)
+{
+    if (mpPolicyManager == NULL) {
+        return AudioSystem::FORCE_NONE;
+    }
+    if (!checkPermission()) {
+        return AudioSystem::FORCE_NONE;
+    }
+    if (usage < 0 || usage >= AudioSystem::NUM_FORCE_USE) {
+        return AudioSystem::FORCE_NONE;
+    }
+    return mpPolicyManager->getForceUse(usage);
+}
+
+audio_io_handle_t AudioPolicyService::getOutput(AudioSystem::stream_type stream,
+                                    uint32_t samplingRate,
+                                    uint32_t format,
+                                    uint32_t channels,
+                                    AudioSystem::output_flags flags)
+{
+    if (mpPolicyManager == NULL) {
+        return 0;
+    }
+    LOGV("getOutput() tid %d", gettid());
+    Mutex::Autolock _l(mLock);
+    return mpPolicyManager->getOutput(stream, samplingRate, format, channels, flags);
+}
+
+status_t AudioPolicyService::startOutput(audio_io_handle_t output, AudioSystem::stream_type stream)
+{
+    if (mpPolicyManager == NULL) {
+        return NO_INIT;
+    }
+    LOGV("startOutput() tid %d", gettid());
+    Mutex::Autolock _l(mLock);
+    return mpPolicyManager->startOutput(output, stream);
+}
+
+status_t AudioPolicyService::stopOutput(audio_io_handle_t output, AudioSystem::stream_type stream)
+{
+    if (mpPolicyManager == NULL) {
+        return NO_INIT;
+    }
+    LOGV("stopOutput() tid %d", gettid());
+    Mutex::Autolock _l(mLock);
+    return mpPolicyManager->stopOutput(output, stream);
+}
+
+void AudioPolicyService::releaseOutput(audio_io_handle_t output)
+{
+    if (mpPolicyManager == NULL) {
+        return;
+    }
+    LOGV("releaseOutput() tid %d", gettid());
+    Mutex::Autolock _l(mLock);
+    mpPolicyManager->releaseOutput(output);
+}
+
+audio_io_handle_t AudioPolicyService::getInput(int inputSource,
+                                    uint32_t samplingRate,
+                                    uint32_t format,
+                                    uint32_t channels,
+                                    AudioSystem::audio_in_acoustics acoustics)
+{
+    if (mpPolicyManager == NULL) {
+        return 0;
+    }
+    Mutex::Autolock _l(mLock);
+    return mpPolicyManager->getInput(inputSource, samplingRate, format, channels, acoustics);
+}
+
+status_t AudioPolicyService::startInput(audio_io_handle_t input)
+{
+    if (mpPolicyManager == NULL) {
+        return NO_INIT;
+    }
+    Mutex::Autolock _l(mLock);
+    return mpPolicyManager->startInput(input);
+}
+
+status_t AudioPolicyService::stopInput(audio_io_handle_t input)
+{
+    if (mpPolicyManager == NULL) {
+        return NO_INIT;
+    }
+    Mutex::Autolock _l(mLock);
+    return mpPolicyManager->stopInput(input);
+}
+
+void AudioPolicyService::releaseInput(audio_io_handle_t input)
+{
+    if (mpPolicyManager == NULL) {
+        return;
+    }
+    Mutex::Autolock _l(mLock);
+    mpPolicyManager->releaseInput(input);
+}
+
+status_t AudioPolicyService::initStreamVolume(AudioSystem::stream_type stream,
+                                            int indexMin,
+                                            int indexMax)
+{
+    if (mpPolicyManager == NULL) {
+        return NO_INIT;
+    }
+    if (!checkPermission()) {
+        return PERMISSION_DENIED;
+    }
+    if (stream < 0 || stream >= AudioSystem::NUM_STREAM_TYPES) {
+        return BAD_VALUE;
+    }
+    mpPolicyManager->initStreamVolume(stream, indexMin, indexMax);
+    return NO_ERROR;
+}
+
+status_t AudioPolicyService::setStreamVolumeIndex(AudioSystem::stream_type stream, int index)
+{
+    if (mpPolicyManager == NULL) {
+        return NO_INIT;
+    }
+    if (!checkPermission()) {
+        return PERMISSION_DENIED;
+    }
+    if (stream < 0 || stream >= AudioSystem::NUM_STREAM_TYPES) {
+        return BAD_VALUE;
+    }
+
+    return mpPolicyManager->setStreamVolumeIndex(stream, index);
+}
+
+status_t AudioPolicyService::getStreamVolumeIndex(AudioSystem::stream_type stream, int *index)
+{
+    if (mpPolicyManager == NULL) {
+        return NO_INIT;
+    }
+    if (!checkPermission()) {
+        return PERMISSION_DENIED;
+    }
+    if (stream < 0 || stream >= AudioSystem::NUM_STREAM_TYPES) {
+        return BAD_VALUE;
+    }
+    return mpPolicyManager->getStreamVolumeIndex(stream, index);
+}
+
+void AudioPolicyService::binderDied(const wp<IBinder>& who) {
+    LOGW("binderDied() %p, tid %d, calling tid %d", who.unsafe_get(), gettid(), IPCThreadState::self()->getCallingPid());
+}
+
+static bool tryLock(Mutex& mutex)
+{
+    bool locked = false;
+    for (int i = 0; i < kDumpLockRetries; ++i) {
+        if (mutex.tryLock() == NO_ERROR) {
+            locked = true;
+            break;
+        }
+        usleep(kDumpLockSleep);
+    }
+    return locked;
+}
+
+status_t AudioPolicyService::dumpInternals(int fd)
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+
+    snprintf(buffer, SIZE, "PolicyManager Interface: %p\n", mpPolicyManager);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "Command Thread: %p\n", mAudioCommandThread.get());
+    result.append(buffer);
+    snprintf(buffer, SIZE, "Tones Thread: %p\n", mTonePlaybackThread.get());
+    result.append(buffer);
+
+    write(fd, result.string(), result.size());
+    return NO_ERROR;
+}
+
+status_t AudioPolicyService::dump(int fd, const Vector<String16>& args)
+{
+    if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
+        dumpPermissionDenial(fd);
+    } else {
+        bool locked = tryLock(mLock);
+        if (!locked) {
+            String8 result(kDeadlockedString);
+            write(fd, result.string(), result.size());
+        }
+
+        dumpInternals(fd);
+        if (mAudioCommandThread != NULL) {
+            mAudioCommandThread->dump(fd);
+        }
+        if (mTonePlaybackThread != NULL) {
+            mTonePlaybackThread->dump(fd);
+        }
+
+        if (mpPolicyManager) {
+            mpPolicyManager->dump(fd);
+        }
+
+        if (locked) mLock.unlock();
+    }
+    return NO_ERROR;
+}
+
+status_t AudioPolicyService::dumpPermissionDenial(int fd)
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+    snprintf(buffer, SIZE, "Permission Denial: "
+            "can't dump AudioPolicyService from pid=%d, uid=%d\n",
+            IPCThreadState::self()->getCallingPid(),
+            IPCThreadState::self()->getCallingUid());
+    result.append(buffer);
+    write(fd, result.string(), result.size());
+    return NO_ERROR;
+}
+
+status_t AudioPolicyService::onTransact(
+        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    return BnAudioPolicyService::onTransact(code, data, reply, flags);
+}
+
+
+// ----------------------------------------------------------------------------
+void AudioPolicyService::instantiate() {
+    defaultServiceManager()->addService(
+            String16("media.audio_policy"), new AudioPolicyService());
+}
+
+
+// ----------------------------------------------------------------------------
+// AudioPolicyClientInterface implementation
+// ----------------------------------------------------------------------------
+
+
+audio_io_handle_t AudioPolicyService::openOutput(uint32_t *pDevices,
+                                uint32_t *pSamplingRate,
+                                uint32_t *pFormat,
+                                uint32_t *pChannels,
+                                uint32_t *pLatencyMs,
+                                AudioSystem::output_flags flags)
+{
+    sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
+    if (af == 0) {
+        LOGW("openOutput() could not get AudioFlinger");
+        return 0;
+    }
+
+    return af->openOutput(pDevices, pSamplingRate, (uint32_t *)pFormat, pChannels, pLatencyMs, flags);
+}
+
+audio_io_handle_t AudioPolicyService::openDuplicateOutput(audio_io_handle_t output1, audio_io_handle_t output2)
+{
+    sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
+    if (af == 0) {
+        LOGW("openDuplicateOutput() could not get AudioFlinger");
+        return 0;
+    }
+    return af->openDuplicateOutput(output1, output2);
+}
+
+status_t AudioPolicyService::closeOutput(audio_io_handle_t output)
+{
+    sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
+    if (af == 0) return PERMISSION_DENIED;
+
+    return af->closeOutput(output);
+}
+
+
+status_t AudioPolicyService::suspendOutput(audio_io_handle_t output)
+{
+    sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
+    if (af == 0) {
+        LOGW("suspendOutput() could not get AudioFlinger");
+        return PERMISSION_DENIED;
+    }
+
+    return af->suspendOutput(output);
+}
+
+status_t AudioPolicyService::restoreOutput(audio_io_handle_t output)
+{
+    sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
+    if (af == 0) {
+        LOGW("restoreOutput() could not get AudioFlinger");
+        return PERMISSION_DENIED;
+    }
+
+    return af->restoreOutput(output);
+}
+
+audio_io_handle_t AudioPolicyService::openInput(uint32_t *pDevices,
+                                uint32_t *pSamplingRate,
+                                uint32_t *pFormat,
+                                uint32_t *pChannels,
+                                uint32_t acoustics)
+{
+    sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
+    if (af == 0) {
+        LOGW("openInput() could not get AudioFlinger");
+        return 0;
+    }
+
+    return af->openInput(pDevices, pSamplingRate, (uint32_t *)pFormat, pChannels, acoustics);
+}
+
+status_t AudioPolicyService::closeInput(audio_io_handle_t input)
+{
+    sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
+    if (af == 0) return PERMISSION_DENIED;
+
+    return af->closeInput(input);
+}
+
+status_t AudioPolicyService::setStreamVolume(AudioSystem::stream_type stream, float volume, audio_io_handle_t output, int delayMs)
+{
+    return mAudioCommandThread->volumeCommand((int)stream, volume, (int)output, delayMs);
+}
+
+status_t AudioPolicyService::setStreamOutput(AudioSystem::stream_type stream, audio_io_handle_t output)
+{
+    sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
+    if (af == 0) return PERMISSION_DENIED;
+
+    return af->setStreamOutput(stream, output);
+}
+
+
+void AudioPolicyService::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs, int delayMs)
+{
+    mAudioCommandThread->parametersCommand((int)ioHandle, keyValuePairs, delayMs);
+}
+
+String8 AudioPolicyService::getParameters(audio_io_handle_t ioHandle, const String8& keys)
+{
+    String8 result = AudioSystem::getParameters(ioHandle, keys);
+    return result;
+}
+
+status_t AudioPolicyService::startTone(ToneGenerator::tone_type tone, AudioSystem::stream_type stream)
+{
+    mTonePlaybackThread->startToneCommand(tone, stream);
+    return NO_ERROR;
+}
+
+status_t AudioPolicyService::stopTone()
+{
+    mTonePlaybackThread->stopToneCommand();
+    return NO_ERROR;
+}
+
+status_t AudioPolicyService::setVoiceVolume(float volume, int delayMs)
+{
+    return mAudioCommandThread->voiceVolumeCommand(volume, delayMs);
+}
+
+// -----------  AudioPolicyService::AudioCommandThread implementation ----------
+
+AudioPolicyService::AudioCommandThread::AudioCommandThread()
+    :   Thread(false)
+{
+    mpToneGenerator = NULL;
+}
+
+
+AudioPolicyService::AudioCommandThread::~AudioCommandThread()
+{
+    mAudioCommands.clear();
+    if (mpToneGenerator != NULL) delete mpToneGenerator;
+}
+
+void AudioPolicyService::AudioCommandThread::onFirstRef()
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+
+    snprintf(buffer, SIZE, "AudioCommandThread");
+
+    run(buffer, ANDROID_PRIORITY_AUDIO);
+}
+
+bool AudioPolicyService::AudioCommandThread::threadLoop()
+{
+    nsecs_t waitTime = INT64_MAX;
+
+    mLock.lock();
+    while (!exitPending())
+    {
+        while(!mAudioCommands.isEmpty()) {
+            nsecs_t curTime = systemTime();
+            // commands are sorted by increasing time stamp: execute them from index 0 and up
+            if (mAudioCommands[0]->mTime <= curTime) {
+                AudioCommand *command = mAudioCommands[0];
+                mAudioCommands.removeAt(0);
+                mLastCommand = *command;
+
+                switch (command->mCommand) {
+                case START_TONE: {
+                    mLock.unlock();
+                    ToneData *data = (ToneData *)command->mParam;
+                    LOGV("AudioCommandThread() processing start tone %d on stream %d",
+                            data->mType, data->mStream);
+                    if (mpToneGenerator != NULL)
+                        delete mpToneGenerator;
+                    mpToneGenerator = new ToneGenerator(data->mStream, 1.0);
+                    mpToneGenerator->startTone(data->mType);
+                    delete data;
+                    mLock.lock();
+                    }break;
+                case STOP_TONE: {
+                    mLock.unlock();
+                    LOGV("AudioCommandThread() processing stop tone");
+                    if (mpToneGenerator != NULL) {
+                        mpToneGenerator->stopTone();
+                        delete mpToneGenerator;
+                        mpToneGenerator = NULL;
+                    }
+                    mLock.lock();
+                    }break;
+                case SET_VOLUME: {
+                    VolumeData *data = (VolumeData *)command->mParam;
+                    LOGV("AudioCommandThread() processing set volume stream %d, volume %f, output %d", data->mStream, data->mVolume, data->mIO);
+                    command->mStatus = AudioSystem::setStreamVolume(data->mStream, data->mVolume, data->mIO);
+                    if (command->mWaitStatus) {
+                        command->mCond.signal();
+                        mWaitWorkCV.wait(mLock);
+                    }
+                    delete data;
+                    }break;
+                case SET_PARAMETERS: {
+                     ParametersData *data = (ParametersData *)command->mParam;
+                     LOGV("AudioCommandThread() processing set parameters string %s, io %d", data->mKeyValuePairs.string(), data->mIO);
+                     command->mStatus = AudioSystem::setParameters(data->mIO, data->mKeyValuePairs);
+                     if (command->mWaitStatus) {
+                         command->mCond.signal();
+                         mWaitWorkCV.wait(mLock);
+                     }
+                     delete data;
+                     }break;
+                case SET_VOICE_VOLUME: {
+                    VoiceVolumeData *data = (VoiceVolumeData *)command->mParam;
+                    LOGV("AudioCommandThread() processing set voice volume volume %f", data->mVolume);
+                    command->mStatus = AudioSystem::setVoiceVolume(data->mVolume);
+                    if (command->mWaitStatus) {
+                        command->mCond.signal();
+                        mWaitWorkCV.wait(mLock);
+                    }
+                    delete data;
+                    }break;
+                default:
+                    LOGW("AudioCommandThread() unknown command %d", command->mCommand);
+                }
+                delete command;
+                waitTime = INT64_MAX;
+            } else {
+                waitTime = mAudioCommands[0]->mTime - curTime;
+                break;
+            }
+        }
+        LOGV("AudioCommandThread() going to sleep");
+        mWaitWorkCV.waitRelative(mLock, waitTime);
+        LOGV("AudioCommandThread() waking up");
+    }
+    mLock.unlock();
+    return false;
+}
+
+status_t AudioPolicyService::AudioCommandThread::dump(int fd)
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+
+    snprintf(buffer, SIZE, "AudioCommandThread %p Dump\n", this);
+    result.append(buffer);
+    write(fd, result.string(), result.size());
+
+    bool locked = tryLock(mLock);
+    if (!locked) {
+        String8 result2(kCmdDeadlockedString);
+        write(fd, result2.string(), result2.size());
+    }
+
+    snprintf(buffer, SIZE, "- Commands:\n");
+    result = String8(buffer);
+    result.append("   Command Time        Wait pParam\n");
+    for (int i = 0; i < (int)mAudioCommands.size(); i++) {
+        mAudioCommands[i]->dump(buffer, SIZE);
+        result.append(buffer);
+    }
+    result.append("  Last Command\n");
+    mLastCommand.dump(buffer, SIZE);
+    result.append(buffer);
+
+    write(fd, result.string(), result.size());
+
+    if (locked) mLock.unlock();
+
+    return NO_ERROR;
+}
+
+void AudioPolicyService::AudioCommandThread::startToneCommand(int type, int stream)
+{
+    AudioCommand *command = new AudioCommand();
+    command->mCommand = START_TONE;
+    ToneData *data = new ToneData();
+    data->mType = type;
+    data->mStream = stream;
+    command->mParam = (void *)data;
+    command->mWaitStatus = false;
+    Mutex::Autolock _l(mLock);
+    insertCommand_l(command);
+    LOGV("AudioCommandThread() adding tone start type %d, stream %d", type, stream);
+    mWaitWorkCV.signal();
+}
+
+void AudioPolicyService::AudioCommandThread::stopToneCommand()
+{
+    AudioCommand *command = new AudioCommand();
+    command->mCommand = STOP_TONE;
+    command->mParam = NULL;
+    command->mWaitStatus = false;
+    Mutex::Autolock _l(mLock);
+    insertCommand_l(command);
+    LOGV("AudioCommandThread() adding tone stop");
+    mWaitWorkCV.signal();
+}
+
+status_t AudioPolicyService::AudioCommandThread::volumeCommand(int stream, float volume, int output, int delayMs)
+{
+    status_t status = NO_ERROR;
+
+    AudioCommand *command = new AudioCommand();
+    command->mCommand = SET_VOLUME;
+    VolumeData *data = new VolumeData();
+    data->mStream = stream;
+    data->mVolume = volume;
+    data->mIO = output;
+    command->mParam = data;
+    if (delayMs == 0) {
+        command->mWaitStatus = true;
+    } else {
+        command->mWaitStatus = false;
+    }
+    Mutex::Autolock _l(mLock);
+    insertCommand_l(command, delayMs);
+    LOGV("AudioCommandThread() adding set volume stream %d, volume %f, output %d", stream, volume, output);
+    mWaitWorkCV.signal();
+    if (command->mWaitStatus) {
+        command->mCond.wait(mLock);
+        status =  command->mStatus;
+        mWaitWorkCV.signal();
+    }
+    return status;
+}
+
+status_t AudioPolicyService::AudioCommandThread::parametersCommand(int ioHandle, const String8& keyValuePairs, int delayMs)
+{
+    status_t status = NO_ERROR;
+
+    AudioCommand *command = new AudioCommand();
+    command->mCommand = SET_PARAMETERS;
+    ParametersData *data = new ParametersData();
+    data->mIO = ioHandle;
+    data->mKeyValuePairs = keyValuePairs;
+    command->mParam = data;
+    if (delayMs == 0) {
+        command->mWaitStatus = true;
+    } else {
+        command->mWaitStatus = false;
+    }
+    Mutex::Autolock _l(mLock);
+    insertCommand_l(command, delayMs);
+    LOGV("AudioCommandThread() adding set parameter string %s, io %d ,delay %d", keyValuePairs.string(), ioHandle, delayMs);
+    mWaitWorkCV.signal();
+    if (command->mWaitStatus) {
+        command->mCond.wait(mLock);
+        status =  command->mStatus;
+        mWaitWorkCV.signal();
+    }
+    return status;
+}
+
+status_t AudioPolicyService::AudioCommandThread::voiceVolumeCommand(float volume, int delayMs)
+{
+    status_t status = NO_ERROR;
+
+    AudioCommand *command = new AudioCommand();
+    command->mCommand = SET_VOICE_VOLUME;
+    VoiceVolumeData *data = new VoiceVolumeData();
+    data->mVolume = volume;
+    command->mParam = data;
+    if (delayMs == 0) {
+        command->mWaitStatus = true;
+    } else {
+        command->mWaitStatus = false;
+    }
+    Mutex::Autolock _l(mLock);
+    insertCommand_l(command, delayMs);
+    LOGV("AudioCommandThread() adding set voice volume volume %f", volume);
+    mWaitWorkCV.signal();
+    if (command->mWaitStatus) {
+        command->mCond.wait(mLock);
+        status =  command->mStatus;
+        mWaitWorkCV.signal();
+    }
+    return status;
+}
+
+// insertCommand_l() must be called with mLock held
+void AudioPolicyService::AudioCommandThread::insertCommand_l(AudioCommand *command, int delayMs)
+{
+    ssize_t i;
+    Vector <AudioCommand *> removedCommands;
+
+    command->mTime = systemTime() + milliseconds(delayMs);
+
+    // check same pending commands with later time stamps and eliminate them
+    for (i = mAudioCommands.size()-1; i >= 0; i--) {
+        AudioCommand *command2 = mAudioCommands[i];
+        // commands are sorted by increasing time stamp: no need to scan the rest of mAudioCommands
+        if (command2->mTime <= command->mTime) break;
+        if (command2->mCommand != command->mCommand) continue;
+
+        switch (command->mCommand) {
+        case SET_PARAMETERS: {
+            ParametersData *data = (ParametersData *)command->mParam;
+            ParametersData *data2 = (ParametersData *)command2->mParam;
+            if (data->mIO != data2->mIO) break;
+            LOGV("Comparing parameter command %s to new command %s", data2->mKeyValuePairs.string(), data->mKeyValuePairs.string());
+            AudioParameter param = AudioParameter(data->mKeyValuePairs);
+            AudioParameter param2 = AudioParameter(data2->mKeyValuePairs);
+            for (size_t j = 0; j < param.size(); j++) {
+               String8 key;
+               String8 value;
+               param.getAt(j, key, value);
+               for (size_t k = 0; k < param2.size(); k++) {
+                  String8 key2;
+                  String8 value2;
+                  param2.getAt(k, key2, value2);
+                  if (key2 == key) {
+                      param2.remove(key2);
+                      LOGV("Filtering out parameter %s", key2.string());
+                      break;
+                  }
+               }
+            }
+            // if all keys have been filtered out, remove the command.
+            // otherwise, update the key value pairs
+            if (param2.size() == 0) {
+                removedCommands.add(command2);
+            } else {
+                data2->mKeyValuePairs = param2.toString();
+            }
+        } break;
+
+        case SET_VOLUME: {
+            VolumeData *data = (VolumeData *)command->mParam;
+            VolumeData *data2 = (VolumeData *)command2->mParam;
+            if (data->mIO != data2->mIO) break;
+            if (data->mStream != data2->mStream) break;
+            LOGV("Filtering out volume command on output %d for stream %d", data->mIO, data->mStream);
+            removedCommands.add(command2);
+        } break;
+        case START_TONE:
+        case STOP_TONE:
+        default:
+            break;
+        }
+    }
+
+    // remove filtered commands
+    for (size_t j = 0; j < removedCommands.size(); j++) {
+        // removed commands always have time stamps greater than current command
+        for (size_t k = i + 1; k < mAudioCommands.size(); k++) {
+            if (mAudioCommands[k] == removedCommands[j]) {
+                LOGV("suppressing command: %d", mAudioCommands[k]->mCommand);
+                mAudioCommands.removeAt(k);
+                break;
+            }
+        }
+    }
+    removedCommands.clear();
+
+    // insert command at the right place according to its time stamp
+    LOGV("inserting command: %d at index %ld, num commands %d", command->mCommand, i+1, mAudioCommands.size());
+    mAudioCommands.insertAt(command, i + 1);
+}
+
+void AudioPolicyService::AudioCommandThread::exit()
+{
+    LOGV("AudioCommandThread::exit");
+    {
+        AutoMutex _l(mLock);
+        requestExit();
+        mWaitWorkCV.signal();
+    }
+    requestExitAndWait();
+}
+
+void AudioPolicyService::AudioCommandThread::AudioCommand::dump(char* buffer, size_t size)
+{
+    snprintf(buffer, size, "   %02d      %06d.%03d  %01u    %p\n",
+            mCommand,
+            (int)ns2s(mTime),
+            (int)ns2ms(mTime)%1000,
+            mWaitStatus,
+            mParam);
+}
+
+}; // namespace android
diff --git a/libs/audioflinger/AudioPolicyService.h b/libs/audioflinger/AudioPolicyService.h
new file mode 100644
index 0000000..b9234ec
--- /dev/null
+++ b/libs/audioflinger/AudioPolicyService.h
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_AUDIOPOLICYSERVICE_H
+#define ANDROID_AUDIOPOLICYSERVICE_H
+
+#include <media/IAudioPolicyService.h>
+#include <hardware_legacy/AudioPolicyInterface.h>
+#include <media/ToneGenerator.h>
+#include <utils/Vector.h>
+
+namespace android {
+
+class String8;
+
+// ----------------------------------------------------------------------------
+
+class AudioPolicyService: public BnAudioPolicyService, public AudioPolicyClientInterface, public IBinder::DeathRecipient
+{
+
+public:
+    static  void        instantiate();
+
+    virtual status_t    dump(int fd, const Vector<String16>& args);
+
+    //
+    // BnAudioPolicyService (see AudioPolicyInterface for method descriptions)
+    //
+
+    virtual status_t setDeviceConnectionState(AudioSystem::audio_devices device,
+                                              AudioSystem::device_connection_state state,
+                                              const char *device_address);
+    virtual AudioSystem::device_connection_state getDeviceConnectionState(AudioSystem::audio_devices device,
+                                                                          const char *device_address);
+    virtual status_t setPhoneState(int state);
+    virtual status_t setRingerMode(uint32_t mode, uint32_t mask);
+    virtual status_t setForceUse(AudioSystem::force_use usage, AudioSystem::forced_config config);
+    virtual AudioSystem::forced_config getForceUse(AudioSystem::force_use usage);
+    virtual audio_io_handle_t getOutput(AudioSystem::stream_type stream,
+                                        uint32_t samplingRate = 0,
+                                        uint32_t format = AudioSystem::FORMAT_DEFAULT,
+                                        uint32_t channels = 0,
+                                        AudioSystem::output_flags flags = AudioSystem::OUTPUT_FLAG_INDIRECT);
+    virtual status_t startOutput(audio_io_handle_t output, AudioSystem::stream_type stream);
+    virtual status_t stopOutput(audio_io_handle_t output, AudioSystem::stream_type stream);
+    virtual void releaseOutput(audio_io_handle_t output);
+    virtual audio_io_handle_t getInput(int inputSource,
+                                    uint32_t samplingRate = 0,
+                                    uint32_t format = AudioSystem::FORMAT_DEFAULT,
+                                    uint32_t channels = 0,
+                                    AudioSystem::audio_in_acoustics acoustics = (AudioSystem::audio_in_acoustics)0);
+    virtual status_t startInput(audio_io_handle_t input);
+    virtual status_t stopInput(audio_io_handle_t input);
+    virtual void releaseInput(audio_io_handle_t input);
+    virtual status_t initStreamVolume(AudioSystem::stream_type stream,
+                                      int indexMin,
+                                      int indexMax);
+    virtual status_t setStreamVolumeIndex(AudioSystem::stream_type stream, int index);
+    virtual status_t getStreamVolumeIndex(AudioSystem::stream_type stream, int *index);
+
+    virtual     status_t    onTransact(
+                                uint32_t code,
+                                const Parcel& data,
+                                Parcel* reply,
+                                uint32_t flags);
+
+    // IBinder::DeathRecipient
+    virtual     void        binderDied(const wp<IBinder>& who);
+
+    //
+    // AudioPolicyClientInterface
+    //
+    virtual audio_io_handle_t openOutput(uint32_t *pDevices,
+                                    uint32_t *pSamplingRate,
+                                    uint32_t *pFormat,
+                                    uint32_t *pChannels,
+                                    uint32_t *pLatencyMs,
+                                    AudioSystem::output_flags flags);
+    virtual audio_io_handle_t openDuplicateOutput(audio_io_handle_t output1, audio_io_handle_t output2);
+    virtual status_t closeOutput(audio_io_handle_t output);
+    virtual status_t suspendOutput(audio_io_handle_t output);
+    virtual status_t restoreOutput(audio_io_handle_t output);
+    virtual audio_io_handle_t openInput(uint32_t *pDevices,
+                                    uint32_t *pSamplingRate,
+                                    uint32_t *pFormat,
+                                    uint32_t *pChannels,
+                                    uint32_t acoustics);
+    virtual status_t closeInput(audio_io_handle_t input);
+    virtual status_t setStreamVolume(AudioSystem::stream_type stream, float volume, audio_io_handle_t output, int delayMs = 0);
+    virtual status_t setStreamOutput(AudioSystem::stream_type stream, audio_io_handle_t output);
+    virtual void setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs, int delayMs = 0);
+    virtual String8 getParameters(audio_io_handle_t ioHandle, const String8& keys);
+    virtual status_t startTone(ToneGenerator::tone_type tone, AudioSystem::stream_type stream);
+    virtual status_t stopTone();
+    virtual status_t setVoiceVolume(float volume, int delayMs = 0);
+
+private:
+                        AudioPolicyService();
+    virtual             ~AudioPolicyService();
+
+            status_t dumpInternals(int fd);
+
+    // Thread used for tone playback and to send audio config commands to audio flinger
+    // For tone playback, using a separate thread is necessary to avoid deadlock with mLock because startTone()
+    // and stopTone() are normally called with mLock locked and requesting a tone start or stop will cause
+    // calls to AudioPolicyService and an attempt to lock mLock.
+    // For audio config commands, it is necessary because audio flinger requires that the calling process (user)
+    // has permission to modify audio settings.
+    class AudioCommandThread : public Thread {
+        class AudioCommand;
+    public:
+
+        // commands for tone AudioCommand
+        enum {
+            START_TONE,
+            STOP_TONE,
+            SET_VOLUME,
+            SET_PARAMETERS,
+            SET_VOICE_VOLUME
+        };
+
+        AudioCommandThread ();
+        virtual             ~AudioCommandThread();
+
+                    status_t    dump(int fd);
+
+        // Thread virtuals
+        virtual     void        onFirstRef();
+        virtual     bool        threadLoop();
+
+                    void        exit();
+                    void        startToneCommand(int type = 0, int stream = 0);
+                    void        stopToneCommand();
+                    status_t    volumeCommand(int stream, float volume, int output, int delayMs = 0);
+                    status_t    parametersCommand(int ioHandle, const String8& keyValuePairs, int delayMs = 0);
+                    status_t    voiceVolumeCommand(float volume, int delayMs = 0);
+                    void        insertCommand_l(AudioCommand *command, int delayMs = 0);
+
+    private:
+        // descriptor for requested tone playback event
+        class AudioCommand {
+
+        public:
+            AudioCommand()
+            : mCommand(-1) {}
+
+            void dump(char* buffer, size_t size);
+
+            int mCommand;   // START_TONE, STOP_TONE ...
+            nsecs_t mTime;  // time stamp
+            Condition mCond; // condition for status return
+            status_t mStatus; // command status
+            bool mWaitStatus; // true if caller is waiting for status
+            void *mParam;     // command parameter (ToneData, VolumeData, ParametersData)
+        };
+
+        class ToneData {
+        public:
+            int mType;      // tone type (START_TONE only)
+            int mStream;    // stream type (START_TONE only)
+        };
+
+        class VolumeData {
+        public:
+            int mStream;
+            float mVolume;
+            int mIO;
+        };
+
+        class ParametersData {
+        public:
+            int mIO;
+            String8 mKeyValuePairs;
+        };
+
+        class VoiceVolumeData {
+        public:
+            float mVolume;
+        };
+
+        Mutex   mLock;
+        Condition mWaitWorkCV;
+        Vector <AudioCommand *> mAudioCommands; // list of pending commands
+        ToneGenerator *mpToneGenerator;     // the tone generator
+        AudioCommand mLastCommand;
+    };
+
+    // Internal dump utilities.
+    status_t dumpPermissionDenial(int fd);
+
+
+    Mutex   mLock;      // prevents concurrent access to AudioPolicy manager functions changing device
+                        // connection stated our routing
+    AudioPolicyInterface* mpPolicyManager;          // the platform specific policy manager
+    sp <AudioCommandThread> mAudioCommandThread;    // audio commands thread
+    sp <AudioCommandThread> mTonePlaybackThread;     // tone playback thread
+};
+
+}; // namespace android
+
+#endif // ANDROID_AUDIOPOLICYSERVICE_H
+
+
+
+
+
+
+
+
diff --git a/libs/binder/Android.mk b/libs/binder/Android.mk
new file mode 100644
index 0000000..2df6775
--- /dev/null
+++ b/libs/binder/Android.mk
@@ -0,0 +1,45 @@
+# Copyright (C) 2009 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.
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+# we have the common sources, plus some device-specific stuff
+LOCAL_SRC_FILES:= \
+	Binder.cpp \
+	BpBinder.cpp \
+	IInterface.cpp \
+	IMemory.cpp \
+	IPCThreadState.cpp \
+	IPermissionController.cpp \
+	IServiceManager.cpp \
+	MemoryDealer.cpp \
+    MemoryBase.cpp \
+    MemoryHeapBase.cpp \
+    MemoryHeapPmem.cpp \
+	Parcel.cpp \
+	Permission.cpp \
+	ProcessState.cpp \
+	Static.cpp
+
+LOCAL_LDLIBS += -lpthread
+
+LOCAL_SHARED_LIBRARIES := \
+	liblog \
+	libcutils \
+	libutils
+
+LOCAL_MODULE:= libbinder
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/libs/utils/Binder.cpp b/libs/binder/Binder.cpp
similarity index 92%
rename from libs/utils/Binder.cpp
rename to libs/binder/Binder.cpp
index 37e4685..0dd7622 100644
--- a/libs/utils/Binder.cpp
+++ b/libs/binder/Binder.cpp
@@ -14,12 +14,12 @@
  * limitations under the License.
  */
 
-#include <utils/Binder.h>
+#include <binder/Binder.h>
 
 #include <utils/Atomic.h>
-#include <utils/BpBinder.h>
-#include <utils/IInterface.h>
-#include <utils/Parcel.h>
+#include <binder/BpBinder.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
 
 #include <stdio.h>
 
@@ -27,6 +27,17 @@
 
 // ---------------------------------------------------------------------------
 
+IBinder::IBinder()
+    : RefBase()
+{
+}
+
+IBinder::~IBinder()
+{
+}
+
+// ---------------------------------------------------------------------------
+
 sp<IInterface>  IBinder::queryLocalInterface(const String16& descriptor)
 {
     return NULL;
@@ -58,6 +69,8 @@
 
 // ---------------------------------------------------------------------------
 
+String16 BBinder::sEmptyDescriptor;
+
 BBinder::BBinder()
     : mExtras(NULL)
 {
@@ -73,10 +86,10 @@
     return NO_ERROR;
 }
 
-String16 BBinder::getInterfaceDescriptor() const
+const String16& BBinder::getInterfaceDescriptor() const
 {
     LOGW("reached BBinder::getInterfaceDescriptor (this=%p)", this);
-    return String16();
+    return sEmptyDescriptor;
 }
 
 status_t BBinder::transact(
diff --git a/libs/utils/BpBinder.cpp b/libs/binder/BpBinder.cpp
similarity index 89%
rename from libs/utils/BpBinder.cpp
rename to libs/binder/BpBinder.cpp
index 69ab195..5de87ec 100644
--- a/libs/utils/BpBinder.cpp
+++ b/libs/binder/BpBinder.cpp
@@ -17,9 +17,9 @@
 #define LOG_TAG "BpBinder"
 //#define LOG_NDEBUG 0
 
-#include <utils/BpBinder.h>
+#include <binder/BpBinder.h>
 
-#include <utils/IPCThreadState.h>
+#include <binder/IPCThreadState.h>
 #include <utils/Log.h>
 
 #include <stdio.h>
@@ -98,16 +98,33 @@
     IPCThreadState::self()->incWeakHandle(handle);
 }
 
-String16 BpBinder::getInterfaceDescriptor() const
+bool BpBinder::isDescriptorCached() const {
+    Mutex::Autolock _l(mLock);
+    return mDescriptorCache.size() ? true : false;
+}
+
+const String16& BpBinder::getInterfaceDescriptor() const
 {
-    String16 res;
-    Parcel send, reply;
-    status_t err = const_cast<BpBinder*>(this)->transact(
-            INTERFACE_TRANSACTION, send, &reply);
-    if (err == NO_ERROR) {
-        res = reply.readString16();
+    if (isDescriptorCached() == false) {
+        Parcel send, reply;
+        // do the IPC without a lock held.
+        status_t err = const_cast<BpBinder*>(this)->transact(
+                INTERFACE_TRANSACTION, send, &reply);
+        if (err == NO_ERROR) {
+            String16 res(reply.readString16());
+            Mutex::Autolock _l(mLock);
+            // mDescriptorCache could have been assigned while the lock was
+            // released.
+            if (mDescriptorCache.size() == 0)
+                mDescriptorCache = res;
+        }
     }
-    return res;
+    
+    // we're returning a reference to a non-static object here. Usually this
+    // is not something smart to do, however, with binder objects it is 
+    // (usually) safe because they are reference-counted.
+    
+    return mDescriptorCache;
 }
 
 bool BpBinder::isBinderAlive() const
diff --git a/libs/utils/IInterface.cpp b/libs/binder/IInterface.cpp
similarity index 90%
rename from libs/utils/IInterface.cpp
rename to libs/binder/IInterface.cpp
index 6ea8178..29acf5d 100644
--- a/libs/utils/IInterface.cpp
+++ b/libs/binder/IInterface.cpp
@@ -14,12 +14,19 @@
  * limitations under the License.
  */
 
-#include <utils/IInterface.h>
+#include <binder/IInterface.h>
 
 namespace android {
 
 // ---------------------------------------------------------------------------
 
+IInterface::IInterface() 
+    : RefBase() {
+}
+
+IInterface::~IInterface() {
+}
+
 sp<IBinder> IInterface::asBinder()
 {
     return this ? onAsBinder() : NULL;
diff --git a/libs/utils/IMemory.cpp b/libs/binder/IMemory.cpp
similarity index 96%
rename from libs/utils/IMemory.cpp
rename to libs/binder/IMemory.cpp
index 429bc2b..6c1d225 100644
--- a/libs/utils/IMemory.cpp
+++ b/libs/binder/IMemory.cpp
@@ -25,11 +25,11 @@
 #include <sys/types.h>
 #include <sys/mman.h>
 
-#include <utils/IMemory.h>
+#include <binder/IMemory.h>
 #include <utils/KeyedVector.h>
 #include <utils/threads.h>
 #include <utils/Atomic.h>
-#include <utils/Parcel.h>
+#include <binder/Parcel.h>
 #include <utils/CallStack.h>
 
 #define VERBOSE   0
@@ -205,11 +205,11 @@
 
 IMPLEMENT_META_INTERFACE(Memory, "android.utils.IMemory");
 
-#define CHECK_INTERFACE(interface, data, reply) \
-        do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \
-            LOGW("Call incorrectly routed to " #interface); \
-            return PERMISSION_DENIED; \
-        } } while (0)
+BnMemory::BnMemory() {
+}
+
+BnMemory::~BnMemory() { 
+}
 
 status_t BnMemory::onTransact(
     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
@@ -299,11 +299,11 @@
         ssize_t size = reply.readInt32();
         uint32_t flags = reply.readInt32();
 
-        LOGE_IF(err, "binder=%p transaction failed fd=%d, size=%d, err=%d (%s)",
+        LOGE_IF(err, "binder=%p transaction failed fd=%d, size=%ld, err=%d (%s)",
                 asBinder().get(), parcel_fd, size, err, strerror(-err));
 
         int fd = dup( parcel_fd );
-        LOGE_IF(fd==-1, "cannot dup fd=%d, size=%d, err=%d (%s)",
+        LOGE_IF(fd==-1, "cannot dup fd=%d, size=%ld, err=%d (%s)",
                 parcel_fd, size, err, strerror(errno));
 
         int access = PROT_READ;
@@ -316,7 +316,7 @@
             mRealHeap = true;
             mBase = mmap(0, size, access, MAP_SHARED, fd, 0);
             if (mBase == MAP_FAILED) {
-                LOGE("cannot map BpMemoryHeap (binder=%p), size=%d, fd=%d (%s)",
+                LOGE("cannot map BpMemoryHeap (binder=%p), size=%ld, fd=%d (%s)",
                         asBinder().get(), size, fd, strerror(errno));
                 close(fd);
             } else {
@@ -357,8 +357,14 @@
 
 IMPLEMENT_META_INTERFACE(MemoryHeap, "android.utils.IMemoryHeap");
 
+BnMemoryHeap::BnMemoryHeap() { 
+}
+
+BnMemoryHeap::~BnMemoryHeap() { 
+}
+
 status_t BnMemoryHeap::onTransact(
-    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
 {
     switch(code) {
        case HEAP_ID: {
diff --git a/libs/utils/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
similarity index 96%
rename from libs/utils/IPCThreadState.cpp
rename to libs/binder/IPCThreadState.cpp
index 04ae142..b2a7db8 100644
--- a/libs/utils/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -14,17 +14,20 @@
  * limitations under the License.
  */
 
-#include <utils/IPCThreadState.h>
+#define LOG_TAG "IPCThreadState"
 
-#include <utils/Binder.h>
-#include <utils/BpBinder.h>
+#include <binder/IPCThreadState.h>
+
+#include <binder/Binder.h>
+#include <binder/BpBinder.h>
+#include <cutils/sched_policy.h>
 #include <utils/Debug.h>
 #include <utils/Log.h>
 #include <utils/TextOutput.h>
 #include <utils/threads.h>
 
-#include <private/utils/binder_module.h>
-#include <private/utils/Static.h>
+#include <private/binder/binder_module.h>
+#include <private/binder/Static.h>
 
 #include <sys/ioctl.h>
 #include <signal.h>
@@ -366,13 +369,8 @@
 
 void IPCThreadState::clearCaller()
 {
-    if (mProcess->supportsProcesses()) {
-        mCallingPid = getpid();
-        mCallingUid = getuid();
-    } else {
-        mCallingPid = -1;
-        mCallingUid = -1;
-    }
+    mCallingPid = getpid();
+    mCallingUid = getuid();
 }
 
 void IPCThreadState::flushCommands()
@@ -423,9 +421,26 @@
                 alog << "Processing top-level Command: "
                     << getReturnString(cmd) << endl;
             }
+
+
             result = executeCommand(cmd);
         }
         
+        // After executing the command, ensure that the thread is returned to the
+        // default cgroup and priority before rejoining the pool.  This is a failsafe
+        // in case the command implementation failed to properly restore the thread's
+        // scheduling parameters upon completion.
+        int my_id;
+#ifdef HAVE_GETTID
+        my_id = gettid();
+#else
+        my_id = getpid();
+#endif
+        if (!set_sched_policy(my_id, SP_FOREGROUND)) {
+            // success; reset the priority as well
+            setpriority(PRIO_PROCESS, my_id, ANDROID_PRIORITY_NORMAL);
+        }
+
         // Let this thread exit the thread pool if it is no longer
         // needed and it is not the main process thread.
         if(result == TIMED_OUT && !isMain) {
diff --git a/libs/utils/IPermissionController.cpp b/libs/binder/IPermissionController.cpp
similarity index 87%
rename from libs/utils/IPermissionController.cpp
rename to libs/binder/IPermissionController.cpp
index f01d38f..bff4c9b 100644
--- a/libs/utils/IPermissionController.cpp
+++ b/libs/binder/IPermissionController.cpp
@@ -16,14 +16,14 @@
 
 #define LOG_TAG "PermissionController"
 
-#include <utils/IPermissionController.h>
+#include <binder/IPermissionController.h>
 
 #include <utils/Debug.h>
 #include <utils/Log.h>
-#include <utils/Parcel.h>
+#include <binder/Parcel.h>
 #include <utils/String8.h>
 
-#include <private/utils/Static.h>
+#include <private/binder/Static.h>
 
 namespace android {
 
@@ -55,12 +55,6 @@
 
 // ----------------------------------------------------------------------
 
-#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 BnPermissionController::onTransact(
     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
 {
diff --git a/libs/utils/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
similarity index 93%
rename from libs/utils/IServiceManager.cpp
rename to libs/binder/IServiceManager.cpp
index 9beeadd..0cf4158 100644
--- a/libs/utils/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -16,16 +16,16 @@
 
 #define LOG_TAG "ServiceManager"
 
-#include <utils/IServiceManager.h>
+#include <binder/IServiceManager.h>
 
 #include <utils/Debug.h>
-#include <utils/IPCThreadState.h>
 #include <utils/Log.h>
-#include <utils/Parcel.h>
+#include <binder/IPCThreadState.h>
+#include <binder/Parcel.h>
 #include <utils/String8.h>
 #include <utils/SystemClock.h>
 
-#include <private/utils/Static.h>
+#include <private/binder/Static.h>
 
 #include <unistd.h>
 
@@ -53,14 +53,19 @@
 
 static String16 _permission("permission");
 
+
 bool checkCallingPermission(const String16& permission, int32_t* outPid, int32_t* outUid)
 {
     IPCThreadState* ipcState = IPCThreadState::self();
-    int32_t pid = ipcState->getCallingPid();
-    int32_t uid = ipcState->getCallingUid();
+    pid_t pid = ipcState->getCallingPid();
+    uid_t uid = ipcState->getCallingUid();
     if (outPid) *outPid = pid;
-    if (outUid) *outUid= uid;
-    
+    if (outUid) *outUid = uid;
+    return checkPermission(permission, pid, uid);
+}
+
+bool checkPermission(const String16& permission, pid_t pid, uid_t uid)
+{
     sp<IPermissionController> pc;
     gDefaultServiceManagerLock.lock();
     pc = gPermissionController;
@@ -178,12 +183,6 @@
 
 // ----------------------------------------------------------------------
 
-#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 BnServiceManager::onTransact(
     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
 {
diff --git a/libs/utils/MemoryBase.cpp b/libs/binder/MemoryBase.cpp
similarity index 97%
rename from libs/utils/MemoryBase.cpp
rename to libs/binder/MemoryBase.cpp
index f25e11c..033066b 100644
--- a/libs/utils/MemoryBase.cpp
+++ b/libs/binder/MemoryBase.cpp
@@ -18,7 +18,7 @@
 #include <stdlib.h>
 #include <stdint.h>
 
-#include <utils/MemoryBase.h>
+#include <binder/MemoryBase.h>
 
 
 namespace android {
diff --git a/libs/utils/MemoryDealer.cpp b/libs/binder/MemoryDealer.cpp
similarity index 94%
rename from libs/utils/MemoryDealer.cpp
rename to libs/binder/MemoryDealer.cpp
index cf8201b..d5ffe7f 100644
--- a/libs/utils/MemoryDealer.cpp
+++ b/libs/binder/MemoryDealer.cpp
@@ -16,13 +16,13 @@
 
 #define LOG_TAG "MemoryDealer"
 
-#include <utils/MemoryDealer.h>
+#include <binder/MemoryDealer.h>
 
 #include <utils/Log.h>
-#include <utils/IPCThreadState.h>
+#include <binder/IPCThreadState.h>
 #include <utils/SortedVector.h>
 #include <utils/String8.h>
-#include <utils/MemoryBase.h>
+#include <binder/MemoryBase.h>
 
 #include <stdint.h>
 #include <stdio.h>
@@ -38,7 +38,15 @@
 #include <sys/file.h>
 
 namespace android {
+// ----------------------------------------------------------------------------
 
+HeapInterface::HeapInterface() { }
+HeapInterface::~HeapInterface() { }
+
+// ----------------------------------------------------------------------------
+
+AllocatorInterface::AllocatorInterface() { }
+AllocatorInterface::~AllocatorInterface() { }
 
 // ----------------------------------------------------------------------------
 
@@ -107,7 +115,7 @@
         if (new_memory != 0) {
             memory = new Allocation(this, offset, size, new_memory);
         } else {
-            LOGE("couldn't map [%8x, %d]", offset, size);
+            LOGE("couldn't map [%8lx, %u]", offset, size);
             if (size) {
                 /* NOTE: it's VERY important to not free allocations of size 0
                  * because they're special as they don't have any record in the 
@@ -339,6 +347,10 @@
         
 // ----------------------------------------------------------------------------
 
+SharedHeap::SharedHeap() 
+    : HeapInterface(), MemoryHeapBase() 
+{ 
+}
 
 SharedHeap::SharedHeap(size_t size, uint32_t flags, char const * name)
     : MemoryHeapBase(size, flags, name)
diff --git a/libs/utils/MemoryHeapBase.cpp b/libs/binder/MemoryHeapBase.cpp
similarity index 92%
rename from libs/utils/MemoryHeapBase.cpp
rename to libs/binder/MemoryHeapBase.cpp
index 8251728..624f7eb 100644
--- a/libs/utils/MemoryHeapBase.cpp
+++ b/libs/binder/MemoryHeapBase.cpp
@@ -29,7 +29,7 @@
 #include <cutils/ashmem.h>
 #include <cutils/atomic.h>
 
-#include <utils/MemoryHeapBase.h>
+#include <binder/MemoryHeapBase.h>
 
 #if HAVE_ANDROID_OS
 #include <linux/android_pmem.h>
@@ -67,7 +67,11 @@
     : mFD(-1), mSize(0), mBase(MAP_FAILED), mFlags(flags),
       mDevice(0), mNeedUnmap(false)
 {
-    int fd = open(device, O_RDWR);
+    int open_flags = O_RDWR;
+    if (flags & NO_CACHING)
+        open_flags |= O_SYNC;
+
+    int fd = open(device, open_flags);
     LOGE_IF(fd<0, "error opening %s: %s", device, strerror(errno));
     if (fd >= 0) {
         const size_t pagesize = getpagesize();
@@ -78,13 +82,13 @@
     }
 }
 
-MemoryHeapBase::MemoryHeapBase(int fd, size_t size, uint32_t flags)
+MemoryHeapBase::MemoryHeapBase(int fd, size_t size, uint32_t flags, uint32_t offset)
     : mFD(-1), mSize(0), mBase(MAP_FAILED), mFlags(flags),
       mDevice(0), mNeedUnmap(false)
 {
     const size_t pagesize = getpagesize();
     size = ((size + pagesize-1) & ~(pagesize-1));
-    mapfd(dup(fd), size);
+    mapfd(dup(fd), size, offset);
 }
 
 status_t MemoryHeapBase::init(int fd, void *base, int size, int flags, const char* device)
@@ -100,7 +104,7 @@
     return NO_ERROR;
 }
 
-status_t MemoryHeapBase::mapfd(int fd, size_t size)
+status_t MemoryHeapBase::mapfd(int fd, size_t size, uint32_t offset)
 {
     if (size == 0) {
         // try to figure out the size automatically
@@ -121,7 +125,7 @@
 
     if ((mFlags & DONT_MAP_LOCALLY) == 0) {
         void* base = (uint8_t*)mmap(0, size,
-                PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+                PROT_READ|PROT_WRITE, MAP_SHARED, fd, offset);
         if (base == MAP_FAILED) {
             LOGE("mmap(fd=%d, size=%u) failed (%s)",
                     fd, uint32_t(size), strerror(errno));
diff --git a/libs/utils/MemoryHeapPmem.cpp b/libs/binder/MemoryHeapPmem.cpp
similarity index 97%
rename from libs/utils/MemoryHeapPmem.cpp
rename to libs/binder/MemoryHeapPmem.cpp
index eba2b30..c660947 100644
--- a/libs/utils/MemoryHeapPmem.cpp
+++ b/libs/binder/MemoryHeapPmem.cpp
@@ -27,8 +27,8 @@
 
 #include <cutils/log.h>
 
-#include <utils/MemoryHeapPmem.h>
-#include <utils/MemoryHeapBase.h>
+#include <binder/MemoryHeapPmem.h>
+#include <binder/MemoryHeapBase.h>
 
 #if HAVE_ANDROID_OS
 #include <linux/android_pmem.h>
@@ -108,7 +108,7 @@
     // promote() it.
     
 #if HAVE_ANDROID_OS
-    if (mSize != NULL) {
+    if (mSize != 0) {
         const sp<MemoryHeapPmem>& heap(getHeap());
         int our_fd = heap->heapID();
         struct pmem_region sub;
@@ -132,7 +132,7 @@
     char const * const device = pmemHeap->getDevice();
 #if HAVE_ANDROID_OS
     if (device) {
-        int fd = open(device, O_RDWR);
+        int fd = open(device, O_RDWR | (flags & NO_CACHING ? O_SYNC : 0));
         LOGE_IF(fd<0, "couldn't open %s (%s)", device, strerror(errno));
         if (fd >= 0) {
             int err = ioctl(fd, PMEM_CONNECT, pmemHeap->heapID());
diff --git a/libs/utils/Parcel.cpp b/libs/binder/Parcel.cpp
similarity index 91%
rename from libs/utils/Parcel.cpp
rename to libs/binder/Parcel.cpp
index b0e3750..e397bce 100644
--- a/libs/utils/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -17,19 +17,19 @@
 #define LOG_TAG "Parcel"
 //#define LOG_NDEBUG 0
 
-#include <utils/Parcel.h>
+#include <binder/Parcel.h>
 
-#include <utils/Binder.h>
-#include <utils/BpBinder.h>
+#include <binder/Binder.h>
+#include <binder/BpBinder.h>
 #include <utils/Debug.h>
-#include <utils/ProcessState.h>
+#include <binder/ProcessState.h>
 #include <utils/Log.h>
 #include <utils/String8.h>
 #include <utils/String16.h>
 #include <utils/TextOutput.h>
 #include <utils/misc.h>
 
-#include <private/utils/binder_module.h>
+#include <private/binder/binder_module.h>
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -441,9 +441,14 @@
     return writeString16(interface);
 }
 
+bool Parcel::checkInterface(IBinder* binder) const
+{
+    return enforceInterface(binder->getInterfaceDescriptor()); 
+}
+
 bool Parcel::enforceInterface(const String16& interface) const
 {
-    String16 str = readString16();
+    const String16 str(readString16());
     if (str == interface) {
         return true;
     } else {
@@ -557,54 +562,27 @@
 
 status_t Parcel::writeInt32(int32_t val)
 {
-    if ((mDataPos+sizeof(val)) <= mDataCapacity) {
-restart_write:
-        *reinterpret_cast<int32_t*>(mData+mDataPos) = val;
-        return finishWrite(sizeof(val));
-    }
-
-    status_t err = growData(sizeof(val));
-    if (err == NO_ERROR) goto restart_write;
-    return err;
+    return writeAligned(val);
 }
 
 status_t Parcel::writeInt64(int64_t val)
 {
-    if ((mDataPos+sizeof(val)) <= mDataCapacity) {
-restart_write:
-        *reinterpret_cast<int64_t*>(mData+mDataPos) = val;
-        return finishWrite(sizeof(val));
-    }
-
-    status_t err = growData(sizeof(val));
-    if (err == NO_ERROR) goto restart_write;
-    return err;
+    return writeAligned(val);
 }
 
 status_t Parcel::writeFloat(float val)
 {
-    if ((mDataPos+sizeof(val)) <= mDataCapacity) {
-restart_write:
-        *reinterpret_cast<float*>(mData+mDataPos) = val;
-        return finishWrite(sizeof(val));
-    }
-
-    status_t err = growData(sizeof(val));
-    if (err == NO_ERROR) goto restart_write;
-    return err;
+    return writeAligned(val);
 }
 
 status_t Parcel::writeDouble(double val)
 {
-    if ((mDataPos+sizeof(val)) <= mDataCapacity) {
-restart_write:
-        *reinterpret_cast<double*>(mData+mDataPos) = val;
-        return finishWrite(sizeof(val));
-    }
+    return writeAligned(val);
+}
 
-    status_t err = growData(sizeof(val));
-    if (err == NO_ERROR) goto restart_write;
-    return err;
+status_t Parcel::writeIntPtr(intptr_t val)
+{
+    return writeAligned(val);
 }
 
 status_t Parcel::writeCString(const char* str)
@@ -656,7 +634,7 @@
 
 status_t Parcel::writeNativeHandle(const native_handle* handle)
 {
-    if (handle->version != sizeof(native_handle))
+    if (!handle || handle->version != sizeof(native_handle))
         return BAD_TYPE;
 
     status_t err;
@@ -763,103 +741,98 @@
     return NULL;
 }
 
-status_t Parcel::readInt32(int32_t *pArg) const
-{
-    if ((mDataPos+sizeof(int32_t)) <= mDataSize) {
+template<class T>
+status_t Parcel::readAligned(T *pArg) const {
+    COMPILE_TIME_ASSERT_FUNCTION_SCOPE(PAD_SIZE(sizeof(T)) == sizeof(T));
+
+    if ((mDataPos+sizeof(T)) <= mDataSize) {
         const void* data = mData+mDataPos;
-        mDataPos += sizeof(int32_t);
-        *pArg =  *reinterpret_cast<const int32_t*>(data);
+        mDataPos += sizeof(T);
+        *pArg =  *reinterpret_cast<const T*>(data);
         return NO_ERROR;
     } else {
         return NOT_ENOUGH_DATA;
     }
 }
 
+template<class T>
+T Parcel::readAligned() const {
+    T result;
+    if (readAligned(&result) != NO_ERROR) {
+        result = 0;
+    }
+
+    return result;
+}
+
+template<class T>
+status_t Parcel::writeAligned(T val) {
+    COMPILE_TIME_ASSERT_FUNCTION_SCOPE(PAD_SIZE(sizeof(T)) == sizeof(T));
+
+    if ((mDataPos+sizeof(val)) <= mDataCapacity) {
+restart_write:
+        *reinterpret_cast<T*>(mData+mDataPos) = val;
+        return finishWrite(sizeof(val));
+    }
+
+    status_t err = growData(sizeof(val));
+    if (err == NO_ERROR) goto restart_write;
+    return err;
+}
+
+status_t Parcel::readInt32(int32_t *pArg) const
+{
+    return readAligned(pArg);
+}
+
 int32_t Parcel::readInt32() const
 {
-    if ((mDataPos+sizeof(int32_t)) <= mDataSize) {
-        const void* data = mData+mDataPos;
-        mDataPos += sizeof(int32_t);
-        LOGV("readInt32 Setting data pos of %p to %d\n", this, mDataPos);
-        return *reinterpret_cast<const int32_t*>(data);
-    }
-    return 0;
+    return readAligned<int32_t>();
 }
 
 
 status_t Parcel::readInt64(int64_t *pArg) const
 {
-    if ((mDataPos+sizeof(int64_t)) <= mDataSize) {
-        const void* data = mData+mDataPos;
-        mDataPos += sizeof(int64_t);
-        *pArg = *reinterpret_cast<const int64_t*>(data);
-        LOGV("readInt64 Setting data pos of %p to %d\n", this, mDataPos);
-        return NO_ERROR;
-    } else {
-        return NOT_ENOUGH_DATA;
-    }
+    return readAligned(pArg);
 }
 
 
 int64_t Parcel::readInt64() const
 {
-    if ((mDataPos+sizeof(int64_t)) <= mDataSize) {
-        const void* data = mData+mDataPos;
-        mDataPos += sizeof(int64_t);
-        LOGV("readInt64 Setting data pos of %p to %d\n", this, mDataPos);
-        return *reinterpret_cast<const int64_t*>(data);
-    }
-    return 0;
+    return readAligned<int64_t>();
 }
 
 status_t Parcel::readFloat(float *pArg) const
 {
-    if ((mDataPos+sizeof(float)) <= mDataSize) {
-        const void* data = mData+mDataPos;
-        mDataPos += sizeof(float);
-        LOGV("readFloat Setting data pos of %p to %d\n", this, mDataPos);
-        *pArg = *reinterpret_cast<const float*>(data);
-        return NO_ERROR;
-    } else {
-        return NOT_ENOUGH_DATA;
-    }
+    return readAligned(pArg);
 }
 
 
 float Parcel::readFloat() const
 {
-    if ((mDataPos+sizeof(float)) <= mDataSize) {
-        const void* data = mData+mDataPos;
-        mDataPos += sizeof(float);
-        LOGV("readFloat Setting data pos of %p to %d\n", this, mDataPos);
-        return *reinterpret_cast<const float*>(data);
-    }
-    return 0;
+    return readAligned<float>();
 }
 
 status_t Parcel::readDouble(double *pArg) const
 {
-    if ((mDataPos+sizeof(double)) <= mDataSize) {
-        const void* data = mData+mDataPos;
-        mDataPos += sizeof(double);
-        LOGV("readDouble Setting data pos of %p to %d\n", this, mDataPos);
-        *pArg = *reinterpret_cast<const double*>(data);
-        return NO_ERROR;
-    } else {
-        return NOT_ENOUGH_DATA;
-    }
+    return readAligned(pArg);
 }
 
 
 double Parcel::readDouble() const
 {
-    if ((mDataPos+sizeof(double)) <= mDataSize) {
-        const void* data = mData+mDataPos;
-        mDataPos += sizeof(double);
-        LOGV("readDouble Setting data pos of %p to %d\n", this, mDataPos);
-        return *reinterpret_cast<const double*>(data);
-    }
-    return 0;
+    return readAligned<double>();
+}
+
+status_t Parcel::readIntPtr(intptr_t *pArg) const
+{
+    return readAligned(pArg);
+}
+
+
+intptr_t Parcel::readIntPtr() const
+{
+    return readAligned<intptr_t>();
 }
 
 
diff --git a/libs/binder/Permission.cpp b/libs/binder/Permission.cpp
new file mode 100644
index 0000000..fd8fe69
--- /dev/null
+++ b/libs/binder/Permission.cpp
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2009 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 <utils/Log.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/Permission.h>
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+Permission::Permission(char const* name)
+    : mPermissionName(name), mPid(getpid())
+{
+}
+
+Permission::Permission(const String16& name)
+    : mPermissionName(name), mPid(getpid())
+{
+}
+
+Permission::Permission(const Permission& rhs)
+    : mPermissionName(rhs.mPermissionName),
+    mGranted(rhs.mGranted),
+    mPid(rhs.mPid)
+{
+}
+
+Permission::~Permission()
+{
+}
+
+bool Permission::operator < (const Permission& rhs) const
+{
+    return mPermissionName < rhs.mPermissionName;
+}
+
+bool Permission::checkCalling() const
+{
+    IPCThreadState* ipcState = IPCThreadState::self();
+    pid_t pid = ipcState->getCallingPid();
+    uid_t uid = ipcState->getCallingUid();
+    return doCheckPermission(pid, uid);
+}
+
+bool Permission::check(pid_t pid, uid_t uid) const
+{
+    return doCheckPermission(pid, uid);
+}
+
+bool Permission::doCheckPermission(pid_t pid, uid_t uid) const
+{
+    if ((uid == 0) || (pid == mPid)) {
+        // root and ourselves is always okay
+        return true;
+    } else {
+        // see if we already granted this permission for this uid
+        Mutex::Autolock _l(mLock);
+        if (mGranted.indexOf(uid) >= 0)
+            return true;
+    }
+
+    bool granted = checkPermission(mPermissionName, pid, uid);
+    if (granted) {
+        Mutex::Autolock _l(mLock);
+        // no need to check again, the old item will be replaced if it is
+        // already there.
+        mGranted.add(uid);
+    }
+    return granted;
+}
+
+// ---------------------------------------------------------------------------
+}; // namespace android
diff --git a/libs/utils/ProcessState.cpp b/libs/binder/ProcessState.cpp
similarity index 97%
rename from libs/utils/ProcessState.cpp
rename to libs/binder/ProcessState.cpp
index 4567df6..d7daf73 100644
--- a/libs/utils/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -18,19 +18,19 @@
 
 #include <cutils/process_name.h>
 
-#include <utils/ProcessState.h>
+#include <binder/ProcessState.h>
 
 #include <utils/Atomic.h>
-#include <utils/BpBinder.h>
-#include <utils/IPCThreadState.h>
+#include <binder/BpBinder.h>
+#include <binder/IPCThreadState.h>
 #include <utils/Log.h>
 #include <utils/String8.h>
-#include <utils/IServiceManager.h>
+#include <binder/IServiceManager.h>
 #include <utils/String8.h>
 #include <utils/threads.h>
 
-#include <private/utils/binder_module.h>
-#include <private/utils/Static.h>
+#include <private/binder/binder_module.h>
+#include <private/binder/Static.h>
 
 #include <errno.h>
 #include <fcntl.h>
diff --git a/libs/binder/Static.cpp b/libs/binder/Static.cpp
new file mode 100644
index 0000000..12b0308
--- /dev/null
+++ b/libs/binder/Static.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.
+ */
+
+// All static variables go here, to control initialization and
+// destruction order in the library.
+
+#include <private/binder/Static.h>
+
+#include <binder/IPCThreadState.h>
+#include <utils/Log.h>
+
+namespace android {
+
+// ------------ ProcessState.cpp
+
+Mutex gProcessMutex;
+sp<ProcessState> gProcess;
+
+class LibUtilsIPCtStatics
+{
+public:
+    LibUtilsIPCtStatics()
+    {
+    }
+    
+    ~LibUtilsIPCtStatics()
+    {
+        IPCThreadState::shutdown();
+    }
+};
+
+static LibUtilsIPCtStatics gIPCStatics;
+
+// ------------ ServiceManager.cpp
+
+Mutex gDefaultServiceManagerLock;
+sp<IServiceManager> gDefaultServiceManager;
+sp<IPermissionController> gPermissionController;
+
+}   // namespace android
diff --git a/libs/surfaceflinger/Android.mk b/libs/surfaceflinger/Android.mk
index ec5aa3f..eb51c22 100644
--- a/libs/surfaceflinger/Android.mk
+++ b/libs/surfaceflinger/Android.mk
@@ -5,44 +5,50 @@
     clz.cpp.arm \
     DisplayHardware/DisplayHardware.cpp \
     DisplayHardware/DisplayHardwareBase.cpp \
-    GPUHardware/GPUHardware.cpp \
     BlurFilter.cpp.arm \
-    CPUGauge.cpp \
     Layer.cpp \
     LayerBase.cpp \
     LayerBuffer.cpp \
     LayerBlur.cpp \
-    LayerBitmap.cpp \
     LayerDim.cpp \
-    LayerOrientationAnim.cpp \
-    OrientationAnimation.cpp \
+    MessageQueue.cpp \
     SurfaceFlinger.cpp \
     Tokenizer.cpp \
-    Transform.cpp \
-    VRamHeap.cpp
+    Transform.cpp
 
+LOCAL_CFLAGS:= -DLOG_TAG=\"SurfaceFlinger\"
+LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
+
+ifeq ($(TARGET_BOARD_PLATFORM), msm7k)
+	LOCAL_CFLAGS += -DDIM_WITH_TEXTURE
+endif
+ifeq ($(TARGET_BOARD_PLATFORM), qsd8k)
+	LOCAL_CFLAGS += -DDIM_WITH_TEXTURE
+endif
 
 # need "-lrt" on Linux simulator to pick up clock_gettime
 ifeq ($(TARGET_SIMULATOR),true)
 	ifeq ($(HOST_OS),linux)
-		LOCAL_LDLIBS += -lrt
+		LOCAL_LDLIBS += -lrt -lpthread
 	endif
 endif
 
 LOCAL_SHARED_LIBRARIES := \
+	libcutils \
+	libpixelflinger \
 	libhardware \
 	libutils \
-	libcutils \
-	libui \
-	libcorecg \
-	libsgl \
-	libpixelflinger \
+	libskia \
 	libEGL \
-	libGLESv1_CM
+	libGLESv1_CM \
+	libbinder \
+	libui
 
 LOCAL_C_INCLUDES := \
 	$(call include-path-for, corecg graphics)
 
+LOCAL_C_INCLUDES += hardware/libhardware/modules/gralloc
+
 LOCAL_MODULE:= libsurfaceflinger
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/libs/surfaceflinger/BlurFilter.cpp b/libs/surfaceflinger/BlurFilter.cpp
index 5dc0ba0..1ffbd5b 100644
--- a/libs/surfaceflinger/BlurFilter.cpp
+++ b/libs/surfaceflinger/BlurFilter.cpp
@@ -111,6 +111,50 @@
     }
 };
 
+template <int FACTOR = 0>
+struct BlurColor888X
+{
+    typedef uint32_t type;
+    int r, g, b;    
+    inline BlurColor888X() { }
+    inline BlurColor888X(uint32_t v) {
+        v = BLUR_RGBA_TO_HOST(v);
+        r = v & 0xFF;
+        g = (v >>  8) & 0xFF;
+        b = (v >> 16) & 0xFF;
+    }
+    inline void clear() { r=g=b=0; }
+    inline uint32_t to(int shift, int last, int dither) const {
+        int R = r;
+        int G = g;
+        int B = b;
+        if  (UNLIKELY(last)) {
+            if (FACTOR>0) {
+                int L = (R+G+G+B)>>2;
+                R += ((L - R) * FACTOR) >> 8;
+                G += ((L - G) * FACTOR) >> 8;
+                B += ((L - B) * FACTOR) >> 8;
+            }
+        }
+        R >>= shift;
+        G >>= shift;
+        B >>= shift;
+        return BLUR_HOST_TO_RGBA((0xFF<<24) | (B<<16) | (G<<8) | R);
+    }    
+    inline BlurColor888X& operator += (const BlurColor888X& rhs) {
+        r += rhs.r;
+        g += rhs.g;
+        b += rhs.b;
+        return *this;
+    }
+    inline BlurColor888X& operator -= (const BlurColor888X& rhs) {
+        r -= rhs.r;
+        g -= rhs.g;
+        b -= rhs.b;
+        return *this;
+    }
+};
+
 struct BlurGray565
 {
     typedef uint16_t type;
@@ -316,7 +360,13 @@
         int kernelSizeUser,
         int repeat)
 {
-    return blurFilter< BlurColor565<0x80> >(image, image, kernelSizeUser, repeat);
+    status_t err = BAD_VALUE;
+    if (image->format == GGL_PIXEL_FORMAT_RGB_565) {
+        err = blurFilter< BlurColor565<0x80> >(image, image, kernelSizeUser, repeat);
+    } else if (image->format == GGL_PIXEL_FORMAT_RGBX_8888) {
+        err = blurFilter< BlurColor888X<0x80> >(image, image, kernelSizeUser, repeat);
+    }
+    return err;
 }
 
 } // namespace android
diff --git a/libs/surfaceflinger/CPUGauge.cpp b/libs/surfaceflinger/CPUGauge.cpp
deleted file mode 100644
index 74a9270..0000000
--- a/libs/surfaceflinger/CPUGauge.cpp
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "CPUGauge"
-
-#include <stdint.h>
-#include <limits.h>
-#include <sys/types.h>
-#include <math.h>
-
-#include <utils/threads.h>
-#include <utils/Errors.h>
-#include <utils/Log.h>
-
-#include <ui/PixelFormat.h>
-#include <ui/Rect.h>
-#include <ui/Region.h>
-#include <ui/DisplayInfo.h>
-#include <ui/ISurfaceComposer.h>
-#include <ui/ISurfaceFlingerClient.h>
-
-#include <pixelflinger/pixelflinger.h>
-
-#include "CPUGauge.h"
-
-namespace android {
-
-CPUGauge::CPUGauge( const sp<ISurfaceComposer>& composer,
-                    nsecs_t interval,
-                    int clock,
-                    int refclock)
-    :   Thread(false), 
-        mInterval(interval), mClock(clock), mRefClock(refclock),
-        mReferenceTime(0),
-        mReferenceWorkingTime(0), mCpuUsage(0),
-        mRefIdleTime(0), mIdleTime(0)
-{
-    mFd = fopen("/proc/stat", "r");
-    setvbuf(mFd, NULL, _IONBF, 0);
-
-    mSession = SurfaceComposerClient::clientForConnection(
-        composer->createConnection()->asBinder());
-}
-
-CPUGauge::~CPUGauge()
-{
-    fclose(mFd);
-}
-
-const sp<SurfaceComposerClient>& CPUGauge::session() const 
-{
-    return mSession;
-}
-
-void CPUGauge::onFirstRef()
-{
-    run("CPU Gauge");
-}
-
-status_t CPUGauge::readyToRun()
-{
-    LOGI("Starting CPU gauge...");
-    return NO_ERROR;
-}
-
-bool CPUGauge::threadLoop()
-{
-    DisplayInfo dinfo;
-    session()->getDisplayInfo(0, &dinfo);
-    sp<Surface> s(session()->createSurface(getpid(), 0, dinfo.w, 4, PIXEL_FORMAT_OPAQUE));
-    session()->openTransaction();
-    s->setLayer(INT_MAX);
-    session()->closeTransaction();
-    
-    static const GGLfixed colors[4][4] = {
-            { 0x00000, 0x10000, 0x00000, 0x10000 },
-            { 0x10000, 0x10000, 0x00000, 0x10000 },
-            { 0x10000, 0x00000, 0x00000, 0x10000 },
-            { 0x00000, 0x00000, 0x00000, 0x10000 },
-        };
-
-    GGLContext* gl;
-    gglInit(&gl);
-    gl->activeTexture(gl, 0);
-    gl->disable(gl, GGL_TEXTURE_2D);
-    gl->disable(gl, GGL_BLEND);
-
-    const int w = dinfo.w;
-
-    while(!exitPending())
-    {
-        mLock.lock();
-            const float cpuUsage = this->cpuUsage();
-            const float totalCpuUsage = 1.0f - idle();
-        mLock.unlock();
-
-        Surface::SurfaceInfo info;
-        s->lock(&info);
-            GGLSurface fb;
-                fb.version = sizeof(GGLSurface);
-                fb.width   = info.w;
-                fb.height  = info.h;
-                fb.stride  = info.w;
-                fb.format  = info.format;
-                fb.data = (GGLubyte*)info.bits;
-
-            gl->colorBuffer(gl, &fb);
-            gl->color4xv(gl, colors[3]);
-            gl->recti(gl, 0, 0, w, 4);
-            gl->color4xv(gl, colors[2]); // red
-            gl->recti(gl, 0, 0, int(totalCpuUsage*w), 2);
-            gl->color4xv(gl, colors[0]); // green
-            gl->recti(gl, 0, 2, int(cpuUsage*w), 4);
-        
-        s->unlockAndPost(); 
-
-        usleep(ns2us(mInterval));
-    }
-
-    gglUninit(gl);
-    return false;
-}
-
-void CPUGauge::sample()
-{
-    if (mLock.tryLock() == NO_ERROR) {
-        const nsecs_t now = systemTime(mRefClock);
-        const nsecs_t referenceTime = now-mReferenceTime;
-        if (referenceTime >= mInterval) {
-            const float reftime = 1.0f / referenceTime;
-            const nsecs_t nowWorkingTime = systemTime(mClock);
-            
-            char buf[256];
-            fgets(buf, 256, mFd);
-            rewind(mFd);
-            char *str = buf+5;
-            char const * const usermode = strsep(&str, " ");  (void)usermode;
-            char const * const usernice = strsep(&str, " ");  (void)usernice;
-            char const * const systemmode = strsep(&str, " ");(void)systemmode;
-            char const * const idle = strsep(&str, " ");
-            const nsecs_t nowIdleTime = atoi(idle) * 10000000LL;
-            mIdleTime = float(nowIdleTime - mRefIdleTime) * reftime;
-            mRefIdleTime = nowIdleTime;
-            
-            const nsecs_t workingTime = nowWorkingTime - mReferenceWorkingTime;
-            const float newCpuUsage = float(workingTime) * reftime;
-            if (mCpuUsage != newCpuUsage) {        
-                mCpuUsage = newCpuUsage;
-                mReferenceWorkingTime = nowWorkingTime;
-                mReferenceTime = now;
-            }
-        }
-        mLock.unlock();
-    }
-}
-
-
-}; // namespace android
diff --git a/libs/surfaceflinger/CPUGauge.h b/libs/surfaceflinger/CPUGauge.h
deleted file mode 100644
index 5bb53c0..0000000
--- a/libs/surfaceflinger/CPUGauge.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_CPUGAUGE_H
-#define ANDROID_CPUGAUGE_H
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <utils/Timers.h>
-
-#include <ui/SurfaceComposerClient.h>
-
-namespace android {
-
-class CPUGauge : public Thread
-{
-public:
-    CPUGauge(   const sp<ISurfaceComposer>& composer,
-                nsecs_t interval=s2ns(1),
-                int clock=SYSTEM_TIME_THREAD,
-                int refclock=SYSTEM_TIME_MONOTONIC);
-                
-    ~CPUGauge();
-
-    const sp<SurfaceComposerClient>& session() const;
-
-    void sample();
- 
-    inline float cpuUsage() const { return mCpuUsage; }
-    inline float idle() const { return mIdleTime; }
-
-private:
-    virtual void        onFirstRef();
-    virtual status_t    readyToRun();
-    virtual bool        threadLoop();
-
-    Mutex mLock;
-
-    sp<SurfaceComposerClient> mSession;
-
-    const nsecs_t mInterval;
-    const int mClock;
-    const int mRefClock;
-
-    nsecs_t mReferenceTime;
-    nsecs_t mReferenceWorkingTime;
-    float mCpuUsage;
-    nsecs_t mRefIdleTime;
-    float mIdleTime;
-    FILE*   mFd;
-};
-
-
-}; // namespace android
-
-#endif // ANDROID_CPUGAUGE_H
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
index ab02fa0..1abfd68 100644
--- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
+++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "SurfaceFlinger"
-
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
@@ -23,63 +21,50 @@
 
 #include <cutils/properties.h>
 
+#include <utils/RefBase.h>
 #include <utils/Log.h>
 
-#include <ui/EGLDisplaySurface.h>
+#include <ui/PixelFormat.h>
+#include <ui/FramebufferNativeWindow.h>
+#include <ui/EGLUtils.h>
 
 #include <GLES/gl.h>
+#include <EGL/egl.h>
 #include <EGL/eglext.h>
 
+#include <pixelflinger/pixelflinger.h>
 
 #include "DisplayHardware/DisplayHardware.h"
 
 #include <hardware/copybit.h>
 #include <hardware/overlay.h>
+#include <hardware/gralloc.h>
 
 using namespace android;
 
-static __attribute__((noinline))
-const char *egl_strerror(EGLint err)
-{
-    switch (err){
-        case EGL_SUCCESS:           return "EGL_SUCCESS";
-        case EGL_NOT_INITIALIZED:   return "EGL_NOT_INITIALIZED";
-        case EGL_BAD_ACCESS:        return "EGL_BAD_ACCESS";
-        case EGL_BAD_ALLOC:         return "EGL_BAD_ALLOC";
-        case EGL_BAD_ATTRIBUTE:     return "EGL_BAD_ATTRIBUTE";
-        case EGL_BAD_CONFIG:        return "EGL_BAD_CONFIG";
-        case EGL_BAD_CONTEXT:       return "EGL_BAD_CONTEXT";
-        case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE";
-        case EGL_BAD_DISPLAY:       return "EGL_BAD_DISPLAY";
-        case EGL_BAD_MATCH:         return "EGL_BAD_MATCH";
-        case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP";
-        case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW";
-        case EGL_BAD_PARAMETER:     return "EGL_BAD_PARAMETER";
-        case EGL_BAD_SURFACE:       return "EGL_BAD_SURFACE";
-        case EGL_CONTEXT_LOST:      return "EGL_CONTEXT_LOST";
-        default: return "UNKNOWN";
-    }
-}
 
 static __attribute__((noinline))
 void checkGLErrors()
 {
-    GLenum error = glGetError();
-    if (error != GL_NO_ERROR)
+    do {
+        // there could be more than one error flag
+        GLenum error = glGetError();
+        if (error == GL_NO_ERROR)
+            break;
         LOGE("GL error 0x%04x", int(error));
+    } while(true);
 }
 
 static __attribute__((noinline))
 void checkEGLErrors(const char* token)
 {
     EGLint error = eglGetError();
-    // GLESonGL seems to be returning 0 when there is no errors?
-    if (error && error != EGL_SUCCESS)
-        LOGE("%s error 0x%04x (%s)",
-                token, int(error), egl_strerror(error));
+    if (error && error != EGL_SUCCESS) {
+        LOGE("%s: EGL error 0x%04x (%s)",
+                token, int(error), EGLUtils::strerror(error));
+    }
 }
 
-
 /*
  * Initialize the display to the specified values.
  *
@@ -108,20 +93,37 @@
 
 void DisplayHardware::init(uint32_t dpy)
 {
+    mNativeWindow = new FramebufferNativeWindow();
+    framebuffer_device_t const * fbDev = mNativeWindow->getDevice();
+
+    mOverlayEngine = NULL;
+    hw_module_t const* module;
+    if (hw_get_module(OVERLAY_HARDWARE_MODULE_ID, &module) == 0) {
+        overlay_control_open(module, &mOverlayEngine);
+    }
+
     // initialize EGL
-    const EGLint attribs[] = {
-            EGL_RED_SIZE,       5,
-            EGL_GREEN_SIZE,     6,
-            EGL_BLUE_SIZE,      5,
-            EGL_DEPTH_SIZE,     0,
+    EGLint attribs[] = {
+            EGL_SURFACE_TYPE,   EGL_WINDOW_BIT,
+            EGL_NONE,           0,
             EGL_NONE
     };
+
+    // debug: disable h/w rendering
+    char property[PROPERTY_VALUE_MAX];
+    if (property_get("debug.sf.hw", property, NULL) > 0) {
+        if (atoi(property) == 0) {
+            LOGW("H/W composition disabled");
+            attribs[2] = EGL_CONFIG_CAVEAT;
+            attribs[3] = EGL_SLOW_CONFIG;
+        }
+    }
+
     EGLint w, h, dummy;
-    EGLint numConfigs, n;
-    EGLConfig config;
+    EGLint numConfigs=0;
     EGLSurface surface;
     EGLContext context;
-    mFlags = 0;
+    mFlags = CACHED_BUFFERS;
 
     // TODO: all the extensions below should be queried through
     // eglGetProcAddress().
@@ -129,7 +131,17 @@
     EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
     eglInitialize(display, NULL, NULL);
     eglGetConfigs(display, NULL, 0, &numConfigs);
-    eglChooseConfig(display, attribs, &config, 1, &n);
+
+    EGLConfig config;
+    status_t err = EGLUtils::selectConfigForNativeWindow(
+            display, attribs, mNativeWindow.get(), &config);
+    LOGE_IF(err, "couldn't find an EGLConfig matching the screen format");
+    
+    EGLint r,g,b,a;
+    eglGetConfigAttrib(display, config, EGL_RED_SIZE,   &r);
+    eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &g);
+    eglGetConfigAttrib(display, config, EGL_BLUE_SIZE,  &b);
+    eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &a);
 
     /*
      * Gather EGL extensions
@@ -144,13 +156,13 @@
     LOGI("version   : %s", eglQueryString(display, EGL_VERSION));
     LOGI("extensions: %s", egl_extensions);
     LOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS)?:"Not Supported");
-
-    // TODO: get this from the devfb driver (probably should be HAL module)
-    mFlags |= SWAP_RECTANGLE_EXTENSION;
+    LOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, config);
     
-    // TODO: get the real "update_on_demand" behavior (probably should be HAL module)
-    mFlags |= UPDATE_ON_DEMAND;
 
+    if (mNativeWindow->isUpdateOnDemand()) {
+        mFlags |= PARTIAL_UPDATES;
+    }
+    
     if (eglGetConfigAttrib(display, config, EGL_CONFIG_CAVEAT, &dummy) == EGL_TRUE) {
         if (dummy == EGL_SLOW_CONFIG)
             mFlags |= SLOW_CONFIG;
@@ -160,37 +172,48 @@
      * Create our main surface
      */
 
-    mDisplaySurface = new EGLDisplaySurface();
+    surface = eglCreateWindowSurface(display, config, mNativeWindow.get(), NULL);
 
-    surface = eglCreateWindowSurface(display, config, mDisplaySurface.get(), NULL);
-    //checkEGLErrors("eglCreateDisplaySurfaceANDROID");
+    if (mFlags & PARTIAL_UPDATES) {
+        // if we have partial updates, we definitely don't need to
+        // preserve the backbuffer, which may be costly.
+        eglSurfaceAttrib(display, surface,
+                EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED);
+    }
 
     if (eglQuerySurface(display, surface, EGL_SWAP_BEHAVIOR, &dummy) == EGL_TRUE) {
         if (dummy == EGL_BUFFER_PRESERVED) {
             mFlags |= BUFFER_PRESERVED;
         }
     }
-    
-    GLint value = EGL_UNKNOWN;
-    eglQuerySurface(display, surface, EGL_HORIZONTAL_RESOLUTION, &value);
-    if (value == EGL_UNKNOWN) {
-        mDpiX = 160.0f;
-    } else {
-        mDpiX = 25.4f * float(value)/EGL_DISPLAY_SCALING;
+
+    eglQuerySurface(display, surface, EGL_WIDTH,  &mWidth);
+    eglQuerySurface(display, surface, EGL_HEIGHT, &mHeight);
+
+#ifdef EGL_ANDROID_swap_rectangle    
+    if (strstr(egl_extensions, "EGL_ANDROID_swap_rectangle")) {
+        if (eglSetSwapRectangleANDROID(display, surface,
+                0, 0, mWidth, mHeight) == EGL_TRUE) {
+            // This could fail if this extension is not supported by this
+            // specific surface (of config)
+            mFlags |= SWAP_RECTANGLE;
+        }
     }
-    value = EGL_UNKNOWN;
-    eglQuerySurface(display, surface, EGL_VERTICAL_RESOLUTION, &value);
-    if (value == EGL_UNKNOWN) {
-        mDpiY = 160.0f;
-    } else {
-        mDpiY = 25.4f * float(value)/EGL_DISPLAY_SCALING;
-    }
-    mRefreshRate = 60.f;    // TODO: get the real refresh rate 
+    // when we have the choice between PARTIAL_UPDATES and SWAP_RECTANGLE
+    // choose PARTIAL_UPDATES, which should be more efficient
+    if (mFlags & PARTIAL_UPDATES)
+        mFlags &= ~SWAP_RECTANGLE;
+#endif
     
+
+    LOGI("flags     : %08x", mFlags);
     
-    char property[PROPERTY_VALUE_MAX];
+    mDpiX = mNativeWindow->xdpi;
+    mDpiY = mNativeWindow->ydpi;
+    mRefreshRate = fbDev->fps; 
+    
     /* Read density from build-specific ro.sf.lcd_density property
-     * except if it is overriden by qemu.sf.lcd_density.
+     * except if it is overridden by qemu.sf.lcd_density.
      */
     if (property_get("qemu.sf.lcd_density", property, NULL) <= 0) {
         if (property_get("ro.sf.lcd_density", property, NULL) <= 0) {
@@ -209,11 +232,6 @@
      */
     
     context = eglCreateContext(display, config, NULL, NULL);
-    //checkEGLErrors("eglCreateContext");
-    
-    eglQuerySurface(display, surface, EGL_WIDTH, &mWidth);
-    eglQuerySurface(display, surface, EGL_HEIGHT, &mHeight);
-    
     
     /*
      * Gather OpenGL ES extensions
@@ -221,21 +239,33 @@
 
     eglMakeCurrent(display, surface, surface, context);
     const char* const  gl_extensions = (const char*)glGetString(GL_EXTENSIONS);
+    const char* const  gl_renderer = (const char*)glGetString(GL_RENDERER);
     LOGI("OpenGL informations:");
     LOGI("vendor    : %s", glGetString(GL_VENDOR));
-    LOGI("renderer  : %s", glGetString(GL_RENDERER));
+    LOGI("renderer  : %s", gl_renderer);
     LOGI("version   : %s", glGetString(GL_VERSION));
     LOGI("extensions: %s", gl_extensions);
 
+    if (strstr(gl_renderer, "PowerVR SGX 530")) {
+        LOGD("Assuming uncached graphics buffers.");
+        mFlags &= ~CACHED_BUFFERS;
+    }
     if (strstr(gl_extensions, "GL_ARB_texture_non_power_of_two")) {
         mFlags |= NPOT_EXTENSION;
     }
     if (strstr(gl_extensions, "GL_OES_draw_texture")) {
         mFlags |= DRAW_TEXTURE_EXTENSION;
     }
-    if (strstr(gl_extensions, "GL_ANDROID_direct_texture")) {
+#ifdef EGL_ANDROID_image_native_buffer
+    if (strstr( gl_extensions, "GL_OES_EGL_image") &&
+        (strstr(egl_extensions, "EGL_KHR_image_base") || 
+                strstr(egl_extensions, "EGL_KHR_image")) &&
+        strstr(egl_extensions, "EGL_ANDROID_image_native_buffer")) {
         mFlags |= DIRECT_TEXTURE;
     }
+#else
+#warning "EGL_ANDROID_image_native_buffer not supported"
+#endif
 
     // Unbind the context from this thread
     eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
@@ -244,19 +274,8 @@
     mConfig  = config;
     mSurface = surface;
     mContext = context;
-    mFormat  = GGL_PIXEL_FORMAT_RGB_565;
-    
-    hw_module_t const* module;
-
-    mBlitEngine = NULL;
-    if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) {
-        copybit_open(module, &mBlitEngine);
-    }
-
-    mOverlayEngine = NULL;
-    if (hw_get_module(OVERLAY_HARDWARE_MODULE_ID, &module) == 0) {
-        overlay_control_open(module, &mOverlayEngine);
-    }
+    mFormat  = fbDev->format;
+    mPageFlipCount = 0;
 }
 
 /*
@@ -270,7 +289,6 @@
 {
     eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
     eglTerminate(mDisplay);
-    copybit_close(mBlitEngine);
     overlay_control_close(mOverlayEngine);
 }
 
@@ -284,33 +302,13 @@
     DisplayHardwareBase::acquireScreen();
 }
 
-void DisplayHardware::getDisplaySurface(copybit_image_t* img) const
-{
-    img->w      = mDisplaySurface->stride;
-    img->h      = mDisplaySurface->height;
-    img->format = mDisplaySurface->format;
-    img->offset = mDisplaySurface->offset;
-    img->base   = (void*)mDisplaySurface->base;
-    img->fd     = mDisplaySurface->fd;
-}
-
-void DisplayHardware::getDisplaySurface(GGLSurface* fb) const
-{
-    fb->version= sizeof(GGLSurface);
-    fb->width  = mDisplaySurface->width;
-    fb->height = mDisplaySurface->height;
-    fb->stride = mDisplaySurface->stride;
-    fb->format = mDisplaySurface->format;
-    fb->data   = (GGLubyte*)mDisplaySurface->base + mDisplaySurface->offset;
-}
-
 uint32_t DisplayHardware::getPageFlipCount() const {
-    return mDisplaySurface->getPageFlipCount();
+    return mPageFlipCount;
 }
 
-/*
- * "Flip" the front and back buffers.
- */
+status_t DisplayHardware::compositionComplete() const {
+    return mNativeWindow->compositionComplete();
+}
 
 void DisplayHardware::flip(const Region& dirty) const
 {
@@ -319,21 +317,20 @@
     EGLDisplay dpy = mDisplay;
     EGLSurface surface = mSurface;
 
-    Region newDirty(dirty);
-    newDirty.andSelf(Rect(mWidth, mHeight));
-
-    if (mFlags & BUFFER_PRESERVED) {
-        const Region copyback(mDirty.subtract(newDirty));
-        mDirty = newDirty;
-        mDisplaySurface->copyFrontToBack(copyback);
-    } 
-
-    if (mFlags & SWAP_RECTANGLE_EXTENSION) {
-        const Rect& b(newDirty.bounds());
-        mDisplaySurface->setSwapRectangle(
+#ifdef EGL_ANDROID_swap_rectangle    
+    if (mFlags & SWAP_RECTANGLE) {
+        const Region newDirty(dirty.intersect(bounds()));
+        const Rect b(newDirty.getBounds());
+        eglSetSwapRectangleANDROID(dpy, surface,
                 b.left, b.top, b.width(), b.height());
+    } 
+#endif
+    
+    if (mFlags & PARTIAL_UPDATES) {
+        mNativeWindow->setUpdateRectangle(dirty.getBounds());
     }
-
+    
+    mPageFlipCount++;
     eglSwapBuffers(dpy, surface);
     checkEGLErrors("eglSwapBuffers");
 
@@ -351,11 +348,3 @@
 {
     eglMakeCurrent(mDisplay, mSurface, mSurface, mContext);
 }
-
-void DisplayHardware::copyFrontToImage(const copybit_image_t& front) const {
-    mDisplaySurface->copyFrontToImage(front);
-}
-
-void DisplayHardware::copyBackToImage(const copybit_image_t& front) const {
-    mDisplaySurface->copyBackToImage(front);
-}
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.h b/libs/surfaceflinger/DisplayHardware/DisplayHardware.h
index 550a4d1..6914d0c 100644
--- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.h
+++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.h
@@ -22,31 +22,36 @@
 #include <ui/PixelFormat.h>
 #include <ui/Region.h>
 
+#include <GLES/gl.h>
+#include <GLES/glext.h>
 #include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+#include <pixelflinger/pixelflinger.h>
 
 #include "DisplayHardware/DisplayHardwareBase.h"
 
 struct overlay_control_device_t;
-struct copybit_device_t;
+struct framebuffer_device_t;
 struct copybit_image_t;
-struct copybit_t;
 
 namespace android {
 
-class EGLDisplaySurface;
+class FramebufferNativeWindow;
 
 class DisplayHardware : public DisplayHardwareBase
 {
 public:
     enum {
         DIRECT_TEXTURE          = 0x00000002,
-        SWAP_RECTANGLE_EXTENSION= 0x00000004,
         COPY_BITS_EXTENSION     = 0x00000008,
         NPOT_EXTENSION          = 0x00000100,
         DRAW_TEXTURE_EXTENSION  = 0x00000200,
         BUFFER_PRESERVED        = 0x00010000,
-        UPDATE_ON_DEMAND        = 0x00020000,   // video driver feature
+        PARTIAL_UPDATES         = 0x00020000,   // video driver feature
         SLOW_CONFIG             = 0x00040000,   // software
+        SWAP_RECTANGLE          = 0x00080000,
+        CACHED_BUFFERS          = 0x00100000
     };
 
     DisplayHardware(
@@ -73,15 +78,11 @@
     void        makeCurrent() const;
 
     uint32_t getPageFlipCount() const;
-    void getDisplaySurface(copybit_image_t* img) const;
-    void getDisplaySurface(GGLSurface* fb) const;
     EGLDisplay getEGLDisplay() const { return mDisplay; }
-    copybit_device_t* getBlitEngine() const { return mBlitEngine; }
     overlay_control_device_t* getOverlayEngine() const { return mOverlayEngine; }
     
-    void copyFrontToImage(const copybit_image_t& front) const;
-    void copyBackToImage(const copybit_image_t& front) const;
-       
+    status_t compositionComplete() const;
+    
     Rect bounds() const {
         return Rect(mWidth, mHeight);
     }
@@ -102,9 +103,9 @@
     int             mHeight;
     PixelFormat     mFormat;
     uint32_t        mFlags;
-    mutable Region  mDirty;
-    sp<EGLDisplaySurface> mDisplaySurface;
-    copybit_device_t*     mBlitEngine;
+    mutable uint32_t mPageFlipCount;
+    
+    sp<FramebufferNativeWindow> mNativeWindow;
     overlay_control_device_t* mOverlayEngine;
 };
 
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp
index f75e5c2..1d09f84 100644
--- a/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp
+++ b/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "SurfaceFlinger"
-
 #include <assert.h>
 #include <errno.h>
 #include <stdlib.h>
diff --git a/libs/surfaceflinger/GPUHardware/GPUHardware.cpp b/libs/surfaceflinger/GPUHardware/GPUHardware.cpp
deleted file mode 100644
index 7168bf2..0000000
--- a/libs/surfaceflinger/GPUHardware/GPUHardware.cpp
+++ /dev/null
@@ -1,585 +0,0 @@
-/*
- * 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 "SurfaceFlinger"
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <math.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-
-#include <cutils/log.h>
-#include <cutils/properties.h>
-
-#include <utils/IBinder.h>
-#include <utils/MemoryDealer.h>
-#include <utils/MemoryBase.h>
-#include <utils/MemoryHeapPmem.h>
-#include <utils/MemoryHeapBase.h>
-#include <utils/IPCThreadState.h>
-#include <utils/StopWatch.h>
-
-#include <ui/ISurfaceComposer.h>
-
-#include "VRamHeap.h"
-#include "GPUHardware.h"
-
-#if HAVE_ANDROID_OS
-#include <linux/android_pmem.h>
-#endif
-
-#include "GPUHardware/GPUHardware.h"
-
-
-/* 
- * Manage the GPU. This implementation is very specific to the G1.
- * There are no abstraction here. 
- * 
- * All this code will soon go-away and be replaced by a new architecture
- * for managing graphics accelerators.
- * 
- * In the meantime, it is conceptually possible to instantiate a
- * GPUHardwareInterface for another GPU (see GPUFactory at the bottom
- * of this file); practically... doubtful.
- * 
- */
-
-namespace android {
-
-// ---------------------------------------------------------------------------
-
-class GPUClientHeap;
-class GPUAreaHeap;
-
-class GPUHardware : public GPUHardwareInterface, public IBinder::DeathRecipient
-{
-public:
-    static const int GPU_RESERVED_SIZE;
-    static const int GPUR_SIZE;
-
-            GPUHardware();
-    virtual ~GPUHardware();
-    
-    virtual void revoke(int pid);
-    virtual sp<MemoryDealer> request(int pid);
-    virtual status_t request(int pid, 
-            const sp<IGPUCallback>& callback,
-            ISurfaceComposer::gpu_info_t* gpu);
-
-    virtual status_t friendlyRevoke();
-    virtual void unconditionalRevoke();
-    
-    virtual pid_t getOwner() const { return mOwner; }
-
-    // used for debugging only...
-    virtual sp<SimpleBestFitAllocator> getAllocator() const;
-
-private:
-    
-    
-    enum {
-        NO_OWNER = -1,
-    };
-        
-    struct GPUArea {
-        sp<GPUAreaHeap>     heap;
-        sp<MemoryHeapPmem>  clientHeap;
-        sp<IMemory> map();
-    };
-    
-    struct Client {
-        pid_t       pid;
-        GPUArea     smi;
-        GPUArea     ebi;
-        GPUArea     reg;
-        void createClientHeaps();
-        void revokeAllHeaps();
-    };
-    
-    Client& getClientLocked(pid_t pid);
-    status_t requestLocked(int pid);
-    void releaseLocked();
-    void takeBackGPULocked();
-    void registerCallbackLocked(const sp<IGPUCallback>& callback,
-            Client& client);
-
-    virtual void binderDied(const wp<IBinder>& who);
-
-    mutable Mutex           mLock;
-    sp<GPUAreaHeap>         mSMIHeap;
-    sp<GPUAreaHeap>         mEBIHeap;
-    sp<GPUAreaHeap>         mREGHeap;
-
-    KeyedVector<pid_t, Client> mClients;
-    DefaultKeyedVector< wp<IBinder>, pid_t > mRegisteredClients;
-    
-    pid_t                   mOwner;
-
-    sp<MemoryDealer>        mCurrentAllocator;
-    sp<IGPUCallback>        mCallback;
-    
-    sp<SimpleBestFitAllocator>  mAllocator;
-
-    Condition               mCondition;
-};
-
-// size reserved for GPU surfaces
-// 1200 KB fits exactly:
-//  - two 320*480 16-bits double-buffered surfaces
-//  - one 320*480 32-bits double-buffered surface
-//  - one 320*240 16-bits double-buffered, 4x anti-aliased surface
-const int GPUHardware::GPU_RESERVED_SIZE  = 1200 * 1024;
-const int GPUHardware::GPUR_SIZE          = 1 * 1024 * 1024;
-
-// ---------------------------------------------------------------------------
-
-/* 
- * GPUHandle is a special IMemory given to the client. It represents their
- * handle to the GPU. Once they give it up, they loose GPU access, or if
- * they explicitly revoke their access through the binder code 1000.
- * In both cases, this triggers a callback to revoke()
- * first, and then actually powers down the chip.
- * 
- * In the case of a misbehaving app, GPUHardware can ask for an immediate
- * release of the GPU to the target process which should answer by calling
- * code 1000 on GPUHandle. If it doesn't in a timely manner, the GPU will
- * be revoked from under their feet.
- * 
- * We should never hold a strong reference on GPUHandle. In practice this
- * shouldn't be a big issue though because clients should use code 1000 and
- * not rely on the dtor being called.
- * 
- */
-
-class GPUClientHeap : public MemoryHeapPmem
-{
-public:
-    GPUClientHeap(const wp<GPUHardware>& gpu, 
-            const sp<MemoryHeapBase>& heap)
-        :  MemoryHeapPmem(heap), mGPU(gpu) { }
-protected:
-    wp<GPUHardware> mGPU;
-};
-
-class GPUAreaHeap : public MemoryHeapBase
-{
-public:
-    GPUAreaHeap(const wp<GPUHardware>& gpu,
-            const char* const vram, size_t size=0, size_t reserved=0)
-    : MemoryHeapBase(vram, size), mGPU(gpu) { 
-        if (base() != MAP_FAILED) {
-            if (reserved == 0)
-                reserved = virtualSize();
-            mAllocator = new SimpleBestFitAllocator(reserved);
-        }
-    }
-    virtual sp<MemoryHeapPmem> createClientHeap() {
-        sp<MemoryHeapBase> parentHeap(this);
-        return new GPUClientHeap(mGPU, parentHeap);
-    }
-    virtual const sp<SimpleBestFitAllocator>& getAllocator() const {
-        return mAllocator; 
-    }
-private:
-    sp<SimpleBestFitAllocator>  mAllocator;
-protected:
-    wp<GPUHardware> mGPU;
-};
-
-class GPURegisterHeap : public GPUAreaHeap
-{
-public:
-    GPURegisterHeap(const sp<GPUHardware>& gpu)
-        : GPUAreaHeap(gpu, "/dev/hw3d", GPUHardware::GPUR_SIZE) { }
-    virtual sp<MemoryHeapPmem> createClientHeap() {
-        sp<MemoryHeapBase> parentHeap(this);
-        return new MemoryHeapRegs(mGPU, parentHeap);
-    }
-private:
-    class MemoryHeapRegs : public GPUClientHeap  {
-    public:
-        MemoryHeapRegs(const wp<GPUHardware>& gpu, 
-             const sp<MemoryHeapBase>& heap)
-            : GPUClientHeap(gpu, heap) { }
-        sp<MemoryHeapPmem::MemoryPmem> createMemory(size_t offset, size_t size);
-        virtual void revoke();
-    private:
-        class GPUHandle : public MemoryHeapPmem::MemoryPmem {
-        public:
-            GPUHandle(const sp<GPUHardware>& gpu,
-                    const sp<MemoryHeapPmem>& heap)
-                : MemoryHeapPmem::MemoryPmem(heap), 
-                  mGPU(gpu), mOwner(gpu->getOwner()) { }
-            virtual ~GPUHandle();
-            virtual sp<IMemoryHeap> getMemory(
-                    ssize_t* offset, size_t* size) const;
-            virtual void revoke() { };
-            virtual status_t onTransact(
-                    uint32_t code, const Parcel& data, 
-                    Parcel* reply, uint32_t flags);
-        private:
-            void revokeNotification();
-            wp<GPUHardware> mGPU;
-            pid_t mOwner;
-        };
-    };
-};
-
-GPURegisterHeap::MemoryHeapRegs::GPUHandle::~GPUHandle() { 
-    //LOGD("GPUHandle %p released, revoking GPU", this);
-    revokeNotification(); 
-}
-void GPURegisterHeap::MemoryHeapRegs::GPUHandle::revokeNotification()  {
-    sp<GPUHardware> hw(mGPU.promote());
-    if (hw != 0) {
-        hw->revoke(mOwner);
-    }
-}
-sp<IMemoryHeap> GPURegisterHeap::MemoryHeapRegs::GPUHandle::getMemory(
-        ssize_t* offset, size_t* size) const
-{
-    sp<MemoryHeapPmem> heap = getHeap();
-    if (offset) *offset = 0;
-    if (size)   *size = heap !=0 ? heap->virtualSize() : 0;
-    return heap;
-}
-status_t GPURegisterHeap::MemoryHeapRegs::GPUHandle::onTransact(
-        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
-    status_t err = BnMemory::onTransact(code, data, reply, flags);
-    if (err == UNKNOWN_TRANSACTION && code == 1000) {
-        int callingPid = IPCThreadState::self()->getCallingPid();
-        //LOGD("pid %d voluntarily revoking gpu", callingPid);
-        if (callingPid == mOwner) {
-            revokeNotification();
-            // we've revoked the GPU, don't do it again later when we
-            // are destroyed.
-            mGPU.clear();
-        } else {
-            LOGW("%d revoking someone else's gpu? (owner=%d)",
-                    callingPid, mOwner);            
-        }
-        err = NO_ERROR;
-    }
-    return err;
-}
-
-// ---------------------------------------------------------------------------
-
-
-sp<MemoryHeapPmem::MemoryPmem> GPURegisterHeap::MemoryHeapRegs::createMemory(
-        size_t offset, size_t size)
-{
-    sp<GPUHandle> memory;
-    sp<GPUHardware> gpu = mGPU.promote();
-    if (heapID()>0 && gpu!=0) {
-#if HAVE_ANDROID_OS
-        /* this is where the GPU is powered on and the registers are mapped
-         * in the client */
-        //LOGD("ioctl(HW3D_GRANT_GPU)");
-        int err = ioctl(heapID(), HW3D_GRANT_GPU, base());
-        if (err) {
-            // it can happen if the master heap has been closed already
-            // in which case the GPU already is revoked (app crash for
-            // instance).
-            LOGW("HW3D_GRANT_GPU failed (%s), mFD=%d, base=%p",
-                    strerror(errno), heapID(), base());
-        }
-        memory = new GPUHandle(gpu, this);
-#endif
-    }
-    return memory;
-}
-
-void GPURegisterHeap::MemoryHeapRegs::revoke() 
-{
-    MemoryHeapPmem::revoke();
-#if HAVE_ANDROID_OS
-    if (heapID() > 0) {
-        //LOGD("ioctl(HW3D_REVOKE_GPU)");
-        int err = ioctl(heapID(), HW3D_REVOKE_GPU, base());
-        LOGE_IF(err, "HW3D_REVOKE_GPU failed (%s), mFD=%d, base=%p",
-                strerror(errno), heapID(), base());
-    }
-#endif
-}
-
-/*****************************************************************************/
-
-GPUHardware::GPUHardware()
-    : mOwner(NO_OWNER)
-{
-}
-
-GPUHardware::~GPUHardware()
-{
-}
-
-status_t GPUHardware::requestLocked(int pid)
-{
-    const int self_pid = getpid();
-    if (pid == self_pid) {
-        // can't use GPU from surfaceflinger's process
-        return PERMISSION_DENIED;
-    }
-
-    if (mOwner != pid) {
-        if (mREGHeap != 0) {
-            if (mOwner != NO_OWNER) {
-                // someone already has the gpu.
-                takeBackGPULocked();
-                releaseLocked();
-            }
-        } else {
-            // first time, initialize the stuff.
-            if (mSMIHeap == 0)
-                mSMIHeap = new GPUAreaHeap(this, "/dev/pmem_gpu0");
-            if (mEBIHeap == 0)
-                mEBIHeap = new GPUAreaHeap(this, 
-                        "/dev/pmem_gpu1", 0, GPU_RESERVED_SIZE);
-            mREGHeap = new GPURegisterHeap(this);
-            mAllocator = mEBIHeap->getAllocator();
-            if (mAllocator == NULL) {
-                // something went terribly wrong.
-                mSMIHeap.clear();
-                mEBIHeap.clear();
-                mREGHeap.clear();
-                return INVALID_OPERATION;
-            }
-        }
-        Client& client = getClientLocked(pid);
-        mCurrentAllocator = new MemoryDealer(client.ebi.clientHeap, mAllocator);
-        mOwner = pid;
-    }
-    return NO_ERROR;
-}
-
-sp<MemoryDealer> GPUHardware::request(int pid)
-{
-    sp<MemoryDealer> dealer;
-    Mutex::Autolock _l(mLock);
-    Client* client;
-    LOGD("pid %d requesting gpu surface (current owner = %d)", pid, mOwner);
-    if (requestLocked(pid) == NO_ERROR) {
-        dealer = mCurrentAllocator;
-        LOGD_IF(dealer!=0, "gpu surface granted to pid %d", mOwner);
-    }
-    return dealer;
-}
-
-status_t GPUHardware::request(int pid, const sp<IGPUCallback>& callback,
-        ISurfaceComposer::gpu_info_t* gpu)
-{
-    if (callback == 0)
-        return BAD_VALUE;
-
-    sp<IMemory> gpuHandle;
-    LOGD("pid %d requesting gpu core (owner = %d)", pid, mOwner);
-    Mutex::Autolock _l(mLock);
-    status_t err = requestLocked(pid);
-    if (err == NO_ERROR) {
-        // it's guaranteed to be there, be construction
-        Client& client = mClients.editValueFor(pid);
-        registerCallbackLocked(callback, client);
-        gpu->count = 2;
-        gpu->regions[0].region = client.smi.map();
-        gpu->regions[1].region = client.ebi.map();
-        gpu->regs              = client.reg.map();
-        gpu->regions[0].reserved = 0;
-        gpu->regions[1].reserved = GPU_RESERVED_SIZE;
-        if (gpu->regs != 0) {
-            //LOGD("gpu core granted to pid %d, handle base=%p",
-            //        mOwner, gpu->regs->pointer());
-        }
-        mCallback = callback;
-    } else {
-        LOGW("couldn't grant gpu core to pid %d", pid);
-    }
-    return err;
-}
-
-void GPUHardware::revoke(int pid)
-{
-    Mutex::Autolock _l(mLock);
-    if (mOwner > 0) {
-        if (pid != mOwner) {
-            LOGW("GPU owned by %d, revoke from %d", mOwner, pid);
-            return;
-        }
-        //LOGD("revoke pid=%d, owner=%d", pid, mOwner);
-        // mOwner could be <0 if the same process acquired the GPU
-        // several times without releasing it first.
-        mCondition.signal();
-        releaseLocked();
-    }
-}
-
-status_t GPUHardware::friendlyRevoke()
-{
-    Mutex::Autolock _l(mLock);
-    //LOGD("friendlyRevoke owner=%d", mOwner);
-    takeBackGPULocked();
-    releaseLocked();
-    return NO_ERROR;
-}
-
-void GPUHardware::takeBackGPULocked()
-{
-    sp<IGPUCallback> callback = mCallback;
-    mCallback.clear();
-    if (callback != 0) {
-        callback->gpuLost(); // one-way
-        mCondition.waitRelative(mLock, ms2ns(250));
-    }
-}
-
-void GPUHardware::releaseLocked()
-{
-    //LOGD("revoking gpu from pid %d", mOwner);
-    if (mOwner != NO_OWNER) {
-        // this may fail because the client might have died, and have
-        // been removed from the list.
-        ssize_t index = mClients.indexOfKey(mOwner);
-        if (index >= 0) {
-            Client& client(mClients.editValueAt(index));
-            client.revokeAllHeaps();
-        }
-        mOwner = NO_OWNER;
-        mCurrentAllocator.clear();
-        mCallback.clear();
-    }
-}
-
-GPUHardware::Client& GPUHardware::getClientLocked(pid_t pid)
-{
-    ssize_t index = mClients.indexOfKey(pid);
-    if (index < 0) {
-        Client client;
-        client.pid = pid;
-        client.smi.heap = mSMIHeap;
-        client.ebi.heap = mEBIHeap;
-        client.reg.heap = mREGHeap;
-        index = mClients.add(pid, client);
-    }
-    Client& client(mClients.editValueAt(index));
-    client.createClientHeaps();
-    return client;
-}
-
-// ----------------------------------------------------------------------------
-// for debugging / testing ...
-
-sp<SimpleBestFitAllocator> GPUHardware::getAllocator() const {
-    Mutex::Autolock _l(mLock);
-    return mAllocator;
-}
-
-void GPUHardware::unconditionalRevoke()
-{
-    Mutex::Autolock _l(mLock);
-    releaseLocked();
-}
-
-// ---------------------------------------------------------------------------
-
-sp<IMemory> GPUHardware::GPUArea::map() {
-    sp<IMemory> memory;
-    if (clientHeap != 0 && heap != 0) {
-        memory = clientHeap->mapMemory(0, heap->virtualSize());
-    }
-    return memory;
-}
-
-void GPUHardware::Client::createClientHeaps() 
-{
-    if (smi.clientHeap == 0)
-        smi.clientHeap = smi.heap->createClientHeap();
-    if (ebi.clientHeap == 0)
-        ebi.clientHeap = ebi.heap->createClientHeap();
-    if (reg.clientHeap == 0)
-        reg.clientHeap = reg.heap->createClientHeap();
-}
-
-void GPUHardware::Client::revokeAllHeaps() 
-{
-    if (smi.clientHeap != 0)
-        smi.clientHeap->revoke();
-    if (ebi.clientHeap != 0)
-        ebi.clientHeap->revoke();
-    if (reg.clientHeap != 0)
-        reg.clientHeap->revoke();
-}
-
-void GPUHardware::registerCallbackLocked(const sp<IGPUCallback>& callback,
-        Client& client)
-{
-    sp<IBinder> binder = callback->asBinder();
-    if (mRegisteredClients.add(binder, client.pid) >= 0) {
-        binder->linkToDeath(this);
-    }
-}
-
-void GPUHardware::binderDied(const wp<IBinder>& who)
-{
-    Mutex::Autolock _l(mLock);
-    pid_t pid = mRegisteredClients.valueFor(who);
-    if (pid != 0) {
-        ssize_t index = mClients.indexOfKey(pid);
-        if (index >= 0) {
-            //LOGD("*** removing client at %d", index);
-            Client& client(mClients.editValueAt(index));
-            client.revokeAllHeaps(); // not really needed in theory
-            mClients.removeItemsAt(index);
-            if (mClients.size() == 0) {
-                //LOGD("*** was last client closing everything");
-                mCallback.clear();
-                mAllocator.clear();
-                mCurrentAllocator.clear();
-                mSMIHeap.clear();
-                mREGHeap.clear();
-                
-                // NOTE: we cannot clear the EBI heap because surfaceflinger
-                // itself may be using it, since this is where surfaces
-                // are allocated. if we're in the middle of compositing 
-                // a surface (even if its process just died), we cannot
-                // rip the heap under our feet.
-                
-                mOwner = NO_OWNER;
-            }
-        }
-    }
-}
-
-// ---------------------------------------------------------------------------
-
-sp<GPUHardwareInterface> GPUFactory::getGPU()
-{
-    sp<GPUHardwareInterface> gpu;
-    if (access("/dev/hw3d", F_OK) == 0) {
-        gpu = new GPUHardware();
-    }
-    return gpu;
-}
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-
diff --git a/libs/surfaceflinger/GPUHardware/GPUHardware.h b/libs/surfaceflinger/GPUHardware/GPUHardware.h
deleted file mode 100644
index 3354528..0000000
--- a/libs/surfaceflinger/GPUHardware/GPUHardware.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef ANDROID_GPU_HARDWARE_H
-#define ANDROID_GPU_HARDWARE_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <utils/RefBase.h>
-#include <utils/threads.h>
-#include <utils/KeyedVector.h>
-
-#include <ui/ISurfaceComposer.h>
-
-namespace android {
-
-// ---------------------------------------------------------------------------
-
-class IGPUCallback;
-
-class GPUHardwareInterface : public virtual RefBase
-{
-public:
-    virtual void                revoke(int pid) = 0;
-    virtual sp<MemoryDealer>    request(int pid) = 0;
-    virtual status_t            request(int pid, const sp<IGPUCallback>& callback,
-            ISurfaceComposer::gpu_info_t* gpu) = 0;
-
-    virtual status_t            friendlyRevoke() = 0;
-    
-    // used for debugging only...
-    virtual sp<SimpleBestFitAllocator> getAllocator() const  = 0;
-    virtual pid_t getOwner() const = 0;
-    virtual void unconditionalRevoke() = 0;
-};
-
-// ---------------------------------------------------------------------------
-
-class GPUFactory
-{    
-public:
-    // the gpu factory
-    static sp<GPUHardwareInterface> getGPU();
-};
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-
-#endif // ANDROID_GPU_HARDWARE_H
diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp
index 96395a8..f5a5a0b 100644
--- a/libs/surfaceflinger/Layer.cpp
+++ b/libs/surfaceflinger/Layer.cpp
@@ -14,26 +14,24 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "SurfaceFlinger"
-
 #include <stdlib.h>
 #include <stdint.h>
 #include <sys/types.h>
 
 #include <cutils/properties.h>
+#include <cutils/native_handle.h>
 
 #include <utils/Errors.h>
 #include <utils/Log.h>
 #include <utils/StopWatch.h>
 
+#include <ui/GraphicBuffer.h>
 #include <ui/PixelFormat.h>
-#include <ui/EGLDisplaySurface.h>
+#include <ui/Surface.h>
 
 #include "clz.h"
 #include "Layer.h"
-#include "LayerBitmap.h"
 #include "SurfaceFlinger.h"
-#include "VRamHeap.h"
 #include "DisplayHardware/DisplayHardware.h"
 
 
@@ -49,178 +47,330 @@
 
 // ---------------------------------------------------------------------------
 
-Layer::Layer(SurfaceFlinger* flinger, DisplayID display, Client* c, int32_t i)
+Layer::Layer(SurfaceFlinger* flinger, DisplayID display, 
+        const sp<Client>& c, int32_t i)
     :   LayerBaseClient(flinger, display, c, i),
         mSecure(false),
-        mFrontBufferIndex(1),
+        mNoEGLImageForSwBuffers(false),
         mNeedsBlending(true),
-        mResizeTransactionDone(false),
-        mTextureName(-1U), mTextureWidth(0), mTextureHeight(0)
+        mNeedsDithering(false)
 {
     // no OpenGL operation is possible here, since we might not be
     // in the OpenGL thread.
+    mFrontBufferIndex = lcblk->getFrontBuffer();
 }
 
 Layer::~Layer()
 {
-    client->free(clientIndex());
-    // this should always be called from the OpenGL thread
-    if (mTextureName != -1U) {
-        //glDeleteTextures(1, &mTextureName);
-        deletedTextures.add(mTextureName);
-    }
+    destroy();
+    // the actual buffers will be destroyed here
 }
 
-void Layer::initStates(uint32_t w, uint32_t h, uint32_t flags)
+void Layer::destroy()
 {
-    LayerBase::initStates(w,h,flags);
-
-    if (flags & ISurfaceComposer::eDestroyBackbuffer)
-        lcblk->flags |= eNoCopyBack;
+    for (size_t i=0 ; i<NUM_BUFFERS ; i++) {
+        if (mTextures[i].name != -1U) {
+            glDeleteTextures(1, &mTextures[i].name);
+            mTextures[i].name = -1U;
+        }
+        if (mTextures[i].image != EGL_NO_IMAGE_KHR) {
+            EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
+            eglDestroyImageKHR(dpy, mTextures[i].image);
+            mTextures[i].image = EGL_NO_IMAGE_KHR;
+        }
+        Mutex::Autolock _l(mLock);
+        mBuffers[i].clear();
+        mWidth = mHeight = 0;
+    }
+    mSurface.clear();
 }
 
-sp<LayerBaseClient::Surface> Layer::getSurface() const
+sp<LayerBaseClient::Surface> Layer::createSurface() const
 {
     return mSurface;
 }
 
-status_t Layer::setBuffers( Client* client,
-                            uint32_t w, uint32_t h,
+status_t Layer::ditch()
+{
+    // the layer is not on screen anymore. free as much resources as possible
+    destroy();
+    return NO_ERROR;
+}
+
+status_t Layer::setBuffers( uint32_t w, uint32_t h,
                             PixelFormat format, uint32_t flags)
 {
+    // this surfaces pixel format
     PixelFormatInfo info;
     status_t err = getPixelFormatInfo(format, &info);
     if (err) return err;
 
-    // TODO: if eHardware is explicitly requested, we should fail
-    // on systems where we can't allocate memory that can be used with
-    // DMA engines for instance.
+    // the display's pixel format
+    const DisplayHardware& hw(graphicPlane(0).displayHardware());
+    PixelFormatInfo displayInfo;
+    getPixelFormatInfo(hw.getFormat(), &displayInfo);
+    const uint32_t hwFlags = hw.getFlags();
     
-    // FIXME: we always ask for hardware for now (this should come from copybit)
-    flags |= ISurfaceComposer::eHardware;
-
-    const uint32_t memory_flags = flags & 
-            (ISurfaceComposer::eGPU | 
-             ISurfaceComposer::eHardware | 
-             ISurfaceComposer::eSecure);
-    
-    // pixel-alignment. the final alignment may be bigger because
-    // we always force a 4-byte aligned bpr.
-    uint32_t alignment = 1;
-
-    if ((flags & ISurfaceComposer::eGPU) && (mFlinger->getGPU() != 0)) {
-        // FIXME: this value should come from the h/w
-        alignment = 8; 
-        // FIXME: this is msm7201A specific, as its GPU only supports
-        // BGRA_8888.
-        if (format == PIXEL_FORMAT_RGBA_8888) {
-            format = PIXEL_FORMAT_BGRA_8888;
-        }
-    }
-
+    mFormat = format;
+    mWidth = w;
+    mHeight = h;
     mSecure = (flags & ISurfaceComposer::eSecure) ? true : false;
     mNeedsBlending = (info.h_alpha - info.l_alpha) > 0;
-    sp<MemoryDealer> allocators[2];
-    for (int i=0 ; i<2 ; i++) {
-        allocators[i] = client->createAllocator(memory_flags);
-        if (allocators[i] == 0)
-            return NO_MEMORY;
-        mBuffers[i].init(allocators[i]);
-        int err = mBuffers[i].setBits(w, h, alignment, format, LayerBitmap::SECURE_BITS);
-        if (err != NO_ERROR)
-            return err;
-        mBuffers[i].clear(); // clear the bits for security
-        mBuffers[i].getInfo(lcblk->surface + i);
+    mNoEGLImageForSwBuffers = !(hwFlags & DisplayHardware::CACHED_BUFFERS);
+    
+    // we use the red index
+    int displayRedSize = displayInfo.getSize(PixelFormatInfo::INDEX_RED);
+    int layerRedsize = info.getSize(PixelFormatInfo::INDEX_RED);
+    mNeedsDithering = layerRedsize > displayRedSize;
+
+    for (size_t i=0 ; i<NUM_BUFFERS ; i++) {
+        mBuffers[i] = new GraphicBuffer();
     }
-
-    mSurface = new Surface(clientIndex(),
-            allocators[0]->getMemoryHeap(),
-            allocators[1]->getMemoryHeap(),
-            mIdentity);
-
+    mSurface = new SurfaceLayer(mFlinger, clientIndex(), this);
     return NO_ERROR;
 }
 
 void Layer::reloadTexture(const Region& dirty)
 {
-    if (UNLIKELY(mTextureName == -1U)) {
-        // create the texture name the first time
-        // can't do that in the ctor, because it runs in another thread.
-        mTextureName = createTexture();
-    }
-    const GGLSurface& t(frontBuffer().surface());
-    loadTexture(dirty, mTextureName, t, mTextureWidth, mTextureHeight);
-}
+    Mutex::Autolock _l(mLock);
+    sp<GraphicBuffer> buffer(getFrontBufferLocked());
+    int index = mFrontBufferIndex;
 
+    // create the new texture name if needed
+    if (UNLIKELY(mTextures[index].name == -1U)) {
+        mTextures[index].name = createTexture();
+        mTextures[index].width = 0;
+        mTextures[index].height = 0;
+    }
+
+#ifdef EGL_ANDROID_image_native_buffer
+    if (mFlags & DisplayHardware::DIRECT_TEXTURE) {
+        if (buffer->usage & GraphicBuffer::USAGE_HW_TEXTURE) {
+            if (mTextures[index].dirty) {
+                initializeEglImage(buffer, &mTextures[index]);
+            }
+        } else {
+            if (mHybridBuffer==0 || (mHybridBuffer->width != buffer->width ||
+                    mHybridBuffer->height != buffer->height)) {
+                mHybridBuffer.clear();
+                mHybridBuffer = new GraphicBuffer(
+                        buffer->width, buffer->height, buffer->format,
+                        GraphicBuffer::USAGE_SW_WRITE_OFTEN |
+                        GraphicBuffer::USAGE_HW_TEXTURE);
+                initializeEglImage(
+                        mHybridBuffer, &mTextures[0]);
+            }
+
+            GGLSurface t;
+            status_t res = buffer->lock(&t, GRALLOC_USAGE_SW_READ_OFTEN);
+            LOGE_IF(res, "error %d (%s) locking buffer %p",
+                    res, strerror(res), buffer.get());
+            if (res == NO_ERROR) {
+                Texture* const texture(&mTextures[0]);
+
+                glBindTexture(GL_TEXTURE_2D, texture->name);
+
+                sp<GraphicBuffer> buf(mHybridBuffer);
+                void* vaddr;
+                res = buf->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN, &vaddr);
+                if (res == NO_ERROR) {
+                    int bpp = 0;
+                    switch (t.format) {
+                    case GGL_PIXEL_FORMAT_RGB_565:
+                    case GGL_PIXEL_FORMAT_RGBA_4444:
+                        bpp = 2;
+                        break;
+                    case GGL_PIXEL_FORMAT_RGBA_8888:
+                    case GGL_PIXEL_FORMAT_RGBX_8888:
+                        bpp = 4;
+                        break;
+                    case GGL_PIXEL_FORMAT_YCbCr_422_SP:
+                    case GGL_PIXEL_FORMAT_YCbCr_420_SP:
+                        // just show the Y plane of YUV buffers
+                        bpp = 1;
+                        break;
+                    default:
+                        // oops, we don't handle this format!
+                        LOGE("layer %p, texture=%d, using format %d, which is not "
+                                "supported by the GL", this, texture->name, t.format);
+                    }
+                    if (bpp) {
+                        const Rect bounds(dirty.getBounds());
+                        size_t src_stride = t.stride;
+                        size_t dst_stride = buf->stride;
+                        if (src_stride == dst_stride &&
+                            bounds.width() == t.width &&
+                            bounds.height() == t.height)
+                        {
+                            memcpy(vaddr, t.data, t.height * t.stride * bpp);
+                        } else {
+                            GLubyte const * src = t.data +
+                                (bounds.left + bounds.top * src_stride) * bpp;
+                            GLubyte * dst = (GLubyte *)vaddr +
+                                (bounds.left + bounds.top * dst_stride) * bpp;
+                            const size_t length = bounds.width() * bpp;
+                            size_t h = bounds.height();
+                            src_stride *= bpp;
+                            dst_stride *= bpp;
+                            while (h--) {
+                                memcpy(dst, src, length);
+                                dst += dst_stride;
+                                src += src_stride;
+                            }
+                        }
+                    }
+                    buf->unlock();
+                }
+                buffer->unlock();
+            }
+        }
+    } else
+#endif
+    {
+        for (size_t i=0 ; i<NUM_BUFFERS ; i++) {
+            mTextures[i].image = EGL_NO_IMAGE_KHR;
+        }
+        GGLSurface t;
+        status_t res = buffer->lock(&t, GRALLOC_USAGE_SW_READ_OFTEN);
+        LOGE_IF(res, "error %d (%s) locking buffer %p",
+                res, strerror(res), buffer.get());
+        if (res == NO_ERROR) {
+            loadTexture(&mTextures[0], dirty, t);
+            buffer->unlock();
+        }
+    }
+}
 
 void Layer::onDraw(const Region& clip) const
 {
-    if (UNLIKELY(mTextureName == -1LU)) {
-        //LOGW("Layer %p doesn't have a texture", this);
+    int index = mFrontBufferIndex;
+    if (mTextures[index].image == EGL_NO_IMAGE_KHR)
+        index = 0;
+    GLuint textureName = mTextures[index].name;
+    if (UNLIKELY(textureName == -1LU)) {
         // the texture has not been created yet, this Layer has
         // in fact never been drawn into. this happens frequently with
         // SurfaceView.
         clearWithOpenGL(clip);
         return;
     }
-
-    const DisplayHardware& hw(graphicPlane(0).displayHardware());
-    const LayerBitmap& front(frontBuffer());
-    const GGLSurface& t(front.surface());
-
-    status_t err = NO_ERROR;
-    const int can_use_copybit = canUseCopybit();
-    if (can_use_copybit)  {
-        // StopWatch watch("copybit");
-        const State& s(drawingState());
-
-        copybit_image_t dst;
-        hw.getDisplaySurface(&dst);
-        const copybit_rect_t& drect
-            = reinterpret_cast<const copybit_rect_t&>(mTransformedBounds);
-
-        copybit_image_t src;
-        front.getBitmapSurface(&src);
-        copybit_rect_t srect = { 0, 0, t.width, t.height };
-
-        copybit_device_t* copybit = mFlinger->getBlitEngine();
-        copybit->set_parameter(copybit, COPYBIT_TRANSFORM, getOrientation());
-        copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, s.alpha);
-        copybit->set_parameter(copybit, COPYBIT_DITHER,
-                s.flags & ISurfaceComposer::eLayerDither ?
-                        COPYBIT_ENABLE : COPYBIT_DISABLE);
-
-        region_iterator it(clip);
-        err = copybit->stretch(copybit, &dst, &src, &drect, &srect, &it);
-    }
-
-    if (!can_use_copybit || err) {
-        drawWithOpenGL(clip, mTextureName, t);
-    }
+    drawWithOpenGL(clip, mTextures[index]);
 }
 
-status_t Layer::reallocateBuffer(int32_t index, uint32_t w, uint32_t h)
+sp<GraphicBuffer> Layer::requestBuffer(int index, int usage)
 {
-    LOGD_IF(DEBUG_RESIZE,
-                "reallocateBuffer (layer=%p), "
-                "requested (%dx%d), "
-                "index=%d, (%dx%d), (%dx%d)",
-                this,
-                int(w), int(h),
-                int(index),
-                int(mBuffers[0].width()), int(mBuffers[0].height()),
-                int(mBuffers[1].width()), int(mBuffers[1].height()));
+    sp<GraphicBuffer> buffer;
 
-    status_t err = mBuffers[index].resize(w, h);
-    if (err == NO_ERROR) {
-        mBuffers[index].getInfo(lcblk->surface + index);
-    } else {
-        LOGE("resizing buffer %d to (%u,%u) failed [%08x] %s",
-            index, w, h, err, strerror(err));
-        // XXX: what to do, what to do? We could try to free some
-        // hidden surfaces, instead of killing this one?
+    // this ensures our client doesn't go away while we're accessing
+    // the shared area.
+    sp<Client> ourClient(client.promote());
+    if (ourClient == 0) {
+        // oops, the client is already gone
+        return buffer;
     }
-    return err;
+
+    /*
+     * This is called from the client's Surface::dequeue(). This can happen
+     * at any time, especially while we're in the middle of using the
+     * buffer 'index' as our front buffer.
+     * 
+     * Make sure the buffer we're resizing is not the front buffer and has been
+     * dequeued. Once this condition is asserted, we are guaranteed that this
+     * buffer cannot become the front buffer under our feet, since we're called
+     * from Surface::dequeue()
+     */
+    status_t err = lcblk->assertReallocate(index);
+    LOGE_IF(err, "assertReallocate(%d) failed (%s)", index, strerror(-err));
+    if (err != NO_ERROR) {
+        // the surface may have died
+        return buffer;
+    }
+
+    uint32_t w, h;
+    { // scope for the lock
+        Mutex::Autolock _l(mLock);
+        w = mWidth;
+        h = mHeight;
+        buffer = mBuffers[index];
+        
+        // destroy() could have been called before we get here, we log it
+        // because it's uncommon, and the code below should handle it
+        LOGW_IF(buffer==0, 
+                "mBuffers[%d] is null (mWidth=%d, mHeight=%d)",
+                index, w, h);
+        
+        mBuffers[index].clear();
+    }
+
+    const uint32_t effectiveUsage = getEffectiveUsage(usage);
+    if (buffer!=0 && buffer->getStrongCount() == 1) {
+        err = buffer->reallocate(w, h, mFormat, effectiveUsage);
+    } else {
+        // here we have to reallocate a new buffer because we could have a
+        // client in our process with a reference to it (eg: status bar),
+        // and we can't release the handle under its feet.
+        buffer.clear();
+        buffer = new GraphicBuffer(w, h, mFormat, effectiveUsage);
+        err = buffer->initCheck();
+    }
+
+    if (err || buffer->handle == 0) {
+        LOGE_IF(err || buffer->handle == 0,
+                "Layer::requestBuffer(this=%p), index=%d, w=%d, h=%d failed (%s)",
+                this, index, w, h, strerror(-err));
+    } else {
+        LOGD_IF(DEBUG_RESIZE,
+                "Layer::requestBuffer(this=%p), index=%d, w=%d, h=%d, handle=%p",
+                this, index, w, h, buffer->handle);
+    }
+
+    if (err == NO_ERROR && buffer->handle != 0) {
+        Mutex::Autolock _l(mLock);
+        if (mWidth && mHeight) {
+            // and we have new buffer
+            mBuffers[index] = buffer;
+            // texture is now dirty...
+            mTextures[index].dirty = true;
+        } else {
+            // oops we got killed while we were allocating the buffer
+            buffer.clear();
+        }
+    }
+    return buffer;
+}
+
+uint32_t Layer::getEffectiveUsage(uint32_t usage) const
+{
+    /*
+     *  buffers used for software rendering, but h/w composition
+     *  are allocated with SW_READ_OFTEN | SW_WRITE_OFTEN | HW_TEXTURE
+     *
+     *  buffers used for h/w rendering and h/w composition
+     *  are allocated with  HW_RENDER | HW_TEXTURE
+     *
+     *  buffers used with h/w rendering and either NPOT or no egl_image_ext
+     *  are allocated with SW_READ_RARELY | HW_RENDER
+     *
+     */
+
+    if (mSecure) {
+        // secure buffer, don't store it into the GPU
+        usage = GraphicBuffer::USAGE_SW_READ_OFTEN |
+                GraphicBuffer::USAGE_SW_WRITE_OFTEN;
+    } else {
+        // it's allowed to modify the usage flags here, but generally
+        // the requested flags should be honored.
+        if (mNoEGLImageForSwBuffers) {
+            if (usage & GraphicBuffer::USAGE_HW_MASK) {
+                // request EGLImage for h/w buffers only
+                usage |= GraphicBuffer::USAGE_HW_TEXTURE;
+            }
+        } else {
+            // request EGLImage for all buffers
+            usage |= GraphicBuffer::USAGE_HW_TEXTURE;
+        }
+    }
+    return usage;
 }
 
 uint32_t Layer::doTransaction(uint32_t flags)
@@ -228,113 +378,44 @@
     const Layer::State& front(drawingState());
     const Layer::State& temp(currentState());
 
-    // the test front.{w|h} != temp.{w|h} is not enough because it is possible
-    // that the size changed back to its previous value before the buffer
-    // was resized (in the eLocked case below), in which case, we still
-    // need to execute the code below so the clients have a chance to be
-    // release. resze() deals with the fact that the size can be the same.
-
-    /*
-     *  Various states we could be in...
-
-         resize = state & eResizeRequested;
-         if (backbufferChanged) {
-             if (resize == 0) {
-                 // ERROR, the resized buffer doesn't have its resize flag set
-             } else if (resize == mask) {
-                 // ERROR one of the buffer has already been resized
-             } else if (resize == mask ^ eResizeRequested) {
-                 // ERROR, the resized buffer doesn't have its resize flag set
-             } else if (resize == eResizeRequested) {
-                 // OK, Normal case, proceed with resize
-             }
-         } else {
-             if (resize == 0) {
-                 // OK, nothing special, do nothing
-             } else if (resize == mask) {
-                 // restarted transaction, do nothing
-             } else if (resize == mask ^ eResizeRequested) {
-                 // restarted transaction, do nothing
-             } else if (resize == eResizeRequested) {
-                 // OK, size reset to previous value, proceed with resize
-             }
-         }
-     */
-
-    // Index of the back buffer
-    const bool backbufferChanged = (front.w != temp.w) || (front.h != temp.h);
-    const uint32_t state = lcblk->swapState;
-    const int32_t clientBackBufferIndex = layer_cblk_t::backBuffer(state);
-    const uint32_t mask = clientBackBufferIndex ? eResizeBuffer1 : eResizeBuffer0;
-    uint32_t resizeFlags = state & eResizeRequested;
-
-    if (UNLIKELY(backbufferChanged && (resizeFlags != eResizeRequested))) {
-        LOGE(   "backbuffer size changed, but both resize flags are not set! "
-                "(layer=%p), state=%08x, requested (%dx%d), drawing (%d,%d), "
-                "index=%d, (%dx%d), (%dx%d)",
-                this,  state,
-                int(temp.w), int(temp.h),
-                int(drawingState().w), int(drawingState().h),
-                int(clientBackBufferIndex),
-                int(mBuffers[0].width()), int(mBuffers[0].height()),
-                int(mBuffers[1].width()), int(mBuffers[1].height()));
-        // if we get there we're pretty screwed. the only reasonable
-        // thing to do is to pretend we should do the resize since
-        // backbufferChanged is set (this also will give a chance to
-        // client to get unblocked)
-        resizeFlags = eResizeRequested;
-    }
-
-    if (resizeFlags == eResizeRequested)  {
-        // NOTE: asserting that clientBackBufferIndex!=mFrontBufferIndex
-        // here, would be wrong and misleading because by this point
-        // mFrontBufferIndex has not been updated yet.
-
+    if ((front.requested_w != temp.requested_w) || 
+        (front.requested_h != temp.requested_h)) {
+        // the size changed, we need to ask our client to request a new buffer
         LOGD_IF(DEBUG_RESIZE,
-                    "resize (layer=%p), state=%08x, "
-                    "requested (%dx%d), "
-                    "drawing (%d,%d), "
-                    "index=%d, (%dx%d), (%dx%d)",
-                    this,  state,
-                    int(temp.w), int(temp.h),
-                    int(drawingState().w), int(drawingState().h),
-                    int(clientBackBufferIndex),
-                    int(mBuffers[0].width()), int(mBuffers[0].height()),
-                    int(mBuffers[1].width()), int(mBuffers[1].height()));
+                    "resize (layer=%p), requested (%dx%d), "
+                    "drawing (%d,%d), (%dx%d), (%dx%d)",
+                    this, 
+                    int(temp.requested_w), int(temp.requested_h),
+                    int(front.requested_w), int(front.requested_h),
+                    int(mBuffers[0]->getWidth()), int(mBuffers[0]->getHeight()),
+                    int(mBuffers[1]->getWidth()), int(mBuffers[1]->getHeight()));
 
-        if (state & eLocked) {
-            // if the buffer is locked, we can't resize anything because
-            // - the backbuffer is currently in use by the user
-            // - the front buffer is being shown
-            // We just act as if the transaction didn't happen and we
-            // reschedule it later...
-            flags |= eRestartTransaction;
-        } else {
-            // This buffer needs to be resized
-            status_t err =
-                resize(clientBackBufferIndex, temp.w, temp.h, "transaction");
-            if (err == NO_ERROR) {
-                const uint32_t mask = clientBackBufferIndex ? eResizeBuffer1 : eResizeBuffer0;
-                android_atomic_and(~mask, &(lcblk->swapState));
-                // since a buffer became available, we can let the client go...
-                mFlinger->scheduleBroadcast(client);
-                mResizeTransactionDone = true;
-
-                // we're being resized and there is a freeze display request,
-                // acquire a freeze lock, so that the screen stays put
-                // until we've redrawn at the new size; this is to avoid
-                // glitches upon orientation changes.
-                if (mFlinger->hasFreezeRequest()) {
-                    // if the surface is hidden, don't try to acquire the
-                    // freeze lock, since hidden surfaces may never redraw
-                    if (!(front.flags & ISurfaceComposer::eLayerHidden)) {
-                        mFreezeLock = mFlinger->getFreezeLock();
-                    }
-                }
+        // we're being resized and there is a freeze display request,
+        // acquire a freeze lock, so that the screen stays put
+        // until we've redrawn at the new size; this is to avoid
+        // glitches upon orientation changes.
+        if (mFlinger->hasFreezeRequest()) {
+            // if the surface is hidden, don't try to acquire the
+            // freeze lock, since hidden surfaces may never redraw
+            if (!(front.flags & ISurfaceComposer::eLayerHidden)) {
+                mFreezeLock = mFlinger->getFreezeLock();
             }
         }
+
+        // this will make sure LayerBase::doTransaction doesn't update
+        // the drawing state's size
+        Layer::State& editDraw(mDrawingState);
+        editDraw.requested_w = temp.requested_w;
+        editDraw.requested_h = temp.requested_h;
+
+        // record the new size, form this point on, when the client request a
+        // buffer, it'll get the new size.
+        setDrawingSize(temp.requested_w, temp.requested_h);
+
+        // all buffers need reallocation
+        lcblk->reallocate();
     }
-    
+
     if (temp.sequence != front.sequence) {
         if (temp.flags & ISurfaceComposer::eLayerHidden || temp.alpha == 0) {
             // this surface is now hidden, so it shouldn't hold a freeze lock
@@ -346,54 +427,10 @@
     return LayerBase::doTransaction(flags);
 }
 
-status_t Layer::resize(
-        int32_t clientBackBufferIndex,
-        uint32_t width, uint32_t height,
-        const char* what)
-{
-    /*
-     * handle resize (backbuffer and frontbuffer reallocation)
-     */
-
-    const LayerBitmap& clientBackBuffer(mBuffers[clientBackBufferIndex]);
-
-    // if the new (transaction) size is != from the the backbuffer
-    // then we need to reallocate the backbuffer
-    bool backbufferChanged = (clientBackBuffer.width()  != width) ||
-                             (clientBackBuffer.height() != height);
-
-    LOGD_IF(!backbufferChanged,
-            "(%s) eResizeRequested (layer=%p), but size not changed: "
-            "requested (%dx%d), drawing (%d,%d), current (%d,%d),"
-            "state=%08lx, index=%d, (%dx%d), (%dx%d)",
-            what, this,
-            int(width), int(height),
-            int(drawingState().w), int(drawingState().h),
-            int(currentState().w), int(currentState().h),
-            long(lcblk->swapState),
-            int(clientBackBufferIndex),
-            int(mBuffers[0].width()), int(mBuffers[0].height()),
-            int(mBuffers[1].width()), int(mBuffers[1].height()));
-
-    // this can happen when changing the size back and forth quickly
-    status_t err = NO_ERROR;
-    if (backbufferChanged) {
-        err = reallocateBuffer(clientBackBufferIndex, width, height);
-    }
-    if (UNLIKELY(err != NO_ERROR)) {
-        // couldn't reallocate the surface
-        android_atomic_write(eInvalidSurface, &lcblk->swapState);
-        memset(lcblk->surface+clientBackBufferIndex, 0, sizeof(surface_info_t));
-    }
-    return err;
-}
-
-void Layer::setSizeChanged(uint32_t w, uint32_t h)
-{
-    LOGD_IF(DEBUG_RESIZE,
-            "setSizeChanged w=%d, h=%d (old: w=%d, h=%d)",
-            w, h, mCurrentState.w, mCurrentState.h);
-    android_atomic_or(eResizeRequested, &(lcblk->swapState));
+void Layer::setDrawingSize(uint32_t w, uint32_t h) {
+    Mutex::Autolock _l(mLock);
+    mWidth = w;
+    mHeight = h;
 }
 
 // ----------------------------------------------------------------------------
@@ -402,128 +439,61 @@
 
 void Layer::lockPageFlip(bool& recomputeVisibleRegions)
 {
-    uint32_t state = android_atomic_or(eBusy, &(lcblk->swapState));
-    // preemptively block the client, because he might set
-    // eFlipRequested at any time and want to use this buffer
-    // for the next frame. This will be unset below if it
-    // turns out we didn't need it.
-
-    uint32_t mask = eInvalidSurface | eFlipRequested | eResizeRequested;
-    if (!(state & mask))
-        return;
-
-    if (UNLIKELY(state & eInvalidSurface)) {
-        // if eInvalidSurface is set, this means the surface
-        // became invalid during a transaction (NO_MEMORY for instance)
-        mFlinger->scheduleBroadcast(client);
+    ssize_t buf = lcblk->retireAndLock();
+    if (buf < NO_ERROR) {
+        //LOGW("nothing to retire (%s)", strerror(-buf));
+        // NOTE: here the buffer is locked because we will used 
+        // for composition later in the loop
         return;
     }
+    
+    // we retired a buffer, which becomes the new front buffer
+    mFrontBufferIndex = buf;
 
-    if (UNLIKELY(state & eFlipRequested)) {
-        uint32_t oldState;
-        mPostedDirtyRegion = post(&oldState, recomputeVisibleRegions);
-        if (oldState & eNextFlipPending) {
-            // Process another round (we know at least a buffer
-            // is ready for that client).
-            mFlinger->signalEvent();
-        }
-    }
-}
+    // get the dirty region
+    sp<GraphicBuffer> newFrontBuffer(getBuffer(buf));
+    const Region dirty(lcblk->getDirtyRegion(buf));
+    mPostedDirtyRegion = dirty.intersect( newFrontBuffer->getBounds() );
 
-Region Layer::post(uint32_t* previousSate, bool& recomputeVisibleRegions)
-{
-    // atomically swap buffers and (re)set eFlipRequested
-    int32_t oldValue, newValue;
-    layer_cblk_t * const lcblk = this->lcblk;
-    do {
-        oldValue = lcblk->swapState;
-            // get the current value
+    const Layer::State& front(drawingState());
+    if (newFrontBuffer->getWidth()  == front.requested_w &&
+        newFrontBuffer->getHeight() == front.requested_h)
+    {
+        if ((front.w != front.requested_w) ||
+            (front.h != front.requested_h))
+        {
+            // Here we pretend the transaction happened by updating the
+            // current and drawing states. Drawing state is only accessed
+            // in this thread, no need to have it locked
+            Layer::State& editDraw(mDrawingState);
+            editDraw.w = editDraw.requested_w;
+            editDraw.h = editDraw.requested_h;
 
-        LOG_ASSERT(oldValue&eFlipRequested,
-            "eFlipRequested not set, yet we're flipping! (state=0x%08lx)",
-            long(oldValue));
+            // We also need to update the current state so that we don't
+            // end-up doing too much work during the next transaction.
+            // NOTE: We actually don't need hold the transaction lock here
+            // because State::w and State::h are only accessed from
+            // this thread
+            Layer::State& editTemp(currentState());
+            editTemp.w = editDraw.w;
+            editTemp.h = editDraw.h;
 
-        newValue = (oldValue ^ eIndex);
-            // swap buffers
-
-        newValue &= ~(eFlipRequested | eNextFlipPending);
-            // clear eFlipRequested and eNextFlipPending
-
-        if (oldValue & eNextFlipPending)
-            newValue |= eFlipRequested;
-            // if eNextFlipPending is set (second buffer already has something
-            // in it) we need to reset eFlipRequested because the client
-            // might never do it
-
-    } while(android_atomic_cmpxchg(oldValue, newValue, &(lcblk->swapState)));
-    *previousSate = oldValue;
-
-    const int32_t index = (newValue & eIndex) ^ 1;
-    mFrontBufferIndex = index;
-
-    // ... post the new front-buffer
-    Region dirty(lcblk->region + index);
-    dirty.andSelf(frontBuffer().bounds());
-
-    //LOGI("Did post oldValue=%08lx, newValue=%08lx, mFrontBufferIndex=%u\n",
-    //    oldValue, newValue, mFrontBufferIndex);
-    //dirty.dump("dirty");
-
-    if (UNLIKELY(oldValue & eResizeRequested)) {
-
-        LOGD_IF(DEBUG_RESIZE,
-                     "post (layer=%p), state=%08x, "
-                     "index=%d, (%dx%d), (%dx%d)",
-                     this,  newValue,
-                     int(1-index),
-                     int(mBuffers[0].width()), int(mBuffers[0].height()),
-                     int(mBuffers[1].width()), int(mBuffers[1].height()));
-
-        // here, we just posted the surface and we have resolved
-        // the front/back buffer indices. The client is blocked, so
-        // it cannot start using the new backbuffer.
-
-        // If the backbuffer was resized in THIS round, we actually cannot
-        // resize the frontbuffer because it has *just* been drawn (and we
-        // would have nothing to draw). In this case we just skip the resize
-        // it'll happen after the next page flip or during the next
-        // transaction.
-
-        const uint32_t mask = (1-index) ? eResizeBuffer1 : eResizeBuffer0;
-        if (mResizeTransactionDone && (newValue & mask)) {
-            // Resize the layer's second buffer only if the transaction
-            // happened. It may not have happened yet if eResizeRequested
-            // was set immediately after the "transactionRequested" test,
-            // in which case the drawing state's size would be wrong.
-            mFreezeLock.clear();
-            const Layer::State& s(drawingState());
-            if (resize(1-index, s.w, s.h, "post") == NO_ERROR) {
-                do {
-                    oldValue = lcblk->swapState;
-                    if ((oldValue & eResizeRequested) == eResizeRequested) {
-                        // ugh, another resize was requested since we processed
-                        // the first buffer, don't free the client, and let
-                        // the next transaction handle everything.
-                        break;
-                    }
-                    newValue = oldValue & ~mask;
-                } while(android_atomic_cmpxchg(oldValue, newValue, &(lcblk->swapState)));
-            }
-            mResizeTransactionDone = false;
+            // recompute visible region
             recomputeVisibleRegions = true;
-            this->contentDirty = true;
         }
+
+        // we now have the correct size, unfreeze the screen
+        mFreezeLock.clear();
     }
 
-    reloadTexture(dirty);
+    if (lcblk->getQueuedCount()) {
+        // signal an event if we have more buffers waiting
+        mFlinger->signalEvent();
+    }
 
-    return dirty;
-}
-
-Point Layer::getPhysicalSize() const
-{
-    const LayerBitmap& front(frontBuffer());
-    return Point(front.width(), front.height());
+    if (!mPostedDirtyRegion.isEmpty()) {
+        reloadTexture( mPostedDirtyRegion );
+    }
 }
 
 void Layer::unlockPageFlip(
@@ -544,23 +514,42 @@
         // is in screen space as well).
         dirtyRegion.andSelf(visibleRegionScreen);
         outDirtyRegion.orSelf(dirtyRegion);
-
-        // client could be blocked, so signal them so they get a
-        // chance to reevaluate their condition.
-        mFlinger->scheduleBroadcast(client);
     }
 }
 
 void Layer::finishPageFlip()
 {
-    if (LIKELY(!(lcblk->swapState & eInvalidSurface))) {
-        LOGE_IF(!(lcblk->swapState & eBusy),
-                "layer %p wasn't locked!", this);
-        android_atomic_and(~eBusy, &(lcblk->swapState));
-    }
-    mFlinger->scheduleBroadcast(client);
+    status_t err = lcblk->unlock( mFrontBufferIndex );
+    LOGE_IF(err!=NO_ERROR, 
+            "layer %p, buffer=%d wasn't locked!",
+            this, mFrontBufferIndex);
 }
 
+// ---------------------------------------------------------------------------
+
+Layer::SurfaceLayer::SurfaceLayer(const sp<SurfaceFlinger>& flinger,
+        SurfaceID id, const sp<Layer>& owner)
+    : Surface(flinger, id, owner->getIdentity(), owner)
+{
+}
+
+Layer::SurfaceLayer::~SurfaceLayer()
+{
+}
+
+sp<GraphicBuffer> Layer::SurfaceLayer::requestBuffer(int index, int usage)
+{
+    sp<GraphicBuffer> buffer;
+    sp<Layer> owner(getOwner());
+    if (owner != 0) {
+        LOGE_IF(uint32_t(index)>=NUM_BUFFERS,
+                "getBuffer() index (%d) out of range", index);
+        if (uint32_t(index) < NUM_BUFFERS) {
+            buffer = owner->requestBuffer(index, usage);
+        }
+    }
+    return buffer;
+}
 
 // ---------------------------------------------------------------------------
 
diff --git a/libs/surfaceflinger/Layer.h b/libs/surfaceflinger/Layer.h
index 2867f2b..1310ecc 100644
--- a/libs/surfaceflinger/Layer.h
+++ b/libs/surfaceflinger/Layer.h
@@ -20,14 +20,15 @@
 #include <stdint.h>
 #include <sys/types.h>
 
+#include <ui/GraphicBuffer.h>
 #include <ui/PixelFormat.h>
-
-#include <private/ui/SharedState.h>
-#include <private/ui/LayerState.h>
-
 #include <pixelflinger/pixelflinger.h>
 
-#include "LayerBitmap.h"
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+
 #include "LayerBase.h"
 #include "Transform.h"
 
@@ -36,12 +37,12 @@
 // ---------------------------------------------------------------------------
 
 class Client;
-class LayerBitmap;
-class MemoryDealer;
 class FreezeLock;
 
 // ---------------------------------------------------------------------------
 
+const size_t NUM_BUFFERS = 2;
+
 class Layer : public LayerBaseClient
 {
 public:    
@@ -49,68 +50,79 @@
     static const char* const typeID;
     virtual char const* getTypeID() const { return typeID; }
     virtual uint32_t getTypeInfo() const { return typeInfo; }
-
+    
                  Layer(SurfaceFlinger* flinger, DisplayID display,
-                         Client* c, int32_t i);
+                         const sp<Client>& client, int32_t i);
 
         virtual ~Layer();
 
-    inline PixelFormat pixelFormat() const {
-        return frontBuffer().pixelFormat();
-    }
+    status_t setBuffers(uint32_t w, uint32_t h, 
+            PixelFormat format, uint32_t flags=0);
 
-    status_t setBuffers(    Client* client,
-                            uint32_t w, uint32_t h,
-                            PixelFormat format, uint32_t flags=0);
+    void setDrawingSize(uint32_t w, uint32_t h);
 
     virtual void onDraw(const Region& clip) const;
-    virtual void initStates(uint32_t w, uint32_t h, uint32_t flags);
-    virtual void setSizeChanged(uint32_t w, uint32_t h);
     virtual uint32_t doTransaction(uint32_t transactionFlags);
-    virtual Point getPhysicalSize() const;
     virtual void lockPageFlip(bool& recomputeVisibleRegions);
     virtual void unlockPageFlip(const Transform& planeTransform, Region& outDirtyRegion);
     virtual void finishPageFlip();
     virtual bool needsBlending() const      { return mNeedsBlending; }
+    virtual bool needsDithering() const     { return mNeedsDithering; }
     virtual bool isSecure() const           { return mSecure; }
-    virtual GLuint getTextureName() const   { return mTextureName; }
-    virtual sp<Surface> getSurface() const;
-
-    const LayerBitmap& getBuffer(int i) const { return mBuffers[i]; }
-          LayerBitmap& getBuffer(int i)       { return mBuffers[i]; }
-
+    virtual sp<Surface> createSurface() const;
+    virtual status_t ditch();
+    
     // only for debugging
-    const sp<FreezeLock>&  getFreezeLock() const { return mFreezeLock; }
+    inline sp<GraphicBuffer> getBuffer(int i) { return mBuffers[i]; }
+    // only for debugging
+    inline const sp<FreezeLock>&  getFreezeLock() const { return mFreezeLock; }
+    // only for debugging
+    inline PixelFormat pixelFormat() const { return mFormat; }
 
 private:
-    inline const LayerBitmap&
-            frontBuffer() const { return getBuffer(mFrontBufferIndex); }
-    inline LayerBitmap&
-            frontBuffer()       { return getBuffer(mFrontBufferIndex); }
-    inline const LayerBitmap&
-            backBuffer() const  { return getBuffer(1-mFrontBufferIndex); }
-    inline LayerBitmap&
-            backBuffer()        { return getBuffer(1-mFrontBufferIndex); }
-
+    inline sp<GraphicBuffer> getFrontBufferLocked() {
+        return mBuffers[mFrontBufferIndex];
+    }
+ 
     void reloadTexture(const Region& dirty);
 
-    status_t resize(int32_t index, uint32_t w, uint32_t h, const char* what);
-    Region post(uint32_t* oldState, bool& recomputeVisibleRegions);
-    status_t reallocateBuffer(int32_t index, uint32_t w, uint32_t h);
+    uint32_t getEffectiveUsage(uint32_t usage) const;
 
+    sp<GraphicBuffer> requestBuffer(int index, int usage);
+    void destroy();
+
+    class SurfaceLayer : public LayerBaseClient::Surface {
+    public:
+        SurfaceLayer(const sp<SurfaceFlinger>& flinger,
+                SurfaceID id, const sp<Layer>& owner);
+        ~SurfaceLayer();
+    private:
+        virtual sp<GraphicBuffer> requestBuffer(int index, int usage);
+        sp<Layer> getOwner() const {
+            return static_cast<Layer*>(Surface::getOwner().get());
+        }
+    };
+    friend class SurfaceLayer;
+    
     sp<Surface>             mSurface;
 
             bool            mSecure;
-            LayerBitmap     mBuffers[2];
+            bool            mNoEGLImageForSwBuffers;
             int32_t         mFrontBufferIndex;
             bool            mNeedsBlending;
-            bool            mResizeTransactionDone;
+            bool            mNeedsDithering;
             Region          mPostedDirtyRegion;
             sp<FreezeLock>  mFreezeLock;
+            PixelFormat     mFormat;
             
-            GLuint          mTextureName;
-            GLuint          mTextureWidth;
-            GLuint          mTextureHeight;
+            // protected by mLock
+            sp<GraphicBuffer> mBuffers[NUM_BUFFERS];
+            Texture         mTextures[NUM_BUFFERS];
+            sp<GraphicBuffer> mHybridBuffer;
+            uint32_t        mWidth;
+            uint32_t        mHeight;
+            
+   mutable Mutex mLock;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/libs/surfaceflinger/LayerBase.cpp b/libs/surfaceflinger/LayerBase.cpp
index 0cf53f7..8003d22 100644
--- a/libs/surfaceflinger/LayerBase.cpp
+++ b/libs/surfaceflinger/LayerBase.cpp
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "SurfaceFlinger"
-
 #include <stdlib.h>
 #include <stdint.h>
 #include <sys/types.h>
 
 #include <utils/Errors.h>
 #include <utils/Log.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
 
 #include <GLES/gl.h>
 #include <GLES/glext.h>
@@ -30,17 +30,10 @@
 
 #include "clz.h"
 #include "LayerBase.h"
-#include "LayerBlur.h"
 #include "SurfaceFlinger.h"
 #include "DisplayHardware/DisplayHardware.h"
 
 
-// We don't honor the premultiplied alpha flags, which means that
-// premultiplied surface may be composed using a non-premultiplied
-// equation. We do this because it may be a lot faster on some hardware
-// The correct value is HONOR_PREMULTIPLIED_ALPHA = 1
-#define HONOR_PREMULTIPLIED_ALPHA   0
-
 namespace android {
 
 // ---------------------------------------------------------------------------
@@ -53,19 +46,14 @@
 
 // ---------------------------------------------------------------------------
 
-Vector<GLuint> LayerBase::deletedTextures; 
-
-int32_t LayerBase::sIdentity = 0;
-
 LayerBase::LayerBase(SurfaceFlinger* flinger, DisplayID display)
     : dpy(display), contentDirty(false),
       mFlinger(flinger),
       mTransformed(false),
+      mUseLinearFiltering(false),
       mOrientation(0),
-      mCanUseCopyBit(false),
       mTransactionFlags(0),
       mPremultipliedAlpha(true),
-      mIdentity(uint32_t(android_atomic_inc(&sIdentity))),
       mInvalidate(0)
 {
     const DisplayHardware& hw(flinger->graphicPlane(0).displayHardware());
@@ -95,26 +83,22 @@
     if (flags & ISurfaceComposer::eNonPremultiplied)
         mPremultipliedAlpha = false;
 
-    mCurrentState.z         = 0;
-    mCurrentState.w         = w;
-    mCurrentState.h         = h;
-    mCurrentState.alpha     = 0xFF;
-    mCurrentState.flags     = layerFlags;
-    mCurrentState.sequence  = 0;
+    mCurrentState.z             = 0;
+    mCurrentState.w             = w;
+    mCurrentState.h             = h;
+    mCurrentState.requested_w   = w;
+    mCurrentState.requested_h   = h;
+    mCurrentState.alpha         = 0xFF;
+    mCurrentState.flags         = layerFlags;
+    mCurrentState.sequence      = 0;
     mCurrentState.transform.set(0, 0);
 
     // drawing state & current state are identical
     mDrawingState = mCurrentState;
 }
 
-void LayerBase::commitTransaction(bool skipSize) {
-    const uint32_t w = mDrawingState.w;
-    const uint32_t h = mDrawingState.h;
+void LayerBase::commitTransaction() {
     mDrawingState = mCurrentState;
-    if (skipSize) {
-        mDrawingState.w = w;
-        mDrawingState.h = h;
-    }
 }
 void LayerBase::forceVisibilityTransaction() {
     // this can be called without SurfaceFlinger.mStateLock, but if we
@@ -133,9 +117,6 @@
     return android_atomic_or(flags, &mTransactionFlags);
 }
 
-void LayerBase::setSizeChanged(uint32_t w, uint32_t h) {
-}
-
 bool LayerBase::setPosition(int32_t x, int32_t y) {
     if (mCurrentState.transform.tx() == x && mCurrentState.transform.ty() == y)
         return false;
@@ -153,11 +134,10 @@
     return true;
 }
 bool LayerBase::setSize(uint32_t w, uint32_t h) {
-    if (mCurrentState.w == w && mCurrentState.h == h)
+    if (mCurrentState.requested_w == w && mCurrentState.requested_h == h)
         return false;
-    setSizeChanged(w, h);
-    mCurrentState.w = w;
-    mCurrentState.h = h;
+    mCurrentState.requested_w = w;
+    mCurrentState.requested_h = h;
     requestTransaction();
     return true;
 }
@@ -214,21 +194,39 @@
     const Layer::State& front(drawingState());
     const Layer::State& temp(currentState());
 
+    if ((front.requested_w != temp.requested_w) ||
+        (front.requested_h != temp.requested_h))  {
+        // resize the layer, set the physical size to the requested size
+        Layer::State& editTemp(currentState());
+        editTemp.w = temp.requested_w;
+        editTemp.h = temp.requested_h;
+    }
+
+    if ((front.w != temp.w) || (front.h != temp.h)) {
+        // invalidate and recompute the visible regions if needed
+        flags |= Layer::eVisibleRegion;
+        this->contentDirty = true;
+    }
+
     if (temp.sequence != front.sequence) {
         // invalidate and recompute the visible regions if needed
         flags |= eVisibleRegion;
         this->contentDirty = true;
-    }
-    
-    // Commit the transaction
-    commitTransaction(flags & eRestartTransaction);
-    return flags;
-}
 
-Point LayerBase::getPhysicalSize() const
-{
-    const Layer::State& front(drawingState());
-    return Point(front.w, front.h);
+        const bool linearFiltering = mUseLinearFiltering;
+        mUseLinearFiltering = false;
+        if (!(mFlags & DisplayHardware::SLOW_CONFIG)) {
+            // we may use linear filtering, if the matrix scales us
+            const uint8_t type = temp.transform.getType();
+            if (!temp.transform.preserveRects() || (type >= Transform::SCALE)) {
+                mUseLinearFiltering = true;
+            }
+        }
+    }
+
+    // Commit the transaction
+    commitTransaction();
+    return flags;
 }
 
 void LayerBase::validateVisibility(const Transform& planeTransform)
@@ -237,9 +235,8 @@
     const Transform tr(planeTransform * s.transform);
     const bool transformed = tr.transformed();
    
-    const Point size(getPhysicalSize());
-    uint32_t w = size.x;
-    uint32_t h = size.y;    
+    uint32_t w = s.w;
+    uint32_t h = s.h;    
     tr.transform(mVertices[0], 0, 0);
     tr.transform(mVertices[1], 0, h);
     tr.transform(mVertices[2], w, h);
@@ -265,43 +262,6 @@
     mTransformed = transformed;
     mLeft = tr.tx();
     mTop  = tr.ty();
-
-    // see if we can/should use 2D h/w with the new configuration
-    mCanUseCopyBit = false;
-    copybit_device_t* copybit = mFlinger->getBlitEngine();
-    if (copybit) { 
-        const int step = copybit->get(copybit, COPYBIT_ROTATION_STEP_DEG);
-        const int scaleBits = copybit->get(copybit, COPYBIT_SCALING_FRAC_BITS);
-        mCanUseCopyBit = true;
-        if ((mOrientation < 0) && (step > 1)) {
-            // arbitrary orientations not supported
-            mCanUseCopyBit = false;
-        } else if ((mOrientation > 0) && (step > 90)) {
-            // 90 deg rotations not supported
-            mCanUseCopyBit = false;
-        } else if ((tr.getType() & SkMatrix::kScale_Mask) && (scaleBits < 12)) { 
-            // arbitrary scaling not supported
-            mCanUseCopyBit = false;
-        }
-#if HONOR_PREMULTIPLIED_ALPHA 
-        else if (needsBlending() && mPremultipliedAlpha) {
-            // pre-multiplied alpha not supported
-            mCanUseCopyBit = false;
-        }
-#endif
-        else {
-            // here, we determined we can use copybit
-            if (tr.getType() & SkMatrix::kScale_Mask) {
-                // and we have scaling
-                if (!transparentRegionScreen.isRect()) {
-                    // we punt because blending is cheap (h/w) and the region is
-                    // complex, which may causes artifacts when copying
-                    // scaled content
-                    transparentRegionScreen.clear();
-                }
-            }
-        }
-    }
 }
 
 void LayerBase::lockPageFlip(bool& recomputeVisibleRegions)
@@ -329,8 +289,9 @@
 
 void LayerBase::drawRegion(const Region& reg) const
 {
-    Region::iterator iterator(reg);
-    if (iterator) {
+    Region::const_iterator it = reg.begin();
+    Region::const_iterator const end = reg.end();
+    if (it != end) {
         Rect r;
         const DisplayHardware& hw(graphicPlane(0).displayHardware());
         const int32_t fbWidth  = hw.getWidth();
@@ -338,7 +299,8 @@
         const GLshort vertices[][2] = { { 0, 0 }, { fbWidth, 0 }, 
                 { fbWidth, fbHeight }, { 0, fbHeight }  };
         glVertexPointer(2, GL_SHORT, 0, vertices);
-        while (iterator.iterate(&r)) {
+        while (it != end) {
+            const Rect& r = *it++;
             const GLint sy = fbHeight - (r.top + r.height());
             glScissor(r.left, sy, r.width(), r.height());
             glDrawArrays(GL_TRIANGLE_FAN, 0, 4); 
@@ -385,55 +347,52 @@
     glBindTexture(GL_TEXTURE_2D, textureName);
     glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
     glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-    if (mFlags & DisplayHardware::SLOW_CONFIG) {
-        glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-        glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-    } else {
-        glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-        glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-    }
+    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
     return textureName;
 }
 
+void LayerBase::clearWithOpenGL(const Region& clip, GLclampx red,
+                                GLclampx green, GLclampx blue,
+                                GLclampx alpha) const
+{
+    const DisplayHardware& hw(graphicPlane(0).displayHardware());
+    const uint32_t fbHeight = hw.getHeight();
+    glColor4x(red,green,blue,alpha);
+    glDisable(GL_TEXTURE_2D);
+    glDisable(GL_BLEND);
+    glDisable(GL_DITHER);
+
+    Region::const_iterator it = clip.begin();
+    Region::const_iterator const end = clip.end();
+    glEnable(GL_SCISSOR_TEST);
+    glVertexPointer(2, GL_FIXED, 0, mVertices);
+    while (it != end) {
+        const Rect& r = *it++;
+        const GLint sy = fbHeight - (r.top + r.height());
+        glScissor(r.left, sy, r.width(), r.height());
+        glDrawArrays(GL_TRIANGLE_FAN, 0, 4); 
+    }
+}
+
 void LayerBase::clearWithOpenGL(const Region& clip) const
 {
-    const DisplayHardware& hw(graphicPlane(0).displayHardware());
-    const uint32_t fbHeight = hw.getHeight();
-    glColor4x(0,0,0,0);
-    glDisable(GL_TEXTURE_2D);
-    glDisable(GL_BLEND);
-    glDisable(GL_DITHER);
-    Rect r;
-    Region::iterator iterator(clip);
-    if (iterator) {
-        glEnable(GL_SCISSOR_TEST);
-        glVertexPointer(2, GL_FIXED, 0, mVertices);
-        while (iterator.iterate(&r)) {
-            const GLint sy = fbHeight - (r.top + r.height());
-            glScissor(r.left, sy, r.width(), r.height());
-            glDrawArrays(GL_TRIANGLE_FAN, 0, 4); 
-        }
-    }
+    clearWithOpenGL(clip,0,0,0,0);
 }
 
-void LayerBase::drawWithOpenGL(const Region& clip,
-        GLint textureName, const GGLSurface& t, int transform) const
+void LayerBase::drawWithOpenGL(const Region& clip, const Texture& texture) const
 {
     const DisplayHardware& hw(graphicPlane(0).displayHardware());
     const uint32_t fbHeight = hw.getHeight();
     const State& s(drawingState());
-
+    
     // bind our texture
-    validateTexture(textureName);
+    validateTexture(texture.name);
+    uint32_t width  = texture.width; 
+    uint32_t height = texture.height;
+    
     glEnable(GL_TEXTURE_2D);
 
-    // Dithering...
-    if (s.flags & ISurfaceComposer::eLayerDither) {
-        glEnable(GL_DITHER);
-    } else {
-        glDisable(GL_DITHER);
-    }
-
     if (UNLIKELY(s.alpha < 0xFF)) {
         // We have an alpha-modulation. We need to modulate all
         // texture components by alpha because we're always using 
@@ -468,77 +427,55 @@
         }
     }
 
+    Region::const_iterator it = clip.begin();
+    Region::const_iterator const end = clip.end();
     if (UNLIKELY(transformed()
             || !(mFlags & DisplayHardware::DRAW_TEXTURE_EXTENSION) )) 
     {
         //StopWatch watch("GL transformed");
-        Region::iterator iterator(clip);
-        if (iterator) {
-            // always use high-quality filtering with fast configurations
-            bool fast = !(mFlags & DisplayHardware::SLOW_CONFIG);
-            if (!fast && s.flags & ISurfaceComposer::eLayerFilter) {
-                glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-                glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-            }            
-            const GLfixed texCoords[4][2] = {
-                    { 0,        0 },
-                    { 0,        0x10000 },
-                    { 0x10000,  0x10000 },
-                    { 0x10000,  0 }
-            };
+        const GLfixed texCoords[4][2] = {
+                { 0,        0 },
+                { 0,        0x10000 },
+                { 0x10000,  0x10000 },
+                { 0x10000,  0 }
+        };
 
-            glMatrixMode(GL_TEXTURE);
-            glLoadIdentity();
-            
-            if (transform == HAL_TRANSFORM_ROT_90) {
-                glTranslatef(0, 1, 0);
-                glRotatef(-90, 0, 0, 1);
-            }
+        glMatrixMode(GL_TEXTURE);
+        glLoadIdentity();
 
-            if (!(mFlags & DisplayHardware::NPOT_EXTENSION)) {
-                // find the smallest power-of-two that will accommodate our surface
-                GLuint tw = 1 << (31 - clz(t.width));
-                GLuint th = 1 << (31 - clz(t.height));
-                if (tw < t.width)  tw <<= 1;
-                if (th < t.height) th <<= 1;
-                // this divide should be relatively fast because it's
-                // a power-of-two (optimized path in libgcc)
-                GLfloat ws = GLfloat(t.width) /tw;
-                GLfloat hs = GLfloat(t.height)/th;
-                glScalef(ws, hs, 1.0f);
-            }
-
-            glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-            glVertexPointer(2, GL_FIXED, 0, mVertices);
-            glTexCoordPointer(2, GL_FIXED, 0, texCoords);
-
-            Rect r;
-            while (iterator.iterate(&r)) {
-                const GLint sy = fbHeight - (r.top + r.height());
-                glScissor(r.left, sy, r.width(), r.height());
-                glDrawArrays(GL_TRIANGLE_FAN, 0, 4); 
-            }
-
-            if (!fast && s.flags & ISurfaceComposer::eLayerFilter) {
-                glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-                glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-            }
-            glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+        // the texture's source is rotated
+        if (texture.transform == HAL_TRANSFORM_ROT_90) {
+            // TODO: handle the other orientations
+            glTranslatef(0, 1, 0);
+            glRotatef(-90, 0, 0, 1);
         }
+        
+        if (texture.NPOTAdjust) {
+            glScalef(texture.wScale, texture.hScale, 1.0f);
+        }
+
+        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+        glVertexPointer(2, GL_FIXED, 0, mVertices);
+        glTexCoordPointer(2, GL_FIXED, 0, texCoords);
+
+        while (it != end) {
+            const Rect& r = *it++;
+            const GLint sy = fbHeight - (r.top + r.height());
+            glScissor(r.left, sy, r.width(), r.height());
+            glDrawArrays(GL_TRIANGLE_FAN, 0, 4); 
+        }
+        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
     } else {
-        Region::iterator iterator(clip);
-        if (iterator) {
-            Rect r;
-            GLint crop[4] = { 0, t.height, t.width, -t.height };
-            glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop);
-            int x = tx();
-            int y = ty();
-            y = fbHeight - (y + t.height);
-            while (iterator.iterate(&r)) {
-                const GLint sy = fbHeight - (r.top + r.height());
-                glScissor(r.left, sy, r.width(), r.height());
-                glDrawTexiOES(x, y, 0, t.width, t.height);
-            }
+        GLint crop[4] = { 0, height, width, -height };
+        glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop);
+        int x = tx();
+        int y = ty();
+        y = fbHeight - (y + height);
+        while (it != end) {
+            const Rect& r = *it++;
+            const GLint sy = fbHeight - (r.top + r.height());
+            glScissor(r.left, sy, r.width(), r.height());
+            glDrawTexiOES(x, y, 0, width, height);
         }
     }
 }
@@ -548,25 +485,34 @@
     glBindTexture(GL_TEXTURE_2D, textureName);
     // TODO: reload the texture if needed
     // this is currently done in loadTexture() below
+    if (mUseLinearFiltering) {
+        glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+        glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    } else {
+        glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+        glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    }
+
+    if (needsDithering()) {
+        glEnable(GL_DITHER);
+    } else {
+        glDisable(GL_DITHER);
+    }
 }
 
-void LayerBase::loadTexture(const Region& dirty,
-        GLint textureName, const GGLSurface& t,
-        GLuint& textureWidth, GLuint& textureHeight) const
+void LayerBase::loadTexture(Texture* texture, 
+        const Region& dirty, const GGLSurface& t) const
 {
-    // TODO: defer the actual texture reload until LayerBase::validateTexture
-    // is called.
+    if (texture->name == -1U) {
+        // uh?
+        return;
+    }
 
-    uint32_t flags = mFlags;
-    glBindTexture(GL_TEXTURE_2D, textureName);
-
-    GLuint tw = t.width;
-    GLuint th = t.height;
+    glBindTexture(GL_TEXTURE_2D, texture->name);
 
     /*
      * In OpenGL ES we can't specify a stride with glTexImage2D (however,
-     * GL_UNPACK_ALIGNMENT is 4, which in essence allows a limited form of
-     * stride).
+     * GL_UNPACK_ALIGNMENT is a limited form of stride).
      * So if the stride here isn't representable with GL_UNPACK_ALIGNMENT, we
      * need to do something reasonable (here creating a bigger texture).
      * 
@@ -579,161 +525,294 @@
      *
      * This should never be a problem with POT textures
      */
-
-    tw += (((t.stride - tw) * bytesPerPixel(t.format)) / 4);
-
+    
+    int unpack = __builtin_ctz(t.stride * bytesPerPixel(t.format));
+    unpack = 1 << ((unpack > 3) ? 3 : unpack);
+    glPixelStorei(GL_UNPACK_ALIGNMENT, unpack);
+    
     /*
      * round to POT if needed 
      */
+    if (!(mFlags & DisplayHardware::NPOT_EXTENSION)) {
+        texture->NPOTAdjust = true;
+    }
     
-    GLuint texture_w = tw;
-    GLuint texture_h = th;
-    if (!(flags & DisplayHardware::NPOT_EXTENSION)) {
+    if (texture->NPOTAdjust) {
         // find the smallest power-of-two that will accommodate our surface
-        texture_w = 1 << (31 - clz(t.width));
-        texture_h = 1 << (31 - clz(t.height));
-        if (texture_w < t.width)  texture_w <<= 1;
-        if (texture_h < t.height) texture_h <<= 1;
-        if (texture_w != tw || texture_h != th) {
-            // we can't use DIRECT_TEXTURE since we changed the size
-            // of the texture
-            flags &= ~DisplayHardware::DIRECT_TEXTURE;
-        }
-    }
-
-    if (flags & DisplayHardware::DIRECT_TEXTURE) {
-        // here we're guaranteed that texture_{w|h} == t{w|h}
-        if (t.format == GGL_PIXEL_FORMAT_RGB_565) {
-            glTexImage2D(GL_DIRECT_TEXTURE_2D_QUALCOMM, 0,
-                    GL_RGB, tw, th, 0,
-                    GL_RGB, GL_UNSIGNED_SHORT_5_6_5, t.data);
-        } else if (t.format == GGL_PIXEL_FORMAT_RGBA_4444) {
-            glTexImage2D(GL_DIRECT_TEXTURE_2D_QUALCOMM, 0,
-                    GL_RGBA, tw, th, 0,
-                    GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, t.data);
-        } else if (t.format == GGL_PIXEL_FORMAT_RGBA_8888) {
-            glTexImage2D(GL_DIRECT_TEXTURE_2D_QUALCOMM, 0,
-                    GL_RGBA, tw, th, 0,
-                    GL_RGBA, GL_UNSIGNED_BYTE, t.data);
-        } else if (t.format == GGL_PIXEL_FORMAT_BGRA_8888) {
-            // TODO: add GL_BGRA extension
-        } else {
-            // oops, we don't handle this format, try the regular path
-            goto regular;
-        }
-        textureWidth = tw;
-        textureHeight = th;
+        texture->potWidth  = 1 << (31 - clz(t.width));
+        texture->potHeight = 1 << (31 - clz(t.height));
+        if (texture->potWidth  < t.width)  texture->potWidth  <<= 1;
+        if (texture->potHeight < t.height) texture->potHeight <<= 1;
+        texture->wScale = float(t.width)  / texture->potWidth;
+        texture->hScale = float(t.height) / texture->potHeight;
     } else {
-regular:
-        Rect bounds(dirty.bounds());
-        GLvoid* data = 0;
-        if (texture_w!=textureWidth || texture_h!=textureHeight) {
-            // texture size changed, we need to create a new one
+        texture->potWidth  = t.width;
+        texture->potHeight = t.height;
+    }
 
-            if (!textureWidth || !textureHeight) {
-                // this is the first time, load the whole texture
-                if (texture_w==tw && texture_h==th) {
-                    // we can do it one pass
-                    data = t.data;
-                } else {
-                    // we have to create the texture first because it
-                    // doesn't match the size of the buffer
-                    bounds.set(Rect(tw, th));
-                }
-            }
-            
-            if (t.format == GGL_PIXEL_FORMAT_RGB_565) {
-                glTexImage2D(GL_TEXTURE_2D, 0,
-                        GL_RGB, texture_w, texture_h, 0,
-                        GL_RGB, GL_UNSIGNED_SHORT_5_6_5, data);
-            } else if (t.format == GGL_PIXEL_FORMAT_RGBA_4444) {
-                glTexImage2D(GL_TEXTURE_2D, 0,
-                        GL_RGBA, texture_w, texture_h, 0,
-                        GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, data);
-            } else if (t.format == GGL_PIXEL_FORMAT_RGBA_8888) {
-                glTexImage2D(GL_TEXTURE_2D, 0,
-                        GL_RGBA, texture_w, texture_h, 0,
-                        GL_RGBA, GL_UNSIGNED_BYTE, data);
-            } else if ( t.format == GGL_PIXEL_FORMAT_YCbCr_422_SP ||
-                        t.format == GGL_PIXEL_FORMAT_YCbCr_420_SP) {
-                // just show the Y plane of YUV buffers
-                data = t.data;
-                glTexImage2D(GL_TEXTURE_2D, 0,
-                        GL_LUMINANCE, texture_w, texture_h, 0,
-                        GL_LUMINANCE, GL_UNSIGNED_BYTE, data);
-            } else {
-                // oops, we don't handle this format!
-                LOGE("layer %p, texture=%d, using format %d, which is not "
-                     "supported by the GL", this, textureName, t.format);
-                textureName = -1;
-            }
-            textureWidth = texture_w;
-            textureHeight = texture_h;
+    Rect bounds(dirty.bounds());
+    GLvoid* data = 0;
+    if (texture->width != t.width || texture->height != t.height) {
+        texture->width  = t.width;
+        texture->height = t.height;
+
+        // texture size changed, we need to create a new one
+        bounds.set(Rect(t.width, t.height));
+        if (t.width  == texture->potWidth &&
+            t.height == texture->potHeight) {
+            // we can do it one pass
+            data = t.data;
         }
-        if (!data && textureName>=0) {
-            if (t.format == GGL_PIXEL_FORMAT_RGB_565) {
-                glTexSubImage2D(GL_TEXTURE_2D, 0,
-                        0, bounds.top, t.width, bounds.height(),
-                        GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
-                        t.data + bounds.top*t.width*2);
-            } else if (t.format == GGL_PIXEL_FORMAT_RGBA_4444) {
-                glTexSubImage2D(GL_TEXTURE_2D, 0,
-                        0, bounds.top, t.width, bounds.height(),
-                        GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4,
-                        t.data + bounds.top*t.width*2);
-            } else if (t.format == GGL_PIXEL_FORMAT_RGBA_8888) {
-                glTexSubImage2D(GL_TEXTURE_2D, 0,
-                        0, bounds.top, t.width, bounds.height(),
-                        GL_RGBA, GL_UNSIGNED_BYTE,
-                        t.data + bounds.top*t.width*4);
-            }
+
+        if (t.format == GGL_PIXEL_FORMAT_RGB_565) {
+            glTexImage2D(GL_TEXTURE_2D, 0,
+                    GL_RGB, texture->potWidth, texture->potHeight, 0,
+                    GL_RGB, GL_UNSIGNED_SHORT_5_6_5, data);
+        } else if (t.format == GGL_PIXEL_FORMAT_RGBA_4444) {
+            glTexImage2D(GL_TEXTURE_2D, 0,
+                    GL_RGBA, texture->potWidth, texture->potHeight, 0,
+                    GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, data);
+        } else if (t.format == GGL_PIXEL_FORMAT_RGBA_8888 || 
+                   t.format == GGL_PIXEL_FORMAT_RGBX_8888) {
+            glTexImage2D(GL_TEXTURE_2D, 0,
+                    GL_RGBA, texture->potWidth, texture->potHeight, 0,
+                    GL_RGBA, GL_UNSIGNED_BYTE, data);
+        } else if ( t.format == GGL_PIXEL_FORMAT_YCbCr_422_SP ||
+                    t.format == GGL_PIXEL_FORMAT_YCbCr_420_SP) {
+            // just show the Y plane of YUV buffers
+            glTexImage2D(GL_TEXTURE_2D, 0,
+                    GL_LUMINANCE, texture->potWidth, texture->potHeight, 0,
+                    GL_LUMINANCE, GL_UNSIGNED_BYTE, data);
+        } else {
+            // oops, we don't handle this format!
+            LOGE("layer %p, texture=%d, using format %d, which is not "
+                 "supported by the GL", this, texture->name, t.format);
+        }
+    }
+    if (!data) {
+        if (t.format == GGL_PIXEL_FORMAT_RGB_565) {
+            glTexSubImage2D(GL_TEXTURE_2D, 0,
+                    0, bounds.top, t.width, bounds.height(),
+                    GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
+                    t.data + bounds.top*t.stride*2);
+        } else if (t.format == GGL_PIXEL_FORMAT_RGBA_4444) {
+            glTexSubImage2D(GL_TEXTURE_2D, 0,
+                    0, bounds.top, t.width, bounds.height(),
+                    GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4,
+                    t.data + bounds.top*t.stride*2);
+        } else if (t.format == GGL_PIXEL_FORMAT_RGBA_8888 ||
+                   t.format == GGL_PIXEL_FORMAT_RGBX_8888) {
+            glTexSubImage2D(GL_TEXTURE_2D, 0,
+                    0, bounds.top, t.width, bounds.height(),
+                    GL_RGBA, GL_UNSIGNED_BYTE,
+                    t.data + bounds.top*t.stride*4);
+        } else if ( t.format == GGL_PIXEL_FORMAT_YCbCr_422_SP ||
+                    t.format == GGL_PIXEL_FORMAT_YCbCr_420_SP) {
+            // just show the Y plane of YUV buffers
+            glTexSubImage2D(GL_TEXTURE_2D, 0,
+                    0, bounds.top, t.width, bounds.height(),
+                    GL_LUMINANCE, GL_UNSIGNED_BYTE,
+                    t.data + bounds.top*t.stride);
         }
     }
 }
 
-bool LayerBase::canUseCopybit() const
+status_t LayerBase::initializeEglImage(
+        const sp<GraphicBuffer>& buffer, Texture* texture)
 {
-    return mCanUseCopyBit;
+    status_t err = NO_ERROR;
+
+    // we need to recreate the texture
+    EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
+
+    // free the previous image
+    if (texture->image != EGL_NO_IMAGE_KHR) {
+        eglDestroyImageKHR(dpy, texture->image);
+        texture->image = EGL_NO_IMAGE_KHR;
+    }
+
+    // construct an EGL_NATIVE_BUFFER_ANDROID
+    android_native_buffer_t* clientBuf = buffer->getNativeBuffer();
+
+    // create the new EGLImageKHR
+    const EGLint attrs[] = {
+            EGL_IMAGE_PRESERVED_KHR,    EGL_TRUE,
+            EGL_NONE,                   EGL_NONE
+    };
+    texture->image = eglCreateImageKHR(
+            dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
+            (EGLClientBuffer)clientBuf, attrs);
+
+    LOGE_IF(texture->image == EGL_NO_IMAGE_KHR,
+            "eglCreateImageKHR() failed. err=0x%4x",
+            eglGetError());
+
+    if (texture->image != EGL_NO_IMAGE_KHR) {
+        glBindTexture(GL_TEXTURE_2D, texture->name);
+        glEGLImageTargetTexture2DOES(GL_TEXTURE_2D,
+                (GLeglImageOES)texture->image);
+        GLint error = glGetError();
+        if (UNLIKELY(error != GL_NO_ERROR)) {
+            // this failed, for instance, because we don't support NPOT.
+            // FIXME: do something!
+            LOGE("layer=%p, glEGLImageTargetTexture2DOES(%p) "
+                 "failed err=0x%04x",
+                 this, texture->image, error);
+            mFlags &= ~DisplayHardware::DIRECT_TEXTURE;
+            err = INVALID_OPERATION;
+        } else {
+            // Everything went okay!
+            texture->NPOTAdjust = false;
+            texture->dirty  = false;
+            texture->width  = clientBuf->width;
+            texture->height = clientBuf->height;
+        }
+    } else {
+        err = INVALID_OPERATION;
+    }
+    return err;
 }
 
+
 // ---------------------------------------------------------------------------
 
-LayerBaseClient::LayerBaseClient(SurfaceFlinger* flinger, DisplayID display,
-        Client* c, int32_t i)
-    : LayerBase(flinger, display), client(c),
-      lcblk( c ? &(c->ctrlblk->layers[i]) : 0 ),
-      mIndex(i)
-{
-    if (client) {
-        client->bindLayer(this, i);
+int32_t LayerBaseClient::sIdentity = 0;
 
-        // Initialize this layer's control block
-        memset(this->lcblk, 0, sizeof(layer_cblk_t));
-        this->lcblk->identity = mIdentity;
-        Region::writeEmpty(&(this->lcblk->region[0]), sizeof(flat_region_t));
-        Region::writeEmpty(&(this->lcblk->region[1]), sizeof(flat_region_t));
+LayerBaseClient::LayerBaseClient(SurfaceFlinger* flinger, DisplayID display,
+        const sp<Client>& client, int32_t i)
+    : LayerBase(flinger, display), lcblk(NULL), client(client),
+      mIndex(i), mIdentity(uint32_t(android_atomic_inc(&sIdentity)))
+{
+    lcblk = new SharedBufferServer(
+            client->ctrlblk, i, NUM_BUFFERS,
+            mIdentity);
+}
+
+void LayerBaseClient::onFirstRef()
+{    
+    sp<Client> client(this->client.promote());
+    if (client != 0) {
+        client->bindLayer(this, mIndex);
     }
 }
 
 LayerBaseClient::~LayerBaseClient()
 {
-    if (client) {
+    sp<Client> client(this->client.promote());
+    if (client != 0) {
         client->free(mIndex);
     }
+    delete lcblk;
 }
 
-int32_t LayerBaseClient::serverIndex() const {
-    if (client) {
+int32_t LayerBaseClient::serverIndex() const 
+{
+    sp<Client> client(this->client.promote());
+    if (client != 0) {
         return (client->cid<<16)|mIndex;
     }
     return 0xFFFF0000 | mIndex;
 }
 
-sp<LayerBaseClient::Surface> LayerBaseClient::getSurface() const
+sp<LayerBaseClient::Surface> LayerBaseClient::getSurface()
 {
-    return new Surface(clientIndex(), mIdentity);
+    sp<Surface> s;
+    Mutex::Autolock _l(mLock);
+    s = mClientSurface.promote();
+    if (s == 0) {
+        s = createSurface();
+        mClientSurface = s;
+    }
+    return s;
 }
 
+sp<LayerBaseClient::Surface> LayerBaseClient::createSurface() const
+{
+    return new Surface(mFlinger, clientIndex(), mIdentity,
+            const_cast<LayerBaseClient *>(this));
+}
+
+// called with SurfaceFlinger::mStateLock as soon as the layer is entered
+// in the purgatory list
+void LayerBaseClient::onRemoved()
+{
+    // wake up the condition
+    lcblk->setStatus(NO_INIT);
+}
+
+// ---------------------------------------------------------------------------
+
+LayerBaseClient::Surface::Surface(
+        const sp<SurfaceFlinger>& flinger,
+        SurfaceID id, int identity, 
+        const sp<LayerBaseClient>& owner) 
+    : mFlinger(flinger), mToken(id), mIdentity(identity), mOwner(owner)
+{
+}
+
+LayerBaseClient::Surface::~Surface() 
+{
+    /*
+     * This is a good place to clean-up all client resources 
+     */
+
+    // destroy client resources
+    sp<LayerBaseClient> layer = getOwner();
+    if (layer != 0) {
+        mFlinger->destroySurface(layer);
+    }
+}
+
+sp<LayerBaseClient> LayerBaseClient::Surface::getOwner() const {
+    sp<LayerBaseClient> owner(mOwner.promote());
+    return owner;
+}
+
+status_t LayerBaseClient::Surface::onTransact(
+        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    switch (code) {
+        case REGISTER_BUFFERS:
+        case UNREGISTER_BUFFERS:
+        case CREATE_OVERLAY:
+        {
+            if (!mFlinger->mAccessSurfaceFlinger.checkCalling()) {
+                IPCThreadState* ipc = IPCThreadState::self();
+                const int pid = ipc->getCallingPid();
+                const int uid = ipc->getCallingUid();
+                LOGE("Permission Denial: "
+                        "can't access SurfaceFlinger pid=%d, uid=%d", pid, uid);
+                return PERMISSION_DENIED;
+            }
+        }
+    }
+    return BnSurface::onTransact(code, data, reply, flags);
+}
+
+sp<GraphicBuffer> LayerBaseClient::Surface::requestBuffer(int index, int usage) 
+{
+    return NULL; 
+}
+
+status_t LayerBaseClient::Surface::registerBuffers(
+        const ISurface::BufferHeap& buffers) 
+{ 
+    return INVALID_OPERATION; 
+}
+
+void LayerBaseClient::Surface::postBuffer(ssize_t offset) 
+{
+}
+
+void LayerBaseClient::Surface::unregisterBuffers() 
+{
+}
+
+sp<OverlayRef> LayerBaseClient::Surface::createOverlay(
+        uint32_t w, uint32_t h, int32_t format) 
+{
+    return NULL;
+};
 
 // ---------------------------------------------------------------------------
 
diff --git a/libs/surfaceflinger/LayerBase.h b/libs/surfaceflinger/LayerBase.h
index a020f44..ed07b3f 100644
--- a/libs/surfaceflinger/LayerBase.h
+++ b/libs/surfaceflinger/LayerBase.h
@@ -20,8 +20,14 @@
 #include <stdint.h>
 #include <sys/types.h>
 
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+#include <private/ui/SharedBufferStack.h>
 #include <private/ui/LayerState.h>
 
+#include <utils/RefBase.h>
+
 #include <ui/Region.h>
 #include <ui/Overlay.h>
 
@@ -33,14 +39,15 @@
 
 // ---------------------------------------------------------------------------
 
-class SurfaceFlinger;
 class DisplayHardware;
-class GraphicPlane;
 class Client;
+class GraphicBuffer;
+class GraphicPlane;
+class SurfaceFlinger;
 
 // ---------------------------------------------------------------------------
 
-class LayerBase
+class LayerBase : public RefBase
 {
     // poor man's dynamic_cast below
     template<typename T>
@@ -69,10 +76,7 @@
     }
 
     
-    static Vector<GLuint> deletedTextures; 
-
     LayerBase(SurfaceFlinger* flinger, DisplayID display);
-    virtual ~LayerBase();
     
     DisplayID           dpy;
     mutable bool        contentDirty;
@@ -83,6 +87,8 @@
             struct State {
                 uint32_t        w;
                 uint32_t        h;
+                uint32_t        requested_w;
+                uint32_t        requested_h;
                 uint32_t        z;
                 uint8_t         alpha;
                 uint8_t         flags;
@@ -102,7 +108,7 @@
             bool setTransparentRegionHint(const Region& opaque);
             bool setFlags(uint8_t flags, uint8_t mask);
             
-            void commitTransaction(bool skipSize);
+            void commitTransaction();
             bool requestTransaction();
             void forceVisibilityTransaction();
             
@@ -133,11 +139,6 @@
     virtual void initStates(uint32_t w, uint32_t h, uint32_t flags);
     
     /**
-     * setSizeChanged - called when the *current* state's size is changed.
-     */
-    virtual void setSizeChanged(uint32_t w, uint32_t h);
-    
-    /**
      * doTransaction - process the transaction. This is a good place to figure
      * out which attributes of the surface have changed.
      */
@@ -157,13 +158,6 @@
     virtual void setCoveredRegion(const Region& coveredRegion);
     
     /**
-     * getPhysicalSize - returns the physical size of the drawing state of
-     * the surface. If the surface is backed by a bitmap, this is the size of
-     * the bitmap (as opposed to the size of the drawing state).
-     */
-    virtual Point getPhysicalSize() const;
-
-    /**
      * validateVisibility - cache a bunch of things
      */
     virtual void validateVisibility(const Transform& globalTransform);
@@ -195,27 +189,42 @@
     virtual bool needsBlending() const  { return false; }
 
     /**
+     * needsDithering - true if this surface needs dithering
+     */
+    virtual bool needsDithering() const { return false; }
+
+    /**
      * transformed -- true is this surface needs a to be transformed
      */
     virtual bool transformed() const    { return mTransformed; }
 
     /**
      * isSecure - true if this surface is secure, that is if it prevents
-     * screenshots or vns servers.
+     * screenshots or VNC servers.
      */
     virtual bool isSecure() const       { return false; }
 
-            enum { // flags for doTransaction()
-                eVisibleRegion      = 0x00000002,
-                eRestartTransaction = 0x00000008
-            };
+    /** Called from the main thread, when the surface is removed from the
+     * draw list */
+    virtual status_t ditch() { return NO_ERROR; }
+
+    /** called with the state lock when the surface is removed from the
+     *  current list */
+    virtual void onRemoved() { };
+    
+    
+    enum { // flags for doTransaction()
+        eVisibleRegion      = 0x00000002,
+    };
 
 
     inline  const State&    drawingState() const    { return mDrawingState; }
     inline  const State&    currentState() const    { return mCurrentState; }
     inline  State&          currentState()          { return mCurrentState; }
 
-    static int compareCurrentStateZ(LayerBase*const* layerA, LayerBase*const* layerB) {
+    static int compareCurrentStateZ(
+            sp<LayerBase> const * layerA,
+            sp<LayerBase> const * layerB) {
         return layerA[0]->currentState().z - layerB[0]->currentState().z;
     }
 
@@ -229,28 +238,42 @@
 
           GLuint createTexture() const;
     
-          void drawWithOpenGL(const Region& clip,
-                  GLint textureName,
-                  const GGLSurface& surface,
-                  int transform = 0) const;
+          struct Texture {
+              Texture() : name(-1U), width(0), height(0),
+                  image(EGL_NO_IMAGE_KHR), transform(0), 
+                  NPOTAdjust(false), dirty(true) { }
+              GLuint        name;
+              GLuint        width;
+              GLuint        height;
+              GLuint        potWidth;
+              GLuint        potHeight;
+              GLfloat       wScale;
+              GLfloat       hScale;
+              EGLImageKHR   image;
+              uint32_t      transform;
+              bool          NPOTAdjust;
+              bool          dirty;
+          };
 
+          void clearWithOpenGL(const Region& clip, GLclampx r, GLclampx g,
+                               GLclampx b, GLclampx alpha) const;
           void clearWithOpenGL(const Region& clip) const;
+          void drawWithOpenGL(const Region& clip, const Texture& texture) const;
+          void loadTexture(Texture* texture, 
+                  const Region& dirty, const GGLSurface& t) const;
+          status_t initializeEglImage(
+                  const sp<GraphicBuffer>& buffer, Texture* texture);
 
-          void loadTexture(const Region& dirty,
-                  GLint textureName, const GGLSurface& t,
-                  GLuint& textureWidth, GLuint& textureHeight) const;
-
-          bool canUseCopybit() const;
           
-                SurfaceFlinger* mFlinger;
+                sp<SurfaceFlinger> mFlinger;
                 uint32_t        mFlags;
 
                 // cached during validateVisibility()
                 bool            mTransformed;
+                bool            mUseLinearFiltering;
                 int32_t         mOrientation;
                 GLfixed         mVertices[4][2];
                 Rect            mTransformedBounds;
-                bool            mCanUseCopyBit;
                 int             mLeft;
                 int             mTop;
             
@@ -262,16 +285,16 @@
                 // don't change, don't need a lock
                 bool            mPremultipliedAlpha;
 
-                // only read
-    const       uint32_t        mIdentity;
-     
                 // atomic
     volatile    int32_t         mInvalidate;
                 
 
+protected:
+    virtual ~LayerBase();
+
 private:
-                void validateTexture(GLint textureName) const;
-    static      int32_t         sIdentity;
+    LayerBase(const LayerBase& rhs);
+    void validateTexture(GLint textureName) const;
 };
 
 
@@ -286,67 +309,67 @@
     virtual char const* getTypeID() const { return typeID; }
     virtual uint32_t getTypeInfo() const { return typeInfo; }
 
+    // lcblk is (almost) only accessed from the main SF thread, in the places
+    // where it's not, a reference to Client must be held
+    SharedBufferServer*     lcblk;
+
     LayerBaseClient(SurfaceFlinger* flinger, DisplayID display, 
-            Client* client, int32_t i);
+            const sp<Client>& client, int32_t i);
     virtual ~LayerBaseClient();
+    virtual void onFirstRef();
 
+    const wp<Client>    client;
 
-    Client*             const client;
-    layer_cblk_t*       const lcblk;
-
+    inline  uint32_t    getIdentity() const { return mIdentity; }
     inline  int32_t     clientIndex() const { return mIndex; }
             int32_t     serverIndex() const;
 
-    virtual sp<Surface> getSurface() const;
    
-            uint32_t    getIdentity() const { return mIdentity; }
+            sp<Surface> getSurface();
+    virtual sp<Surface> createSurface() const;
+    
+    virtual void onRemoved();
 
     class Surface : public BnSurface 
     {
     public:
-        Surface(SurfaceID id, int identity) { 
-            mParams.token = id;
-            mParams.identity = identity;
-        }
-        Surface(SurfaceID id, 
-                const sp<IMemoryHeap>& heap0,
-                const sp<IMemoryHeap>& heap1,
-                int identity)
-        {
-            mParams.token = id;
-            mParams.identity = identity;
-            mParams.heap[0] = heap0;
-            mParams.heap[1] = heap1;
-        }
-        virtual ~Surface() {
-            // TODO: We now have a point here were we can clean-up the
-            // client's mess.
-            // This is also where surface id should be recycled.
-            //LOGD("Surface %d, heaps={%p, %p} destroyed",
-            //        mId, mHeap[0].get(), mHeap[1].get());
-        }
-
-        virtual void getSurfaceData(
-                ISurfaceFlingerClient::surface_data_t* params) const {
-            *params = mParams;
-        }
-
-        virtual status_t registerBuffers(const ISurface::BufferHeap& buffers) 
-                { return INVALID_OPERATION; }
-        virtual void postBuffer(ssize_t offset) { }
-        virtual void unregisterBuffers() { };
-        virtual sp<OverlayRef> createOverlay(
-                uint32_t w, uint32_t h, int32_t format) {
-            return NULL;
-        };
+        int32_t getToken() const { return mToken; }
+        int32_t getIdentity() const { return mIdentity; }
+        
+    protected:
+        Surface(const sp<SurfaceFlinger>& flinger, 
+                SurfaceID id, int identity, 
+                const sp<LayerBaseClient>& owner);
+        virtual ~Surface();
+        virtual status_t onTransact(uint32_t code, const Parcel& data,
+                Parcel* reply, uint32_t flags);
+        sp<LayerBaseClient> getOwner() const;
 
     private:
-        ISurfaceFlingerClient::surface_data_t mParams;
+        virtual sp<GraphicBuffer> requestBuffer(int index, int usage);
+        virtual status_t registerBuffers(const ISurface::BufferHeap& buffers); 
+        virtual void postBuffer(ssize_t offset);
+        virtual void unregisterBuffers();
+        virtual sp<OverlayRef> createOverlay(uint32_t w, uint32_t h,
+                int32_t format);
+
+    protected:
+        friend class LayerBaseClient;
+        sp<SurfaceFlinger>  mFlinger;
+        int32_t             mToken;
+        int32_t             mIdentity;
+        wp<LayerBaseClient> mOwner;
     };
 
-private:
-    int32_t mIndex;
+    friend class Surface;
 
+private:
+                int32_t         mIndex;
+    mutable     Mutex           mLock;
+    mutable     wp<Surface>     mClientSurface;
+    // only read
+    const       uint32_t        mIdentity;
+    static      int32_t         sIdentity;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/libs/surfaceflinger/LayerBitmap.cpp b/libs/surfaceflinger/LayerBitmap.cpp
deleted file mode 100644
index 397ddc8..0000000
--- a/libs/surfaceflinger/LayerBitmap.cpp
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "SurfaceFlinger"
-
-#include <stdlib.h>
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <cutils/memory.h>
-#include <utils/Errors.h>
-#include <utils/Log.h>
-#include <utils/MemoryDealer.h>
-#include <utils/IMemory.h>
-#include <ui/PixelFormat.h>
-#include <pixelflinger/pixelflinger.h>
-
-#include "LayerBitmap.h"
-#include "SurfaceFlinger.h"
-#include "VRamHeap.h"
-
-
-namespace android {
-
-// ---------------------------------------------------------------------------
-
-LayerBitmap::LayerBitmap()
-    : mAllocFlags(0), mOffset(0), mSize(-1U), mAlignment(2)
-{
-    memset(&mSurface, 0, sizeof(mSurface));
-}
-
-LayerBitmap::~LayerBitmap()
-{
-    mSurface.data = 0;
-}
-
-status_t LayerBitmap::init(const sp<MemoryDealer>& allocator)
-{
-    if (mAllocator != NULL)
-        return BAD_VALUE;
-    mAllocator = allocator;
-    return NO_ERROR;
-}
-
-status_t LayerBitmap::setBits(uint32_t w, uint32_t h, uint32_t alignment, 
-        PixelFormat format, uint32_t flags)
-{
-    const sp<MemoryDealer>& allocator(mAllocator);
-    if (allocator == NULL)
-        return NO_INIT;
-
-    if (UNLIKELY(w == mSurface.width && h == mSurface.height &&
-            format == mSurface.format))
-    { // same format and size, do nothing.
-        return NO_ERROR;
-    }
-
-    PixelFormatInfo info;
-    getPixelFormatInfo(format, &info);
-
-    uint32_t allocFlags = MemoryDealer::PAGE_ALIGNED;
-    const uint32_t align = 4; // must match GL_UNPACK_ALIGNMENT
-    const uint32_t Bpp = info.bytesPerPixel;
-    uint32_t stride = (w + (alignment-1)) & ~(alignment-1);
-    stride = ((stride * Bpp + (align-1)) & ~(align-1)) / Bpp;
-    size_t size = info.getScanlineSize(stride) * h;
-    if (allocFlags & MemoryDealer::PAGE_ALIGNED) {
-        size_t pagesize = getpagesize();
-        size = (size + (pagesize-1)) & ~(pagesize-1);
-    }
-
-    /* FIXME: we should be able to have a h/v stride because the user of the
-     * surface might have stride limitation (for instance h/w codecs often do)
-     */
-    int32_t vstride = 0;
-
-    mAlignment = alignment;
-    mAllocFlags = allocFlags;
-    mOffset = 0;
-    if (mSize != size) {
-        // would be nice to have a reallocate() api
-        mBitsMemory.clear(); // free-memory
-        mBitsMemory = allocator->allocate(size, allocFlags);
-        mSize = size;
-    } else {
-        // don't erase memory if we didn't have to reallocate
-        flags &= ~SECURE_BITS;
-    }
-    if (mBitsMemory != 0) {
-        mOffset = mBitsMemory->offset();
-        mSurface.data = static_cast<GGLubyte*>(mBitsMemory->pointer());
-        mSurface.version = sizeof(GGLSurface);
-        mSurface.width  = w;
-        mSurface.height = h;
-        mSurface.stride = stride;
-        mSurface.vstride = vstride;
-        mSurface.format = format;
-        if (flags & SECURE_BITS)
-            clear();
-    }
-
-    if (mBitsMemory==0 || mSurface.data==0) {
-        LOGE("not enough memory for layer bitmap "
-             "size=%u (w=%d, h=%d, stride=%d, format=%d)",
-             size, int(w), int(h), int(stride), int(format));
-        allocator->dump("LayerBitmap");
-        mSurface.data = 0;
-        mSize = -1U;
-        return NO_MEMORY;
-    }
-    return NO_ERROR;
-}
-
-void LayerBitmap::clear()
-{
-    // NOTE: this memset should not be necessary, at least for
-    // opaque surface. However, for security reasons it's better to keep it
-    // (in the case of pmem, it's possible that the memory contains old
-    // data)
-    if (mSurface.data) {
-        memset(mSurface.data, 0, mSize);
-        //if (bytesPerPixel(mSurface.format) == 4) {
-        //    android_memset32((uint32_t*)mSurface.data, 0xFF0000FF, mSize);
-        //} else  {
-        //    android_memset16((uint16_t*)mSurface.data, 0xF800, mSize);
-        //}
-    }
-}
-
-status_t LayerBitmap::getInfo(surface_info_t* info) const
-{
-    if (mSurface.data == 0) {
-        memset(info, 0, sizeof(surface_info_t));
-        info->bits_offset = NO_MEMORY;
-        return NO_MEMORY;
-    }
-    info->w     = uint16_t(width());
-    info->h     = uint16_t(height());
-    info->stride= uint16_t(stride());
-    info->bpr   = uint16_t(stride() * bytesPerPixel(pixelFormat()));
-    info->format= uint8_t(pixelFormat());
-    info->flags = surface_info_t::eBufferDirty;
-    info->bits_offset = ssize_t(mOffset);
-    return NO_ERROR;
-}
-
-status_t LayerBitmap::resize(uint32_t w, uint32_t h)
-{
-    int err = setBits(w, h, mAlignment, pixelFormat(), SECURE_BITS);
-    return err;
-}
-
-size_t LayerBitmap::size() const
-{
-    return mSize;
-}
-
-void LayerBitmap::getBitmapSurface(copybit_image_t* img) const
-{
-    const sp<IMemoryHeap>& mh(getAllocator()->getMemoryHeap());
-    void* sbase = mh->base();
-    const GGLSurface& t(surface());
-    img->w = t.stride  ?: t.width;
-    img->h = t.vstride ?: t.height;
-    img->format = t.format;
-    img->offset = intptr_t(t.data) - intptr_t(sbase);
-    img->base = sbase;
-    img->fd = mh->heapID();
-}
-
-// ---------------------------------------------------------------------------
-
-}; // namespace android
diff --git a/libs/surfaceflinger/LayerBitmap.h b/libs/surfaceflinger/LayerBitmap.h
deleted file mode 100644
index 9ad64c4..0000000
--- a/libs/surfaceflinger/LayerBitmap.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_LAYER_BITMAP_H
-#define ANDROID_LAYER_BITMAP_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <utils/Atomic.h>
-#include <ui/PixelFormat.h>
-#include <ui/Rect.h>
-#include <private/ui/SharedState.h>
-#include <pixelflinger/pixelflinger.h>
-
-class copybit_image_t;
-
-namespace android {
-
-// ---------------------------------------------------------------------------
-
-class IMemory;
-class MemoryDealer;
-class LayerBitmap;
-
-// ---------------------------------------------------------------------------
-
-class LayerBitmap
-{
-public:
-
-    enum {
-        // erase memory to ensure security when necessary
-        SECURE_BITS = 0x00000001
-    };
-
-                LayerBitmap();
-                ~LayerBitmap();
-    status_t    init(const sp<MemoryDealer>& allocator);
-
-    status_t    setBits(uint32_t w, uint32_t h, uint32_t alignment,
-                        PixelFormat format, uint32_t flags = 0);
-    void        clear();
-
-    status_t    getInfo(surface_info_t* info) const;
-    status_t    resize(uint32_t w, uint32_t h);
-
-    const GGLSurface& surface() const   { return mSurface; }
-    Rect bounds() const                 { return Rect(width(), height()); }
-    uint32_t width() const              { return surface().width; }
-    uint32_t height() const             { return surface().height; }
-    uint32_t stride() const             { return surface().stride; }
-    PixelFormat pixelFormat() const     { return surface().format; }
-    void* serverBits() const            { return surface().data; }
-    size_t size() const;
-    const sp<MemoryDealer>& getAllocator() const { return mAllocator; }
-    void getBitmapSurface(copybit_image_t* img) const;
-
-private:
-    sp<MemoryDealer>        mAllocator;
-    sp<IMemory>             mBitsMemory;
-    uint32_t                mAllocFlags;
-    ssize_t                 mOffset;
-    GGLSurface              mSurface;
-    size_t                  mSize;
-    uint32_t                mAlignment;
-};
-
-}; // namespace android
-
-#endif // ANDROID_LAYER_BITMAP_H
diff --git a/libs/surfaceflinger/LayerBlur.cpp b/libs/surfaceflinger/LayerBlur.cpp
index d3e456f..5fd7904 100644
--- a/libs/surfaceflinger/LayerBlur.cpp
+++ b/libs/surfaceflinger/LayerBlur.cpp
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "SurfaceFlinger"
-
 #include <stdlib.h>
 #include <stdint.h>
 #include <sys/types.h>
@@ -26,6 +24,7 @@
 #include <GLES/gl.h>
 #include <GLES/glext.h>
 
+#include "clz.h"
 #include "BlurFilter.h"
 #include "LayerBlur.h"
 #include "SurfaceFlinger.h"
@@ -40,17 +39,18 @@
 // ---------------------------------------------------------------------------
 
 LayerBlur::LayerBlur(SurfaceFlinger* flinger, DisplayID display,
-        Client* client, int32_t i)
-     : LayerBaseClient(flinger, display, client, i), mCacheDirty(true),
-     mRefreshCache(true), mCacheAge(0), mTextureName(-1U)
+        const sp<Client>& client, int32_t i)
+    : LayerBaseClient(flinger, display, client, i), mCacheDirty(true),
+          mRefreshCache(true), mCacheAge(0), mTextureName(-1U),
+          mWidthScale(1.0f), mHeightScale(1.0f),
+          mBlurFormat(GGL_PIXEL_FORMAT_RGB_565)
 {
 }
 
 LayerBlur::~LayerBlur()
 {
     if (mTextureName != -1U) {
-        //glDeleteTextures(1, &mTextureName);
-        deletedTextures.add(mTextureName);
+        glDeleteTextures(1, &mTextureName);
     }
 }
 
@@ -137,44 +137,73 @@
         // create the texture name the first time
         // can't do that in the ctor, because it runs in another thread.
         glGenTextures(1, &mTextureName);
+        glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES, &mReadFormat);
+        glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE_OES, &mReadType);
+        if (mReadFormat != GL_RGB || mReadType != GL_UNSIGNED_SHORT_5_6_5) {
+            mReadFormat = GL_RGBA;
+            mReadType = GL_UNSIGNED_BYTE;
+            mBlurFormat = GGL_PIXEL_FORMAT_RGBX_8888;
+        }
     }
 
-    Region::iterator iterator(clip);
-    if (iterator) {
+    Region::const_iterator it = clip.begin();
+    Region::const_iterator const end = clip.end();
+    if (it != end) {
         glEnable(GL_TEXTURE_2D);
         glBindTexture(GL_TEXTURE_2D, mTextureName);
-    
+
         if (mRefreshCache) {
             mRefreshCache = false;
             mAutoRefreshPending = false;
-            
-            // allocate enough memory for 4-bytes (2 pixels) aligned data
-            const int32_t s = (w + 1) & ~1;
-            uint16_t* const pixels = (uint16_t*)malloc(s*h*2);
+
+            int32_t pixelSize = 4;
+            int32_t s = w;
+            if (mReadType == GL_UNSIGNED_SHORT_5_6_5) {
+                // allocate enough memory for 4-bytes (2 pixels) aligned data
+                s = (w + 1) & ~1;
+                pixelSize = 2;
+            }
+
+            uint16_t* const pixels = (uint16_t*)malloc(s*h*pixelSize);
 
             // This reads the frame-buffer, so a h/w GL would have to
             // finish() its rendering first. we don't want to do that
             // too often. Read data is 4-bytes aligned.
-            glReadPixels(X, Y, w, h, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixels);
-            
+            glReadPixels(X, Y, w, h, mReadFormat, mReadType, pixels);
+
             // blur that texture.
             GGLSurface bl;
             bl.version = sizeof(GGLSurface);
             bl.width = w;
             bl.height = h;
             bl.stride = s;
-            bl.format = GGL_PIXEL_FORMAT_RGB_565;
+            bl.format = mBlurFormat;
             bl.data = (GGLubyte*)pixels;            
             blurFilter(&bl, 8, 2);
-            
-            // NOTE: this works only because we have POT. we'd have to round the
-            // texture size up, otherwise.
-            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0,
-                    GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixels);
+
+            if (mFlags & (DisplayHardware::NPOT_EXTENSION)) {
+                glTexImage2D(GL_TEXTURE_2D, 0, mReadFormat, w, h, 0,
+                        mReadFormat, mReadType, pixels);
+                mWidthScale  = 1.0f / w;
+                mHeightScale =-1.0f / h;
+                mYOffset = 0;
+            } else {
+                GLuint tw = 1 << (31 - clz(w));
+                GLuint th = 1 << (31 - clz(h));
+                if (tw < GLuint(w)) tw <<= 1;
+                if (th < GLuint(h)) th <<= 1;
+                glTexImage2D(GL_TEXTURE_2D, 0, mReadFormat, tw, th, 0,
+                        mReadFormat, mReadType, NULL);
+                glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, 
+                        mReadFormat, mReadType, pixels);
+                mWidthScale  = 1.0f / tw;
+                mHeightScale =-1.0f / th;
+                mYOffset = th-h;
+            }
 
             free((void*)pixels);
         }
-        
+
         const State& s = drawingState();
         if (UNLIKELY(s.alpha < 0xFF)) {
             const GGLfixed alpha = (s.alpha << 16)/255;
@@ -186,7 +215,12 @@
             glDisable(GL_BLEND);
         }
 
-        glDisable(GL_DITHER);
+        if (mFlags & DisplayHardware::SLOW_CONFIG) {
+            glDisable(GL_DITHER);
+        } else {
+            glEnable(GL_DITHER);
+        }
+
         glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
         glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
         glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
@@ -196,37 +230,34 @@
             // This is a very rare scenario.
             glMatrixMode(GL_TEXTURE);
             glLoadIdentity();
-            glScalef(1.0f/w, -1.0f/h, 1);
-            glTranslatef(-x, -y, 0);
+            glScalef(mWidthScale, mHeightScale, 1);
+            glTranslatef(-x, mYOffset - y, 0);
             glEnableClientState(GL_TEXTURE_COORD_ARRAY);
             glVertexPointer(2, GL_FIXED, 0, mVertices);
             glTexCoordPointer(2, GL_FIXED, 0, mVertices);
-            Rect r;
-            while (iterator.iterate(&r)) {
+            while (it != end) {
+                const Rect& r = *it++;
                 const GLint sy = fbHeight - (r.top + r.height());
                 glScissor(r.left, sy, r.width(), r.height());
                 glDrawArrays(GL_TRIANGLE_FAN, 0, 4); 
             }       
+            glDisableClientState(GL_TEXTURE_COORD_ARRAY);
         } else {
-            Region::iterator iterator(clip);
-            if (iterator) {
-                // NOTE: this is marginally faster with the software gl, because
-                // glReadPixels() reads the fb bottom-to-top, however we'll
-                // skip all the jaccobian computations.
-                Rect r;
-                GLint crop[4] = { 0, 0, w, h };
-                glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop);
-                y = fbHeight - (y + h);
-                while (iterator.iterate(&r)) {
-                    const GLint sy = fbHeight - (r.top + r.height());
-                    glScissor(r.left, sy, r.width(), r.height());
-                    glDrawTexiOES(x, y, 0, w, h);
-                }
+            // NOTE: this is marginally faster with the software gl, because
+            // glReadPixels() reads the fb bottom-to-top, however we'll
+            // skip all the jaccobian computations.
+            Rect r;
+            GLint crop[4] = { 0, 0, w, h };
+            glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop);
+            y = fbHeight - (y + h);
+            while (it != end) {
+                const Rect& r = *it++;
+                const GLint sy = fbHeight - (r.top + r.height());
+                glScissor(r.left, sy, r.width(), r.height());
+                glDrawTexiOES(x, y, 0, w, h);
             }
         }
     }
-
-    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
 }
 
 // ---------------------------------------------------------------------------
diff --git a/libs/surfaceflinger/LayerBlur.h b/libs/surfaceflinger/LayerBlur.h
index 24b1156..2e9d7c6 100644
--- a/libs/surfaceflinger/LayerBlur.h
+++ b/libs/surfaceflinger/LayerBlur.h
@@ -39,7 +39,7 @@
     virtual uint32_t getTypeInfo() const { return typeInfo; }
     
                 LayerBlur(SurfaceFlinger* flinger, DisplayID display,
-                        Client* client, int32_t i);
+                        const sp<Client>& client, int32_t i);
         virtual ~LayerBlur();
 
     virtual void onDraw(const Region& clip) const;
@@ -56,6 +56,12 @@
     mutable bool    mAutoRefreshPending;
             nsecs_t mCacheAge;
     mutable GLuint  mTextureName;
+    mutable GLfloat mWidthScale;
+    mutable GLfloat mHeightScale;
+    mutable GLfloat mYOffset;
+    mutable GLint   mReadFormat;
+    mutable GLint   mReadType;
+    mutable uint32_t mBlurFormat;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/libs/surfaceflinger/LayerBuffer.cpp b/libs/surfaceflinger/LayerBuffer.cpp
index 00fab70..a36304c 100644
--- a/libs/surfaceflinger/LayerBuffer.cpp
+++ b/libs/surfaceflinger/LayerBuffer.cpp
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "SurfaceFlinger"
-
 #include <stdlib.h>
 #include <stdint.h>
 #include <math.h>
@@ -25,29 +23,28 @@
 #include <utils/Log.h>
 #include <utils/StopWatch.h>
 
-#include <utils/IPCThreadState.h>
-#include <utils/IServiceManager.h>
-
+#include <ui/GraphicBuffer.h>
 #include <ui/PixelFormat.h>
-#include <ui/EGLDisplaySurface.h>
+#include <ui/FramebufferNativeWindow.h>
+
+#include <hardware/copybit.h>
 
 #include "LayerBuffer.h"
 #include "SurfaceFlinger.h"
-#include "VRamHeap.h"
 #include "DisplayHardware/DisplayHardware.h"
 
-
 namespace android {
 
 // ---------------------------------------------------------------------------
 
 const uint32_t LayerBuffer::typeInfo = LayerBaseClient::typeInfo | 0x20;
 const char* const LayerBuffer::typeID = "LayerBuffer";
+gralloc_module_t const* LayerBuffer::sGrallocModule = 0;
 
 // ---------------------------------------------------------------------------
 
 LayerBuffer::LayerBuffer(SurfaceFlinger* flinger, DisplayID display,
-        Client* client, int32_t i)
+        const sp<Client>& client, int32_t i)
     : LayerBaseClient(flinger, display, client, i),
       mNeedsBlending(false)
 {
@@ -55,30 +52,34 @@
 
 LayerBuffer::~LayerBuffer()
 {
-    sp<SurfaceBuffer> s(getClientSurface());
-    if (s != 0) {
-        s->disown();
-        mClientSurface.clear();
+}
+
+void LayerBuffer::onFirstRef()
+{
+    LayerBaseClient::onFirstRef();
+    mSurface = new SurfaceLayerBuffer(mFlinger, clientIndex(),
+            const_cast<LayerBuffer *>(this));
+
+    hw_module_t const* module = (hw_module_t const*)sGrallocModule;
+    if (!module) {
+        // NOTE: technically there is a race here, but it shouldn't
+        // cause any problem since hw_get_module() always returns
+        // the same value.
+        if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) {
+            sGrallocModule = (gralloc_module_t const *)module;
+        }
     }
 }
 
-sp<LayerBuffer::SurfaceBuffer> LayerBuffer::getClientSurface() const
+sp<LayerBaseClient::Surface> LayerBuffer::createSurface() const
 {
-    Mutex::Autolock _l(mLock);
-    return mClientSurface.promote();
+    return mSurface;
 }
 
-sp<LayerBaseClient::Surface> LayerBuffer::getSurface() const
+status_t LayerBuffer::ditch()
 {
-    sp<SurfaceBuffer> s;
-    Mutex::Autolock _l(mLock);
-    s = mClientSurface.promote();
-    if (s == 0) {
-        s = new SurfaceBuffer(clientIndex(),
-                const_cast<LayerBuffer *>(this));
-        mClientSurface = s;
-    }
-    return s;
+    mSurface.clear();
+    return NO_ERROR;
 }
 
 bool LayerBuffer::needsBlending() const {
@@ -140,6 +141,14 @@
     return false;
 }
 
+void LayerBuffer::serverDestroy()
+{
+    sp<Source> source(clearSource());
+    if (source != 0) {
+        source->destroy();
+    }
+}
+
 /**
  * This creates a "buffer" source for this surface
  */
@@ -189,85 +198,52 @@
 }
 
 // ============================================================================
-// LayerBuffer::SurfaceBuffer
+// LayerBuffer::SurfaceLayerBuffer
 // ============================================================================
 
-LayerBuffer::SurfaceBuffer::SurfaceBuffer(SurfaceID id, LayerBuffer* owner)
-: LayerBaseClient::Surface(id, owner->getIdentity()), mOwner(owner)
+LayerBuffer::SurfaceLayerBuffer::SurfaceLayerBuffer(const sp<SurfaceFlinger>& flinger,
+        SurfaceID id, const sp<LayerBuffer>& owner)
+    : LayerBaseClient::Surface(flinger, id, owner->getIdentity(), owner)
 {
 }
 
-LayerBuffer::SurfaceBuffer::~SurfaceBuffer()
+LayerBuffer::SurfaceLayerBuffer::~SurfaceLayerBuffer()
 {
     unregisterBuffers();
-    mOwner = 0;
 }
 
-status_t LayerBuffer::SurfaceBuffer::onTransact(
-    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+status_t LayerBuffer::SurfaceLayerBuffer::registerBuffers(
+        const ISurface::BufferHeap& buffers)
 {
-    switch (code) {
-        case REGISTER_BUFFERS:
-        case UNREGISTER_BUFFERS:
-        case CREATE_OVERLAY:
-        {
-            // codes that require permission check
-            IPCThreadState* ipc = IPCThreadState::self();
-            const int pid = ipc->getCallingPid();
-            const int self_pid = getpid();
-            if (LIKELY(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 access SurfaceFlinger pid=%d, uid=%d", pid, uid);
-                    return PERMISSION_DENIED;
-                }
-            }
-        }
-    }
-    return LayerBaseClient::Surface::onTransact(code, data, reply, flags);
-}
-
-status_t LayerBuffer::SurfaceBuffer::registerBuffers(const ISurface::BufferHeap& buffers)
-{
-    LayerBuffer* owner(getOwner());
-    if (owner)
+    sp<LayerBuffer> owner(getOwner());
+    if (owner != 0)
         return owner->registerBuffers(buffers);
     return NO_INIT;
 }
 
-void LayerBuffer::SurfaceBuffer::postBuffer(ssize_t offset)
+void LayerBuffer::SurfaceLayerBuffer::postBuffer(ssize_t offset)
 {
-    LayerBuffer* owner(getOwner());
-    if (owner)
+    sp<LayerBuffer> owner(getOwner());
+    if (owner != 0)
         owner->postBuffer(offset);
 }
 
-void LayerBuffer::SurfaceBuffer::unregisterBuffers()
+void LayerBuffer::SurfaceLayerBuffer::unregisterBuffers()
 {
-    LayerBuffer* owner(getOwner());
-    if (owner)
+    sp<LayerBuffer> owner(getOwner());
+    if (owner != 0)
         owner->unregisterBuffers();
 }
 
-sp<OverlayRef> LayerBuffer::SurfaceBuffer::createOverlay(
+sp<OverlayRef> LayerBuffer::SurfaceLayerBuffer::createOverlay(
         uint32_t w, uint32_t h, int32_t format) {
     sp<OverlayRef> result;
-    LayerBuffer* owner(getOwner());
-    if (owner)
+    sp<LayerBuffer> owner(getOwner());
+    if (owner != 0)
         result = owner->createOverlay(w, h, format);
     return result;
 }
 
-void LayerBuffer::SurfaceBuffer::disown()
-{
-    Mutex::Autolock _l(mLock);
-    mOwner = 0;
-}
-
 // ============================================================================
 // LayerBuffer::Buffer
 // ============================================================================
@@ -276,20 +252,36 @@
     : mBufferHeap(buffers)
 {
     NativeBuffer& src(mNativeBuffer);
-    src.crop.l = 0;
-    src.crop.t = 0;
-    src.crop.r = buffers.w;
-    src.crop.b = buffers.h;
-    src.img.w = buffers.hor_stride ?: buffers.w;
-    src.img.h = buffers.ver_stride ?: buffers.h;
-    src.img.format = buffers.format;
-    src.img.offset = offset;
-    src.img.base   = buffers.heap->base();
-    src.img.fd     = buffers.heap->heapID();
+    src.img.handle = 0;
+
+    gralloc_module_t const * module = LayerBuffer::getGrallocModule();
+    if (module && module->perform) {
+        int err = module->perform(module,
+                GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER,
+                buffers.heap->heapID(), buffers.heap->getSize(),
+                offset, buffers.heap->base(),
+                &src.img.handle);
+
+        if (err == NO_ERROR) {
+            src.crop.l = 0;
+            src.crop.t = 0;
+            src.crop.r = buffers.w;
+            src.crop.b = buffers.h;
+
+            src.img.w       = buffers.hor_stride ?: buffers.w;
+            src.img.h       = buffers.ver_stride ?: buffers.h;
+            src.img.format  = buffers.format;
+            src.img.base    = (void*)(intptr_t(buffers.heap->base()) + offset);
+        }
+    }
 }
 
 LayerBuffer::Buffer::~Buffer()
 {
+    NativeBuffer& src(mNativeBuffer);
+    if (src.img.handle) {
+        native_handle_delete(src.img.handle);
+    }
 }
 
 // ============================================================================
@@ -323,8 +315,7 @@
 
 LayerBuffer::BufferSource::BufferSource(LayerBuffer& layer,
         const ISurface::BufferHeap& buffers)
-    : Source(layer), mStatus(NO_ERROR), 
-      mBufferSize(0), mTextureName(-1U)
+    : Source(layer), mStatus(NO_ERROR), mBufferSize(0)
 {
     if (buffers.heap == NULL) {
         // this is allowed, but in this case, it is illegal to receive
@@ -363,13 +354,16 @@
     mLayer.setNeedsBlending((info.h_alpha - info.l_alpha) > 0);    
     mBufferSize = info.getScanlineSize(buffers.hor_stride)*buffers.ver_stride;
     mLayer.forceVisibilityTransaction();
-    
 }
 
 LayerBuffer::BufferSource::~BufferSource()
 {    
-    if (mTextureName != -1U) {
-        LayerBase::deletedTextures.add(mTextureName);
+    if (mTexture.name != -1U) {
+        glDeleteTextures(1, &mTexture.name);
+    }
+    if (mTexture.image != EGL_NO_IMAGE_KHR) {
+        EGLDisplay dpy(mLayer.mFlinger->graphicPlane(0).getEGLDisplay());
+        eglDestroyImageKHR(dpy, mTexture.image);
     }
 }
 
@@ -377,7 +371,7 @@
 {    
     ISurface::BufferHeap buffers;
     { // scope for the lock
-        Mutex::Autolock _l(mLock);
+        Mutex::Autolock _l(mBufferSourceLock);
         buffers = mBufferHeap;
         if (buffers.heap != 0) {
             const size_t memorySize = buffers.heap->getSize();
@@ -402,7 +396,7 @@
 
 void LayerBuffer::BufferSource::unregisterBuffers()
 {
-    Mutex::Autolock _l(mLock);
+    Mutex::Autolock _l(mBufferSourceLock);
     mBufferHeap.heap.clear();
     mBuffer.clear();
     mLayer.invalidate();
@@ -410,13 +404,13 @@
 
 sp<LayerBuffer::Buffer> LayerBuffer::BufferSource::getBuffer() const
 {
-    Mutex::Autolock _l(mLock);
+    Mutex::Autolock _l(mBufferSourceLock);
     return mBuffer;
 }
 
 void LayerBuffer::BufferSource::setBuffer(const sp<LayerBuffer::Buffer>& buffer)
 {
-    Mutex::Autolock _l(mLock);
+    Mutex::Autolock _l(mBufferSourceLock);
     mBuffer = buffer;
 }
 
@@ -427,113 +421,40 @@
 
 void LayerBuffer::BufferSource::onDraw(const Region& clip) const 
 {
-    sp<Buffer> buffer(getBuffer());
-    if (UNLIKELY(buffer == 0))  {
+    sp<Buffer> ourBuffer(getBuffer());
+    if (UNLIKELY(ourBuffer == 0))  {
         // nothing to do, we don't have a buffer
         mLayer.clearWithOpenGL(clip);
         return;
     }
 
     status_t err = NO_ERROR;
-    NativeBuffer src(buffer->getBuffer());
-    const Rect& transformedBounds = mLayer.getTransformedBounds();
-    const int can_use_copybit = mLayer.canUseCopybit();
+    NativeBuffer src(ourBuffer->getBuffer());
+    const Rect transformedBounds(mLayer.getTransformedBounds());
 
-    if (can_use_copybit)  {
-        const int src_width  = src.crop.r - src.crop.l;
-        const int src_height = src.crop.b - src.crop.t;
-        int W = transformedBounds.width();
-        int H = transformedBounds.height();
-        if (mLayer.getOrientation() & Transform::ROT_90) {
-            int t(W); W=H; H=t;
-        }
-
-        /* With LayerBuffer, it is likely that we'll have to rescale the
-         * surface, because this is often used for video playback or
-         * camera-preview. Since we want these operation as fast as possible
-         * we make sure we can use the 2D H/W even if it doesn't support
-         * the requested scale factor, in which case we perform the scaling
-         * in several passes. */
-
-        copybit_device_t* copybit = mLayer.mFlinger->getBlitEngine();
-        const float min = copybit->get(copybit, COPYBIT_MINIFICATION_LIMIT);
-        const float mag = copybit->get(copybit, COPYBIT_MAGNIFICATION_LIMIT);
-
-        float xscale = 1.0f;
-        if (src_width > W*min)          xscale = 1.0f / min;
-        else if (src_width*mag < W)     xscale = mag;
-
-        float yscale = 1.0f;
-        if (src_height > H*min)         yscale = 1.0f / min;
-        else if (src_height*mag < H)    yscale = mag;
-
-        if (UNLIKELY(xscale!=1.0f || yscale!=1.0f)) {
-            if (UNLIKELY(mTemporaryDealer == 0)) {
-                // allocate a memory-dealer for this the first time
-                mTemporaryDealer = mLayer.mFlinger->getSurfaceHeapManager()
-                    ->createHeap(ISurfaceComposer::eHardware);
-                mTempBitmap.init(mTemporaryDealer);
-            }
-
-            const int tmp_w = floorf(src_width  * xscale);
-            const int tmp_h = floorf(src_height * yscale);
-            err = mTempBitmap.setBits(tmp_w, tmp_h, 1, src.img.format);
-
-            if (LIKELY(err == NO_ERROR)) {
-                NativeBuffer tmp;
-                mTempBitmap.getBitmapSurface(&tmp.img);
-                tmp.crop.l = 0;
-                tmp.crop.t = 0;
-                tmp.crop.r = tmp.img.w;
-                tmp.crop.b = tmp.img.h;
-
-                region_iterator tmp_it(Region(Rect(tmp.crop.r, tmp.crop.b)));
-                copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0);
-                copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF);
-                copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_DISABLE);
-                err = copybit->stretch(copybit,
-                        &tmp.img, &src.img, &tmp.crop, &src.crop, &tmp_it);
-                src = tmp;
-            }
-        }
-
-        const DisplayHardware& hw(mLayer.graphicPlane(0).displayHardware());
-        copybit_image_t dst;
-        hw.getDisplaySurface(&dst);
-        const copybit_rect_t& drect
-            = reinterpret_cast<const copybit_rect_t&>(transformedBounds);
-        const State& s(mLayer.drawingState());
-        region_iterator it(clip);
-        
-        // pick the right orientation for this buffer
-        int orientation = mLayer.getOrientation();
-        if (UNLIKELY(mBufferHeap.transform)) {
-            Transform rot90;
-            GraphicPlane::orientationToTransfrom(
-                    ISurfaceComposer::eOrientation90, 0, 0, &rot90);
-            const Transform& planeTransform(mLayer.graphicPlane(0).transform());
-            const Layer::State& s(mLayer.drawingState());
-            Transform tr(planeTransform * s.transform * rot90);
-            orientation = tr.getOrientation();
-        }
-        
-        copybit->set_parameter(copybit, COPYBIT_TRANSFORM, orientation);
-        copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, s.alpha);
-        copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_ENABLE);
-
-        err = copybit->stretch(copybit,
-                &dst, &src.img, &drect, &src.crop, &it);
-        if (err != NO_ERROR) {
-            LOGE("copybit failed (%s)", strerror(err));
-        }
+    if (UNLIKELY(mTexture.name == -1LU)) {
+        mTexture.name = mLayer.createTexture();
     }
 
-    if (!can_use_copybit || err) {
-        if (UNLIKELY(mTextureName == -1LU)) {
-            mTextureName = mLayer.createTexture();
-        }
-        GLuint w = 0;
-        GLuint h = 0;
+#if defined(EGL_ANDROID_image_native_buffer)
+    if (mLayer.mFlags & DisplayHardware::DIRECT_TEXTURE) {
+         // NOTE: Assume the buffer is  allocated with the proper USAGE flags
+        sp<GraphicBuffer> graphicBuffer = new GraphicBuffer(
+                src.crop.r, src.crop.b, src.img.format, 
+                GraphicBuffer::USAGE_HW_TEXTURE,
+                src.img.w, src.img.handle, false);
+
+        graphicBuffer->setVerticalStride(src.img.h);
+
+        err = mLayer.initializeEglImage(graphicBuffer, &mTexture);
+    }
+#endif
+    else {
+        err = INVALID_OPERATION;
+    }
+
+    if (err != NO_ERROR) {
+        // slower fallback
         GGLSurface t;
         t.version = sizeof(GGLSurface);
         t.width  = src.crop.r;
@@ -541,13 +462,14 @@
         t.stride = src.img.w;
         t.vstride= src.img.h;
         t.format = src.img.format;
-        t.data = (GGLubyte*)(intptr_t(src.img.base) + src.img.offset);
+        t.data = (GGLubyte*)src.img.base;
         const Region dirty(Rect(t.width, t.height));
-        mLayer.loadTexture(dirty, mTextureName, t, w, h);
-        mLayer.drawWithOpenGL(clip, mTextureName, t, mBufferHeap.transform);
+        mLayer.loadTexture(&mTexture, dirty, t);
     }
-}
 
+    mTexture.transform = mBufferHeap.transform;
+    mLayer.drawWithOpenGL(clip, mTexture);
+}
 
 // ---------------------------------------------------------------------------
 
@@ -580,15 +502,15 @@
     mFormat = overlay->format; 
     mWidthStride = overlay->w_stride;
     mHeightStride = overlay->h_stride;
+    mInitialized = false;
 
     mOverlayHandle = overlay->getHandleRef(overlay);
     
-    // NOTE: here it's okay to acquire a reference to "this"m as long as
-    // the reference is not released before we leave the ctor.
-    sp<OverlayChannel> channel = new OverlayChannel(this);
+    sp<OverlayChannel> channel = new OverlayChannel( &layer );
 
     *overlayRef = new OverlayRef(mOverlayHandle, channel,
             mWidth, mHeight, mFormat, mWidthStride, mHeightStride);
+    mLayer.mFlinger->signalEvent();
 }
 
 LayerBuffer::OverlaySource::~OverlaySource()
@@ -599,6 +521,15 @@
     }
 }
 
+void LayerBuffer::OverlaySource::onDraw(const Region& clip) const
+{
+    // this would be where the color-key would be set, should we need it.
+    GLclampx red = 0;
+    GLclampx green = 0;
+    GLclampx blue = 0;
+    mLayer.clearWithOpenGL(clip, red, green, blue, 0);
+}
+
 void LayerBuffer::OverlaySource::onTransaction(uint32_t flags)
 {
     const Layer::State& front(mLayer.drawingState());
@@ -614,37 +545,33 @@
     // this code-path must be as tight as possible, it's called each time
     // the screen is composited.
     if (UNLIKELY(mOverlay != 0)) {
-        if (mVisibilityChanged) {
+        if (mVisibilityChanged || !mInitialized) {
             mVisibilityChanged = false;
-            const Rect& bounds = mLayer.getTransformedBounds();
+            mInitialized = true;
+            const Rect bounds(mLayer.getTransformedBounds());
             int x = bounds.left;
             int y = bounds.top;
             int w = bounds.width();
             int h = bounds.height();
             
             // we need a lock here to protect "destroy"
-            Mutex::Autolock _l(mLock);
+            Mutex::Autolock _l(mOverlaySourceLock);
             if (mOverlay) {
                 overlay_control_device_t* overlay_dev = mOverlayDevice;
                 overlay_dev->setPosition(overlay_dev, mOverlay, x,y,w,h);
-                overlay_dev->setParameter(overlay_dev, mOverlay, 
+                overlay_dev->setParameter(overlay_dev, mOverlay,
                         OVERLAY_TRANSFORM, mLayer.getOrientation());
+                overlay_dev->commit(overlay_dev, mOverlay);
             }
         }
     }
 }
 
-void LayerBuffer::OverlaySource::serverDestroy() 
-{
-    mLayer.clearSource();
-    destroyOverlay();
-}
-
-void LayerBuffer::OverlaySource::destroyOverlay() 
+void LayerBuffer::OverlaySource::destroy()
 {
     // we need a lock here to protect "onVisibilityResolved"
-    Mutex::Autolock _l(mLock);
-    if (mOverlay) {
+    Mutex::Autolock _l(mOverlaySourceLock);
+    if (mOverlay && mOverlayDevice) {
         overlay_control_device_t* overlay_dev = mOverlayDevice;
         overlay_dev->destroyOverlay(overlay_dev, mOverlay);
         mOverlay = 0;
diff --git a/libs/surfaceflinger/LayerBuffer.h b/libs/surfaceflinger/LayerBuffer.h
index 2dc77f1..47482f4 100644
--- a/libs/surfaceflinger/LayerBuffer.h
+++ b/libs/surfaceflinger/LayerBuffer.h
@@ -20,21 +20,20 @@
 #include <stdint.h>
 #include <sys/types.h>
 
-#include <utils/IMemory.h>
-#include <private/ui/LayerState.h>
-#include <EGL/eglnatives.h>
-
 #include "LayerBase.h"
-#include "LayerBitmap.h"
+
+struct copybit_device_t;
 
 namespace android {
 
 // ---------------------------------------------------------------------------
 
-class MemoryDealer;
+class Buffer;
 class Region;
 class OverlayRef;
 
+// ---------------------------------------------------------------------------
+
 class LayerBuffer : public LayerBaseClient
 {
     class Source : public LightRefBase<Source> {
@@ -47,11 +46,11 @@
         virtual void postBuffer(ssize_t offset);
         virtual void unregisterBuffers();
         virtual bool transformed() const;
+        virtual void destroy() { }
     protected:
         LayerBuffer& mLayer;
     };
 
-
 public:
     static const uint32_t typeInfo;
     static const char* const typeID;
@@ -59,12 +58,14 @@
     virtual uint32_t getTypeInfo() const { return typeInfo; }
 
             LayerBuffer(SurfaceFlinger* flinger, DisplayID display,
-                        Client* client, int32_t i);
+                    const sp<Client>& client, int32_t i);
         virtual ~LayerBuffer();
 
+    virtual void onFirstRef();
     virtual bool needsBlending() const;
 
-    virtual sp<LayerBaseClient::Surface> getSurface() const;
+    virtual sp<LayerBaseClient::Surface> createSurface() const;
+    virtual status_t ditch();
     virtual void onDraw(const Region& clip) const;
     virtual uint32_t doTransaction(uint32_t flags);
     virtual void unlockPageFlip(const Transform& planeTransform, Region& outDirtyRegion);
@@ -78,16 +79,23 @@
     sp<Source> getSource() const;
     sp<Source> clearSource();
     void setNeedsBlending(bool blending);
-    const Rect& getTransformedBounds() const {
+    Rect getTransformedBounds() const {
         return mTransformedBounds;
     }
 
+    void serverDestroy();
+
 private:
     struct NativeBuffer {
         copybit_image_t   img;
         copybit_rect_t    crop;
     };
 
+    static gralloc_module_t const* sGrallocModule;
+    static gralloc_module_t const* getGrallocModule() {
+        return sGrallocModule;
+    }
+
     class Buffer : public LightRefBase<Buffer> {
     public:
         Buffer(const ISurface::BufferHeap& buffers, ssize_t offset);
@@ -120,15 +128,15 @@
         virtual void postBuffer(ssize_t offset);
         virtual void unregisterBuffers();
         virtual bool transformed() const;
+        virtual void destroy() { }
     private:
-        mutable Mutex   mLock;
-        sp<Buffer>      mBuffer;
-        status_t        mStatus;
-        ISurface::BufferHeap mBufferHeap;
-        size_t          mBufferSize;
-        mutable sp<MemoryDealer> mTemporaryDealer;
-        mutable LayerBitmap mTempBitmap;
-        mutable GLuint  mTextureName;
+        mutable Mutex                   mBufferSourceLock;
+        sp<Buffer>                      mBuffer;
+        status_t                        mStatus;
+        ISurface::BufferHeap            mBufferHeap;
+        size_t                          mBufferSize;
+        mutable sp<GraphicBuffer>       mTempBitmap;
+        mutable LayerBase::Texture      mTexture;
     };
     
     class OverlaySource : public Source {
@@ -137,30 +145,26 @@
                 sp<OverlayRef>* overlayRef, 
                 uint32_t w, uint32_t h, int32_t format);
         virtual ~OverlaySource();
+        virtual void onDraw(const Region& clip) const;
         virtual void onTransaction(uint32_t flags);
         virtual void onVisibilityResolved(const Transform& planeTransform);
+        virtual void destroy();
     private:
-        void serverDestroy(); 
-        void destroyOverlay(); 
+
         class OverlayChannel : public BnOverlay {
-            mutable Mutex mLock;
-            sp<OverlaySource> mSource;
+            wp<LayerBuffer> mLayer;
             virtual void destroy() {
-                sp<OverlaySource> source;
-                { // scope for the lock;
-                    Mutex::Autolock _l(mLock);
-                    source = mSource;
-                    mSource.clear();
-                }
-                if (source != 0) {
-                    source->serverDestroy();
+                sp<LayerBuffer> layer(mLayer.promote());
+                if (layer != 0) {
+                    layer->serverDestroy();
                 }
             }
         public:
-            OverlayChannel(const sp<OverlaySource>& source)
-                : mSource(source) {
+            OverlayChannel(const sp<LayerBuffer>& layer)
+                : mLayer(layer) {
             }
         };
+        
         friend class OverlayChannel;
         bool mVisibilityChanged;
 
@@ -172,41 +176,35 @@
         int32_t mFormat;
         int32_t mWidthStride;
         int32_t mHeightStride;
-        mutable Mutex mLock;
+        mutable Mutex mOverlaySourceLock;
+        bool mInitialized;
     };
 
 
-    class SurfaceBuffer : public LayerBaseClient::Surface
+    class SurfaceLayerBuffer : public LayerBaseClient::Surface
     {
     public:
-                SurfaceBuffer(SurfaceID id, LayerBuffer* owner);
-        virtual ~SurfaceBuffer();
-        virtual status_t onTransact(
-            uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);
+        SurfaceLayerBuffer(const sp<SurfaceFlinger>& flinger,
+                        SurfaceID id, const sp<LayerBuffer>& owner);
+        virtual ~SurfaceLayerBuffer();
+
         virtual status_t registerBuffers(const ISurface::BufferHeap& buffers);
         virtual void postBuffer(ssize_t offset);
         virtual void unregisterBuffers();
+        
         virtual sp<OverlayRef> createOverlay(
                 uint32_t w, uint32_t h, int32_t format);
-       void disown();
     private:
-        LayerBuffer* getOwner() const {
-            Mutex::Autolock _l(mLock);
-            return mOwner;
+        sp<LayerBuffer> getOwner() const {
+            return static_cast<LayerBuffer*>(Surface::getOwner().get());
         }
-        mutable Mutex   mLock;
-        LayerBuffer*    mOwner;
     };
 
-    friend class SurfaceFlinger;
-    sp<SurfaceBuffer>   getClientSurface() const;
-
     mutable Mutex   mLock;
     sp<Source>      mSource;
-
+    sp<Surface>     mSurface;
     bool            mInvalidate;
     bool            mNeedsBlending;
-    mutable wp<SurfaceBuffer> mClientSurface;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/libs/surfaceflinger/LayerDim.cpp b/libs/surfaceflinger/LayerDim.cpp
index 0c347cc..fd61e30 100644
--- a/libs/surfaceflinger/LayerDim.cpp
+++ b/libs/surfaceflinger/LayerDim.cpp
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "SurfaceFlinger"
-
 #include <stdlib.h>
 #include <stdint.h>
 #include <sys/types.h>
@@ -23,9 +21,10 @@
 #include <utils/Errors.h>
 #include <utils/Log.h>
 
+#include <ui/GraphicBuffer.h>
+
 #include "LayerDim.h"
 #include "SurfaceFlinger.h"
-#include "VRamHeap.h"
 #include "DisplayHardware/DisplayHardware.h"
 
 namespace android {
@@ -33,27 +32,76 @@
 
 const uint32_t LayerDim::typeInfo = LayerBaseClient::typeInfo | 0x10;
 const char* const LayerDim::typeID = "LayerDim";
-sp<MemoryDealer> LayerDim::mDimmerDealer;
-LayerBitmap LayerDim::mDimmerBitmap;
+
+bool LayerDim::sUseTexture;
+GLuint LayerDim::sTexId;
+EGLImageKHR LayerDim::sImage;
+int32_t LayerDim::sWidth;
+int32_t LayerDim::sHeight;
 
 // ---------------------------------------------------------------------------
 
 LayerDim::LayerDim(SurfaceFlinger* flinger, DisplayID display,
-        Client* client, int32_t i)
-     : LayerBaseClient(flinger, display, client, i)
+        const sp<Client>& client, int32_t i)
+    : LayerBaseClient(flinger, display, client, i)
 {
 }
 
 void LayerDim::initDimmer(SurfaceFlinger* flinger, uint32_t w, uint32_t h)
 {
-    // must only be called once.
-    mDimmerDealer = flinger->getSurfaceHeapManager()
-            ->createHeap(ISurfaceComposer::eHardware);
-    if (mDimmerDealer != 0) {
-        mDimmerBitmap.init(mDimmerDealer);
-        mDimmerBitmap.setBits(w, h, 1, PIXEL_FORMAT_RGB_565);
-        mDimmerBitmap.clear();
+    sTexId = -1;
+    sImage = EGL_NO_IMAGE_KHR;
+    sWidth = w;
+    sHeight = h;
+    sUseTexture = false;
+    
+#if defined(DIM_WITH_TEXTURE) && defined(EGL_ANDROID_image_native_buffer)
+
+#warning "using a texture to implement LayerDim"
+    
+    /* On some h/w like msm7K, it is faster to use a texture because the
+     * software renderer will defer to copybit, for this to work we need to
+     * use an EGLImage texture so copybit can actually make use of it.
+     * This burns a full-screen worth of graphic memory.
+     */
+
+    const DisplayHardware& hw(flinger->graphicPlane(0).displayHardware());
+    uint32_t flags = hw.getFlags();
+
+    if (LIKELY(flags & DisplayHardware::DIRECT_TEXTURE)) {
+        sp<GraphicBuffer> buffer = new GraphicBuffer(w, h, PIXEL_FORMAT_RGB_565,
+                 GraphicBuffer::USAGE_SW_WRITE_OFTEN |
+                 GraphicBuffer::USAGE_HW_TEXTURE);
+        
+        android_native_buffer_t* clientBuf = buffer->getNativeBuffer();
+
+        glGenTextures(1, &sTexId);
+        glBindTexture(GL_TEXTURE_2D, sTexId);
+
+        EGLDisplay dpy = eglGetCurrentDisplay();
+        sImage = eglCreateImageKHR(dpy, EGL_NO_CONTEXT, 
+                EGL_NATIVE_BUFFER_ANDROID, (EGLClientBuffer)clientBuf, 0);
+        if (sImage == EGL_NO_IMAGE_KHR) {
+            LOGE("eglCreateImageKHR() failed. err=0x%4x", eglGetError());
+            return;
+        }
+
+        glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)sImage);
+        GLint error = glGetError();
+        if (error != GL_NO_ERROR) {
+            eglDestroyImageKHR(dpy, sImage);
+            LOGE("glEGLImageTargetTexture2DOES() failed. err=0x%4x", error);
+            return;
+        }
+
+        // initialize the texture with zeros
+        GGLSurface t;
+        buffer->lock(&t, GRALLOC_USAGE_SW_WRITE_OFTEN);
+        memset(t.data, 0, t.stride * t.height * 2);
+        buffer->unlock();
+        sUseTexture = true;
     }
+#endif
 }
 
 LayerDim::~LayerDim()
@@ -63,49 +111,56 @@
 void LayerDim::onDraw(const Region& clip) const
 {
     const State& s(drawingState());
-
-    Region::iterator iterator(clip);
-    if (s.alpha>0 && iterator) {
+    Region::const_iterator it = clip.begin();
+    Region::const_iterator const end = clip.end();
+    if (s.alpha>0 && (it != end)) {
         const DisplayHardware& hw(graphicPlane(0).displayHardware());
-
-        status_t err = NO_ERROR;
-        const int can_use_copybit = canUseCopybit();
-        if (can_use_copybit)  {
-            // StopWatch watch("copybit");
-            copybit_image_t dst;
-            hw.getDisplaySurface(&dst);
-            const copybit_rect_t& drect
-                = reinterpret_cast<const copybit_rect_t&>(mTransformedBounds);
-
-            copybit_image_t src;
-            mDimmerBitmap.getBitmapSurface(&src);
-            const copybit_rect_t& srect(drect);
-
-            copybit_device_t* copybit = mFlinger->getBlitEngine();
-            copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0);
-            copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, s.alpha);
-            copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_ENABLE);
-            region_iterator it(clip);
-            err = copybit->stretch(copybit, &dst, &src, &drect, &srect, &it);
+        const GGLfixed alpha = (s.alpha << 16)/255;
+        const uint32_t fbHeight = hw.getHeight();
+        glDisable(GL_DITHER);
+        glEnable(GL_BLEND);
+        glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+        glColor4x(0, 0, 0, alpha);
+        
+#if defined(DIM_WITH_TEXTURE) && defined(EGL_ANDROID_image_native_buffer)
+        if (sUseTexture) {
+            glBindTexture(GL_TEXTURE_2D, sTexId);
+            glEnable(GL_TEXTURE_2D);
+            glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+            const GLshort texCoords[4][2] = {
+                    { 0,  0 },
+                    { 0,  1 },
+                    { 1,  1 },
+                    { 1,  0 }
+            };
+            glMatrixMode(GL_TEXTURE);
+            glLoadIdentity();
+            glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+            glTexCoordPointer(2, GL_SHORT, 0, texCoords);
+        } else
+#endif
+        {
+            glDisable(GL_TEXTURE_2D);
         }
 
-        if (!can_use_copybit || err) {
-            const GGLfixed alpha = (s.alpha << 16)/255;
-            const uint32_t fbHeight = hw.getHeight();
-            glDisable(GL_TEXTURE_2D);
-            glDisable(GL_DITHER);
-            glEnable(GL_BLEND);
-            glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
-            glColor4x(0, 0, 0, alpha);
-            glVertexPointer(2, GL_FIXED, 0, mVertices);
-            Rect r;
-            while (iterator.iterate(&r)) {
-                const GLint sy = fbHeight - (r.top + r.height());
-                glScissor(r.left, sy, r.width(), r.height());
-                glDrawArrays(GL_TRIANGLE_FAN, 0, 4); 
-            }
+        GLshort w = sWidth;
+        GLshort h = sHeight;
+        const GLshort vertices[4][2] = {
+                { 0, 0 },
+                { 0, h },
+                { w, h },
+                { w, 0 }
+        };
+        glVertexPointer(2, GL_SHORT, 0, vertices);
+
+        while (it != end) {
+            const Rect& r = *it++;
+            const GLint sy = fbHeight - (r.top + r.height());
+            glScissor(r.left, sy, r.width(), r.height());
+            glDrawArrays(GL_TRIANGLE_FAN, 0, 4); 
         }
     }
+    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
 }
 
 // ---------------------------------------------------------------------------
diff --git a/libs/surfaceflinger/LayerDim.h b/libs/surfaceflinger/LayerDim.h
index 3e37a47..d4672a1 100644
--- a/libs/surfaceflinger/LayerDim.h
+++ b/libs/surfaceflinger/LayerDim.h
@@ -20,15 +20,22 @@
 #include <stdint.h>
 #include <sys/types.h>
 
-#include "LayerBase.h"
-#include "LayerBitmap.h"
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
 
-namespace android {
+#include "LayerBase.h"
 
 // ---------------------------------------------------------------------------
 
+namespace android {
+
 class LayerDim : public LayerBaseClient
 {
+    static bool sUseTexture;
+    static GLuint sTexId;
+    static EGLImageKHR sImage;
+    static int32_t sWidth;
+    static int32_t sHeight;
 public:    
     static const uint32_t typeInfo;
     static const char* const typeID;
@@ -36,7 +43,7 @@
     virtual uint32_t getTypeInfo() const { return typeInfo; }
     
                 LayerDim(SurfaceFlinger* flinger, DisplayID display,
-                        Client* client, int32_t i);
+                        const sp<Client>& client, int32_t i);
         virtual ~LayerDim();
 
     virtual void onDraw(const Region& clip) const;
@@ -44,10 +51,6 @@
     virtual bool isSecure() const       { return false; }
 
     static void initDimmer(SurfaceFlinger* flinger, uint32_t w, uint32_t h);
-
-private:
-    static sp<MemoryDealer> mDimmerDealer;
-    static LayerBitmap mDimmerBitmap;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/libs/surfaceflinger/LayerOrientationAnim.cpp b/libs/surfaceflinger/LayerOrientationAnim.cpp
deleted file mode 100644
index 79e5328..0000000
--- a/libs/surfaceflinger/LayerOrientationAnim.cpp
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "SurfaceFlinger"
-
-#include <stdlib.h>
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <utils/Errors.h>
-#include <utils/Log.h>
-#include <utils/StopWatch.h>
-
-#include <core/SkBitmap.h>
-
-#include <ui/EGLDisplaySurface.h>
-
-#include "BlurFilter.h"
-#include "LayerBase.h"
-#include "LayerOrientationAnim.h"
-#include "SurfaceFlinger.h"
-#include "DisplayHardware/DisplayHardware.h"
-#include "OrientationAnimation.h"
-
-namespace android {
-// ---------------------------------------------------------------------------
-
-const uint32_t LayerOrientationAnim::typeInfo = LayerBase::typeInfo | 0x80;
-const char* const LayerOrientationAnim::typeID = "LayerOrientationAnim";
-
-// ---------------------------------------------------------------------------
-
-// Animation...
-const float DURATION = ms2ns(200);
-const float BOUNCES_PER_SECOND = 0.5f;
-const float DIM_TARGET = 0.40f;
-#define INTERPOLATED_TIME(_t)   (_t)
-
-// ---------------------------------------------------------------------------
-
-LayerOrientationAnim::LayerOrientationAnim(
-        SurfaceFlinger* flinger, DisplayID display, 
-        OrientationAnimation* anim, 
-        const LayerBitmap& bitmapIn,
-        const LayerBitmap& bitmapOut)
-    : LayerOrientationAnimBase(flinger, display), mAnim(anim), 
-      mBitmapIn(bitmapIn), mBitmapOut(bitmapOut), 
-      mTextureName(-1), mTextureNameIn(-1)
-{
-    // blur that texture. 
-    mOrientationCompleted = false;
-    mNeedsBlending = false;
-}
-
-LayerOrientationAnim::~LayerOrientationAnim()
-{
-    if (mTextureName != -1U) {
-        LayerBase::deletedTextures.add(mTextureName);
-    }
-    if (mTextureNameIn != -1U) {
-        LayerBase::deletedTextures.add(mTextureNameIn);
-    }
-}
-
-bool LayerOrientationAnim::needsBlending() const 
-{
-    return mNeedsBlending; 
-}
-
-Point LayerOrientationAnim::getPhysicalSize() const
-{
-    const GraphicPlane& plane(graphicPlane(0));
-    const DisplayHardware& hw(plane.displayHardware());
-    return Point(hw.getWidth(), hw.getHeight());
-}
-
-void LayerOrientationAnim::validateVisibility(const Transform&)
-{
-    const Layer::State& s(drawingState());
-    const Transform tr(s.transform);
-    const Point size(getPhysicalSize());
-    uint32_t w = size.x;
-    uint32_t h = size.y;
-    mTransformedBounds = tr.makeBounds(w, h);
-    mLeft = tr.tx();
-    mTop  = tr.ty();
-    transparentRegionScreen.clear();
-    mTransformed = true;
-    mCanUseCopyBit = false;
-    copybit_device_t* copybit = mFlinger->getBlitEngine();
-    if (copybit) { 
-        mCanUseCopyBit = true;
-    }
-}
-
-void LayerOrientationAnim::onOrientationCompleted()
-{
-    mAnim->onAnimationFinished();
-}
-
-void LayerOrientationAnim::onDraw(const Region& clip) const
-{
-    float alphaIn =  DIM_TARGET;
-    
-    // clear screen
-    // TODO: with update on demand, we may be able 
-    // to not erase the screen at all during the animation 
-    if (!mOrientationCompleted) {
-        glDisable(GL_BLEND);
-        glDisable(GL_DITHER);
-        glDisable(GL_SCISSOR_TEST);
-        glClearColor(0,0,0,0);
-        glClear(GL_COLOR_BUFFER_BIT);
-    }
-    
-    copybit_image_t dst;
-    const GraphicPlane& plane(graphicPlane(0));
-    const DisplayHardware& hw(plane.displayHardware());
-    hw.getDisplaySurface(&dst);
-
-    copybit_image_t src;
-    mBitmapIn.getBitmapSurface(&src);
-
-    copybit_image_t srcOut;
-    mBitmapOut.getBitmapSurface(&srcOut);
-
-    const int w = dst.w; 
-    const int h = dst.h; 
-    const int xc = uint32_t(dst.w-w)/2;
-    const int yc = uint32_t(dst.h-h)/2;
-    const copybit_rect_t drect = { xc, yc, xc+w, yc+h }; 
-    const copybit_rect_t srect = { 0, 0, src.w, src.h };
-    const Region reg(Rect( drect.l, drect.t, drect.r, drect.b ));
-
-    int err = NO_ERROR;
-    const int can_use_copybit = canUseCopybit();
-    if (can_use_copybit)  {
-        copybit_device_t* copybit = mFlinger->getBlitEngine();
-        copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0);
-        copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_ENABLE);
-        
-        if (alphaIn > 0) {
-            region_iterator it(reg);
-            copybit->set_parameter(copybit, COPYBIT_BLUR, COPYBIT_ENABLE);
-            copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, int(alphaIn*255));
-            err = copybit->stretch(copybit, &dst, &src, &drect, &srect, &it);
-            copybit->set_parameter(copybit, COPYBIT_BLUR, COPYBIT_DISABLE);
-        }
-        LOGE_IF(err != NO_ERROR, "copybit failed (%s)", strerror(err));
-    }
-    if (!can_use_copybit || err) {   
-        GGLSurface t;
-        t.version = sizeof(GGLSurface);
-        t.width  = src.w;
-        t.height = src.h;
-        t.stride = src.w;
-        t.vstride= src.h;
-        t.format = src.format;
-        t.data = (GGLubyte*)(intptr_t(src.base) + src.offset);
-
-        Transform tr;
-        tr.set(xc, yc);
-        
-        // FIXME: we should not access mVertices and mDrawingState like that,
-        // but since we control the animation, we know it's going to work okay.
-        // eventually we'd need a more formal way of doing things like this.
-        LayerOrientationAnim& self(const_cast<LayerOrientationAnim&>(*this));
-        tr.transform(self.mVertices[0], 0, 0);
-        tr.transform(self.mVertices[1], 0, src.h);
-        tr.transform(self.mVertices[2], src.w, src.h);
-        tr.transform(self.mVertices[3], src.w, 0);
-        if (!(mFlags & DisplayHardware::SLOW_CONFIG)) {
-            // Too slow to do this in software
-            self.mDrawingState.flags |= ISurfaceComposer::eLayerFilter;
-        }
-
-        if (alphaIn > 0.0f) {
-            t.data = (GGLubyte*)(intptr_t(src.base) + src.offset);
-            if (UNLIKELY(mTextureNameIn == -1LU)) {
-                mTextureNameIn = createTexture();
-                GLuint w=0, h=0;
-                const Region dirty(Rect(t.width, t.height));
-                loadTexture(dirty, mTextureNameIn, t, w, h);
-            }
-            self.mDrawingState.alpha = int(alphaIn*255);
-            drawWithOpenGL(reg, mTextureNameIn, t);
-        }
-    }
-}
-
-// ---------------------------------------------------------------------------
-
-}; // namespace android
diff --git a/libs/surfaceflinger/LayerOrientationAnim.h b/libs/surfaceflinger/LayerOrientationAnim.h
deleted file mode 100644
index 12b6f1c..0000000
--- a/libs/surfaceflinger/LayerOrientationAnim.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_LAYER_ORIENTATION_ANIM_H
-#define ANDROID_LAYER_ORIENTATION_ANIM_H
-
-#include <stdint.h>
-#include <sys/types.h>
-#include <utils/threads.h>
-#include <utils/Parcel.h>
-
-#include "LayerBase.h"
-#include "LayerBitmap.h"
-
-namespace android {
-
-// ---------------------------------------------------------------------------
-class OrientationAnimation;
-
-
-class LayerOrientationAnimBase : public LayerBase
-{
-public:
-    LayerOrientationAnimBase(SurfaceFlinger* flinger, DisplayID display)
-        : LayerBase(flinger, display) {
-    }
-    virtual void onOrientationCompleted() = 0;
-};
-
-// ---------------------------------------------------------------------------
-
-class LayerOrientationAnim : public LayerOrientationAnimBase
-{
-public:    
-    static const uint32_t typeInfo;
-    static const char* const typeID;
-    virtual char const* getTypeID() const { return typeID; }
-    virtual uint32_t getTypeInfo() const { return typeInfo; }
-    
-                LayerOrientationAnim(SurfaceFlinger* flinger, DisplayID display,
-                        OrientationAnimation* anim, 
-                        const LayerBitmap& bitmapIn,
-                        const LayerBitmap& bitmapOut);
-        virtual ~LayerOrientationAnim();
-
-            void onOrientationCompleted();
-
-    virtual void onDraw(const Region& clip) const;
-    virtual Point getPhysicalSize() const;
-    virtual void validateVisibility(const Transform& globalTransform);
-    virtual bool needsBlending() const;
-    virtual bool isSecure() const       { return false; }
-private:
-    OrientationAnimation* mAnim;
-    LayerBitmap mBitmapIn;
-    LayerBitmap mBitmapOut;
-    bool mOrientationCompleted;
-    mutable GLuint  mTextureName;
-    mutable GLuint  mTextureNameIn;
-    mutable bool mNeedsBlending;
-};
-
-// ---------------------------------------------------------------------------
-
-}; // namespace android
-
-#endif // ANDROID_LAYER_ORIENTATION_ANIM_H
diff --git a/libs/surfaceflinger/MessageQueue.cpp b/libs/surfaceflinger/MessageQueue.cpp
new file mode 100644
index 0000000..b43d801
--- /dev/null
+++ b/libs/surfaceflinger/MessageQueue.cpp
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2009 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 <errno.h>
+#include <sys/types.h>
+
+#include <utils/threads.h>
+#include <utils/Timers.h>
+#include <utils/Log.h>
+#include <binder/IPCThreadState.h>
+
+#include "MessageQueue.h"
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+void MessageList::insert(const sp<MessageBase>& node) 
+{
+    LIST::iterator cur(mList.begin());
+    LIST::iterator end(mList.end());
+    while (cur != end) {
+        if (*node < **cur) {
+            mList.insert(cur, node);
+            return;
+        }
+        ++cur;
+    }
+    mList.insert(++end, node);
+}
+
+void MessageList::remove(MessageList::LIST::iterator pos) 
+{
+    mList.erase(pos);
+}
+
+// ---------------------------------------------------------------------------
+
+MessageQueue::MessageQueue()
+    : mInvalidate(false)
+{
+    mInvalidateMessage = new MessageBase(INVALIDATE);
+}
+
+MessageQueue::~MessageQueue()
+{
+}
+
+MessageList::value_type MessageQueue::waitMessage(nsecs_t timeout)
+{
+    MessageList::value_type result;
+
+    bool again;
+    do {
+        const nsecs_t timeoutTime = systemTime() + timeout;
+        while (true) {
+            Mutex::Autolock _l(mLock);
+            nsecs_t now = systemTime();
+            nsecs_t nextEventTime = -1;
+
+            // invalidate messages are always handled first
+            if (mInvalidate) {
+                mInvalidate = false;
+                mInvalidateMessage->when = now;
+                result = mInvalidateMessage;
+                break;
+            }
+
+            LIST::iterator cur(mMessages.begin());
+            if (cur != mMessages.end()) {
+                result = *cur;
+            }
+            
+            if (result != 0) {
+                if (result->when <= now) {
+                    // there is a message to deliver
+                    mMessages.remove(cur);
+                    break;
+                }
+                if (timeout>=0 && timeoutTime < now) {
+                    // we timed-out, return a NULL message
+                    result = 0;
+                    break;
+                }
+                nextEventTime = result->when;
+                result = 0;
+            }
+
+            if (timeout >= 0 && nextEventTime > 0) {
+                if (nextEventTime > timeoutTime) {
+                    nextEventTime = timeoutTime;
+                }
+            }
+
+            if (nextEventTime >= 0) {
+                //LOGD("nextEventTime = %lld ms", nextEventTime);
+                if (nextEventTime > 0) {
+                    // we're about to wait, flush the binder command buffer
+                    IPCThreadState::self()->flushCommands();
+                    const nsecs_t reltime = nextEventTime - systemTime();
+                    if (reltime > 0) {
+                        mCondition.waitRelative(mLock, reltime);
+                    }
+                }
+            } else {
+                //LOGD("going to wait");
+                // we're about to wait, flush the binder command buffer
+                IPCThreadState::self()->flushCommands();
+                mCondition.wait(mLock);
+            }
+        } 
+        // here we're not holding the lock anymore
+
+        if (result == 0)
+            break;
+
+        again = result->handler();
+        if (again) {
+            // the message has been processed. release our reference to it
+            // without holding the lock.
+            result = 0;
+        }
+        
+    } while (again);
+
+    return result;
+}
+
+status_t MessageQueue::postMessage(
+        const MessageList::value_type& message, nsecs_t relTime, uint32_t flags)
+{
+    return queueMessage(message, relTime, flags);
+}
+
+status_t MessageQueue::invalidate() {
+    Mutex::Autolock _l(mLock);
+    mInvalidate = true;
+    mCondition.signal();
+    return NO_ERROR;
+}
+
+status_t MessageQueue::queueMessage(
+        const MessageList::value_type& message, nsecs_t relTime, uint32_t flags)
+{
+    Mutex::Autolock _l(mLock);
+    message->when = systemTime() + relTime;
+    mMessages.insert(message);
+    
+    //LOGD("MessageQueue::queueMessage time = %lld ms", message->when);
+    //dumpLocked(message);
+
+    mCondition.signal();
+    return NO_ERROR;
+}
+
+void MessageQueue::dump(const MessageList::value_type& message)
+{
+    Mutex::Autolock _l(mLock);
+    dumpLocked(message);
+}
+
+void MessageQueue::dumpLocked(const MessageList::value_type& message)
+{
+    LIST::const_iterator cur(mMessages.begin());
+    LIST::const_iterator end(mMessages.end());
+    int c = 0;
+    while (cur != end) {
+        const char tick = (*cur == message) ? '>' : ' ';
+        LOGD("%c %d: msg{.what=%08x, when=%lld}",
+                tick, c, (*cur)->what, (*cur)->when);
+        ++cur;
+        c++;
+    }
+}
+
+// ---------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/libs/surfaceflinger/MessageQueue.h b/libs/surfaceflinger/MessageQueue.h
new file mode 100644
index 0000000..dc8138d
--- /dev/null
+++ b/libs/surfaceflinger/MessageQueue.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_MESSAGE_QUEUE_H
+#define ANDROID_MESSAGE_QUEUE_H
+
+#include <stdint.h>
+#include <errno.h>
+#include <sys/types.h>
+
+#include <utils/threads.h>
+#include <utils/Timers.h>
+#include <utils/List.h>
+
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+class MessageBase;
+
+class MessageList 
+{
+    List< sp<MessageBase> > mList;
+    typedef List< sp<MessageBase> > LIST;
+public:
+    typedef sp<MessageBase> value_type;
+    inline LIST::iterator begin()                { return mList.begin(); }
+    inline LIST::const_iterator begin() const    { return mList.begin(); }
+    inline LIST::iterator end()                  { return mList.end(); }
+    inline LIST::const_iterator end() const      { return mList.end(); }
+    inline bool isEmpty() const { return mList.empty(); }
+    void insert(const sp<MessageBase>& node);
+    void remove(LIST::iterator pos);
+};
+
+// ============================================================================
+
+class MessageBase : 
+    public LightRefBase<MessageBase>
+{
+public:
+    nsecs_t     when;
+    uint32_t    what;
+    int32_t     arg0;    
+
+    MessageBase() : when(0), what(0), arg0(0) { }
+    MessageBase(uint32_t what, int32_t arg0=0)
+        : when(0), what(what), arg0(arg0) { }
+    
+    // return true if message has a handler
+    virtual bool handler() { return false; }
+    
+protected:
+    virtual ~MessageBase() { }
+
+private:
+    friend class LightRefBase<MessageBase>;
+};
+
+inline bool operator < (const MessageBase& lhs, const MessageBase& rhs) {
+    return lhs.when < rhs.when;
+}
+
+// ---------------------------------------------------------------------------
+
+class MessageQueue
+{
+    typedef List< sp<MessageBase> > LIST;
+public:
+
+    // this is a work-around the multichar constant warning. A macro would
+    // work too, but would pollute the namespace.
+    template <int a, int b, int c, int d>
+    struct WHAT {
+        static const uint32_t Value = 
+            (uint32_t(a&0xff)<<24)|(uint32_t(b&0xff)<<16)|
+            (uint32_t(c&0xff)<<8)|uint32_t(d&0xff);
+    };
+    
+    MessageQueue();
+    ~MessageQueue();
+
+    // pre-defined messages
+    enum {
+        INVALIDATE = WHAT<'_','p','d','t'>::Value
+    };
+
+    MessageList::value_type waitMessage(nsecs_t timeout = -1);
+    
+    status_t postMessage(const MessageList::value_type& message, 
+            nsecs_t reltime=0, uint32_t flags = 0);
+        
+    status_t invalidate();
+    
+    void dump(const MessageList::value_type& message);
+
+private:
+    status_t queueMessage(const MessageList::value_type& message,
+            nsecs_t reltime, uint32_t flags);
+    void dumpLocked(const MessageList::value_type& message);
+    
+    Mutex           mLock;
+    Condition       mCondition;
+    MessageList     mMessages;
+    bool            mInvalidate;
+    MessageList::value_type mInvalidateMessage;
+};
+
+// ---------------------------------------------------------------------------
+
+}; // namespace android
+
+#endif /* ANDROID_MESSAGE_QUEUE_H */
diff --git a/libs/surfaceflinger/OrientationAnimation.cpp b/libs/surfaceflinger/OrientationAnimation.cpp
deleted file mode 100644
index 12c0eef..0000000
--- a/libs/surfaceflinger/OrientationAnimation.cpp
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "SurfaceFlinger"
-
-#include <stdint.h>
-#include <sys/types.h>
-#include <limits.h>
-
-#include "LayerOrientationAnim.h"
-#include "OrientationAnimation.h"
-#include "SurfaceFlinger.h"
-#include "VRamHeap.h"
-
-#include "DisplayHardware/DisplayHardware.h"
-
-namespace android {
-
-// ---------------------------------------------------------------------------
-
-OrientationAnimation::OrientationAnimation(const sp<SurfaceFlinger>& flinger)
-    : mFlinger(flinger), mLayerOrientationAnim(NULL), mState(DONE)
-{
-    // allocate a memory-dealer for this the first time
-    mTemporaryDealer = mFlinger->getSurfaceHeapManager()->createHeap(
-            ISurfaceComposer::eHardware);
-}
-
-OrientationAnimation::~OrientationAnimation()
-{
-}
-
-void OrientationAnimation::onOrientationChanged(uint32_t type)
-{
-    if (mState == DONE) {
-        mType = type;
-        if (!(type & ISurfaceComposer::eOrientationAnimationDisable)) {
-            mState = PREPARE;
-        }
-    }
-}
-
-void OrientationAnimation::onAnimationFinished()
-{
-    if (mState != DONE)
-        mState = FINISH;
-}
-
-bool OrientationAnimation::run_impl()
-{
-    bool skip_frame;
-    switch (mState) {
-        default:
-        case DONE:
-            skip_frame = done();
-            break;
-        case PREPARE:
-            skip_frame = prepare();
-            break;
-        case PHASE1:
-            skip_frame = phase1();
-            break;
-        case PHASE2:
-            skip_frame = phase2();
-            break;
-        case FINISH:
-            skip_frame = finished();
-            break;
-    }
-    return skip_frame;
-}
-
-bool OrientationAnimation::done()
-{
-    return done_impl();
-}
-
-bool OrientationAnimation::prepare()
-{
-    mState = PHASE1;
-    
-    const GraphicPlane& plane(mFlinger->graphicPlane(0));
-    const DisplayHardware& hw(plane.displayHardware());
-    const uint32_t w = hw.getWidth();
-    const uint32_t h = hw.getHeight();
-
-    LayerBitmap bitmap;
-    bitmap.init(mTemporaryDealer);
-    bitmap.setBits(w, h, 1, hw.getFormat());
-
-    LayerBitmap bitmapIn;
-    bitmapIn.init(mTemporaryDealer);
-    bitmapIn.setBits(w, h, 1, hw.getFormat());
-
-    copybit_image_t front;
-    bitmap.getBitmapSurface(&front);
-    hw.copyFrontToImage(front);
-
-    LayerOrientationAnimBase* l;
-    
-    l = new LayerOrientationAnim(
-            mFlinger.get(), 0, this, bitmap, bitmapIn);
-
-    l->initStates(w, h, 0);
-    l->setLayer(INT_MAX-1);
-    mFlinger->addLayer(l);
-    mLayerOrientationAnim = l;
-    return true;
-}
-
-bool OrientationAnimation::phase1()
-{
-    if (mFlinger->isFrozen() == false) {
-        // start phase 2
-        mState = PHASE2;
-        mLayerOrientationAnim->onOrientationCompleted();
-        mLayerOrientationAnim->invalidate();
-        return true;
-        
-    }
-    //mLayerOrientationAnim->invalidate();
-    return false;
-}
-
-bool OrientationAnimation::phase2()
-{
-    // do the 2nd phase of the animation
-    mLayerOrientationAnim->invalidate();
-    return false;
-}
-
-bool OrientationAnimation::finished()
-{
-    mState = DONE;
-    mFlinger->removeLayer(mLayerOrientationAnim);
-    mLayerOrientationAnim = NULL;
-    return true;
-}
-
-// ---------------------------------------------------------------------------
-
-}; // namespace android
diff --git a/libs/surfaceflinger/OrientationAnimation.h b/libs/surfaceflinger/OrientationAnimation.h
deleted file mode 100644
index cafa38d..0000000
--- a/libs/surfaceflinger/OrientationAnimation.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_ORIENTATION_ANIMATION_H
-#define ANDROID_ORIENTATION_ANIMATION_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include "SurfaceFlinger.h"
-
-namespace android {
-
-// ---------------------------------------------------------------------------
-
-class SurfaceFlinger;
-class MemoryDealer;
-class LayerOrientationAnim;
-
-class OrientationAnimation
-{
-public:    
-                 OrientationAnimation(const sp<SurfaceFlinger>& flinger);
-        virtual ~OrientationAnimation();
-
-   void onOrientationChanged(uint32_t type);
-   void onAnimationFinished();
-   inline bool run() {
-       if (LIKELY(mState == DONE))
-           return done_impl();
-       return run_impl();
-   }
-
-private:
-    enum {
-        DONE = 0,
-        PREPARE,
-        PHASE1,
-        PHASE2,
-        FINISH
-    };
-
-    bool run_impl();
-    inline bool done_impl() {
-        if (mFlinger->isFrozen()) {
-            // we are not allowed to draw, but pause a bit to make sure
-            // apps don't end up using the whole CPU, if they depend on
-            // surfaceflinger for synchronization.
-            usleep(8333); // 8.3ms ~ 120fps
-            return true;
-        }
-        return false;
-    }
-    
-    bool done();    
-    bool prepare();
-    bool phase1();
-    bool phase2();
-    bool finished();
-
-    sp<SurfaceFlinger> mFlinger;
-    sp<MemoryDealer> mTemporaryDealer;
-    LayerOrientationAnimBase* mLayerOrientationAnim;
-    int mState;
-    uint32_t mType;
-};
-
-// ---------------------------------------------------------------------------
-
-}; // namespace android
-
-#endif // ANDROID_ORIENTATION_ANIMATION_H
diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp
index 97dfecc..9694cf1 100644
--- a/libs/surfaceflinger/SurfaceFlinger.cpp
+++ b/libs/surfaceflinger/SurfaceFlinger.cpp
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "SurfaceFlinger"
-
 #include <stdlib.h>
 #include <stdio.h>
 #include <stdint.h>
@@ -23,6 +21,7 @@
 #include <fcntl.h>
 #include <errno.h>
 #include <math.h>
+#include <limits.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/ioctl.h>
@@ -30,36 +29,29 @@
 #include <cutils/log.h>
 #include <cutils/properties.h>
 
-#include <utils/IPCThreadState.h>
-#include <utils/IServiceManager.h>
-#include <utils/MemoryDealer.h>
-#include <utils/MemoryBase.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/MemoryHeapBase.h>
+
 #include <utils/String8.h>
 #include <utils/String16.h>
 #include <utils/StopWatch.h>
 
+#include <ui/GraphicBufferAllocator.h>
 #include <ui/PixelFormat.h>
 #include <ui/DisplayInfo.h>
-#include <ui/EGLDisplaySurface.h>
 
 #include <pixelflinger/pixelflinger.h>
 #include <GLES/gl.h>
 
 #include "clz.h"
-#include "CPUGauge.h"
 #include "Layer.h"
 #include "LayerBlur.h"
 #include "LayerBuffer.h"
 #include "LayerDim.h"
-#include "LayerBitmap.h"
-#include "LayerOrientationAnim.h"
-#include "OrientationAnimation.h"
 #include "SurfaceFlinger.h"
-#include "VRamHeap.h"
 
 #include "DisplayHardware/DisplayHardware.h"
-#include "GPUHardware/GPUHardware.h"
-
 
 /* ideally AID_GRAPHICS would be in a semi-public header
  * or there would be a way to map a user/group name to its id
@@ -93,30 +85,30 @@
 }
 
 ssize_t SurfaceFlinger::LayerVector::indexOf(
-        LayerBase* key, size_t guess) const
+        const sp<LayerBase>& key, size_t guess) const
 {
     if (guess<size() && lookup.keyAt(guess) == key)
         return guess;
     const ssize_t i = lookup.indexOfKey(key);
     if (i>=0) {
         const size_t idx = lookup.valueAt(i);
-        LOG_ASSERT(layers[idx]==key,
+        LOGE_IF(layers[idx]!=key,
             "LayerVector[%p]: layers[%d]=%p, key=%p",
-            this, int(idx), layers[idx], key);
+            this, int(idx), layers[idx].get(), key.get());
         return idx;
     }
     return i;
 }
 
 ssize_t SurfaceFlinger::LayerVector::add(
-        LayerBase* layer,
-        Vector<LayerBase*>::compar_t cmp)
+        const sp<LayerBase>& layer,
+        Vector< sp<LayerBase> >::compar_t cmp)
 {
     size_t count = layers.size();
     ssize_t l = 0;
     ssize_t h = count-1;
     ssize_t mid;
-    LayerBase* const* a = layers.array();
+    sp<LayerBase> const* a = layers.array();
     while (l <= h) {
         mid = l + (h - l)/2;
         const int c = cmp(a+mid, &layer);
@@ -139,14 +131,14 @@
     return order;
 }
 
-ssize_t SurfaceFlinger::LayerVector::remove(LayerBase* layer)
+ssize_t SurfaceFlinger::LayerVector::remove(const sp<LayerBase>& layer)
 {
     const ssize_t keyIndex = lookup.indexOfKey(layer);
     if (keyIndex >= 0) {
         const size_t index = lookup.valueAt(keyIndex);
-        LOG_ASSERT(layers[index]==layer,
+        LOGE_IF(layers[index]!=layer,
                 "LayerVector[%p]: layers[%u]=%p, layer=%p",
-                this, int(index), layers[index], layer);
+                this, int(index), layers[index].get(), layer.get());
         layers.removeItemsAt(index);
         lookup.removeItemsAt(keyIndex);
         const size_t count = lookup.size();
@@ -161,8 +153,8 @@
 }
 
 ssize_t SurfaceFlinger::LayerVector::reorder(
-        LayerBase* layer,
-        Vector<LayerBase*>::compar_t cmp)
+        const sp<LayerBase>& layer,
+        Vector< sp<LayerBase> >::compar_t cmp)
 {
     // XXX: it's a little lame. but oh well...
     ssize_t err = remove(layer);
@@ -180,19 +172,24 @@
     :   BnSurfaceComposer(), Thread(false),
         mTransactionFlags(0),
         mTransactionCount(0),
+        mResizeTransationPending(false),
+        mLayersRemoved(false),
         mBootTime(systemTime()),
-        mLastScheduledBroadcast(NULL),
+        mHardwareTest("android.permission.HARDWARE_TEST"),
+        mAccessSurfaceFlinger("android.permission.ACCESS_SURFACE_FLINGER"),
+        mDump("android.permission.DUMP"),
         mVisibleRegionsDirty(false),
         mDeferReleaseConsole(false),
         mFreezeDisplay(false),
         mFreezeCount(0),
         mFreezeDisplayTime(0),
         mDebugRegion(0),
-        mDebugCpu(0),
-        mDebugFps(0),
         mDebugBackground(0),
-        mSyncObject(),
-        mDeplayedTransactionPending(0),
+        mDebugInSwapBuffers(0),
+        mLastSwapBufferTime(0),
+        mDebugInTransaction(0),
+        mLastTransactionTime(0),
+        mBootFinished(false),
         mConsoleSignals(0),
         mSecureFrameBuffer(0)
 {
@@ -207,28 +204,16 @@
     char value[PROPERTY_VALUE_MAX];
     property_get("debug.sf.showupdates", value, "0");
     mDebugRegion = atoi(value);
-    property_get("debug.sf.showcpu", value, "0");
-    mDebugCpu = atoi(value);
     property_get("debug.sf.showbackground", value, "0");
     mDebugBackground = atoi(value);
-    property_get("debug.sf.showfps", value, "0");
-    mDebugFps = atoi(value);
 
     LOGI_IF(mDebugRegion,           "showupdates enabled");
-    LOGI_IF(mDebugCpu,              "showcpu enabled");
     LOGI_IF(mDebugBackground,       "showbackground enabled");
-    LOGI_IF(mDebugFps,              "showfps enabled");
 }
 
 SurfaceFlinger::~SurfaceFlinger()
 {
     glDeleteTextures(1, &mWormholeTexName);
-    delete mOrientationAnimation;
-}
-
-copybit_device_t* SurfaceFlinger::getBlitEngine() const
-{
-    return graphicPlane(0).displayHardware().getBlitEngine();
 }
 
 overlay_control_device_t* SurfaceFlinger::getOverlayEngine() const
@@ -236,29 +221,9 @@
     return graphicPlane(0).displayHardware().getOverlayEngine();
 }
 
-sp<IMemory> SurfaceFlinger::getCblk() const
+sp<IMemoryHeap> SurfaceFlinger::getCblk() const
 {
-    return mServerCblkMemory;
-}
-
-status_t SurfaceFlinger::requestGPU(const sp<IGPUCallback>& callback,
-        gpu_info_t* gpu)
-{
-    if (mGPU == 0)
-        return INVALID_OPERATION;
-
-    IPCThreadState* ipc = IPCThreadState::self();
-    const int pid = ipc->getCallingPid();
-    status_t err = mGPU->request(pid, callback, gpu);
-    return err;
-}
-
-status_t SurfaceFlinger::revokeGPU()
-{
-    if (mGPU == 0)
-        return INVALID_OPERATION;
-
-    return mGPU->friendlyRevoke();
+    return mServerHeap;
 }
 
 sp<ISurfaceFlingerClient> SurfaceFlinger::createConnection()
@@ -266,33 +231,34 @@
     Mutex::Autolock _l(mStateLock);
     uint32_t token = mTokens.acquire();
 
-    Client* client = new Client(token, this);
-    if ((client == 0) || (client->ctrlblk == 0)) {
+    sp<Client> client = new Client(token, this);
+    if (client->ctrlblk == 0) {
         mTokens.release(token);
         return 0;
     }
     status_t err = mClientsMap.add(token, client);
     if (err < 0) {
-        delete client;
         mTokens.release(token);
         return 0;
     }
     sp<BClient> bclient =
-        new BClient(this, token, client->controlBlockMemory());
+        new BClient(this, token, client->getControlBlockMemory());
     return bclient;
 }
 
 void SurfaceFlinger::destroyConnection(ClientID cid)
 {
     Mutex::Autolock _l(mStateLock);
-    Client* const client = mClientsMap.valueFor(cid);
-    if (client) {
+    sp<Client> client = mClientsMap.valueFor(cid);
+    if (client != 0) {
         // free all the layers this client owns
-        const Vector<LayerBaseClient*>& layers = client->getLayers();
+        Vector< wp<LayerBaseClient> > layers(client->getLayers());
         const size_t count = layers.size();
         for (size_t i=0 ; i<count ; i++) {
-            LayerBaseClient* const layer = layers[i];
-            removeLayer_l(layer);
+            sp<LayerBaseClient> layer(layers[i].promote());
+            if (layer != 0) {
+                purgatorizeLayer_l(layer);
+            }
         }
 
         // the resources associated with this client will be freed
@@ -328,6 +294,7 @@
     const nsecs_t now = systemTime();
     const nsecs_t duration = now - mBootTime;
     LOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) );  
+    mBootFinished = true;
     property_set("ctl.stop", "bootanim");
 }
 
@@ -339,41 +306,15 @@
     mReadyToRunBarrier.wait();
 }
 
-
 static inline uint16_t pack565(int r, int g, int b) {
     return (r<<11)|(g<<5)|b;
 }
 
-// this is defined in libGLES_CM.so
-extern ISurfaceComposer* GLES_localSurfaceManager;
-
 status_t SurfaceFlinger::readyToRun()
 {
     LOGI(   "SurfaceFlinger's main thread ready to run. "
             "Initializing graphics H/W...");
 
-    // create the shared control-block
-    mServerHeap = new MemoryDealer(4096, MemoryDealer::READ_ONLY);
-    LOGE_IF(mServerHeap==0, "can't create shared memory dealer");
-
-    mServerCblkMemory = mServerHeap->allocate(4096);
-    LOGE_IF(mServerCblkMemory==0, "can't create shared control block");
-
-    mServerCblk = static_cast<surface_flinger_cblk_t *>(mServerCblkMemory->pointer());
-    LOGE_IF(mServerCblk==0, "can't get to shared control block's address");
-    new(mServerCblk) surface_flinger_cblk_t;
-
-    // get a reference to the GPU if we have one
-    mGPU = GPUFactory::getGPU();
-
-    // create the surface Heap manager, which manages the heaps
-    // (be it in RAM or VRAM) where surfaces are allocated
-    // We give 8 MB per client.
-    mSurfaceHeapManager = new SurfaceHeapManager(this, 8 << 20);
-
-    
-    GLES_localSurfaceManager = static_cast<ISurfaceComposer*>(this);
-
     // we only support one display currently
     int dpy = 0;
 
@@ -384,6 +325,16 @@
         plane.setDisplayHardware(hw);
     }
 
+    // create the shared control-block
+    mServerHeap = new MemoryHeapBase(4096,
+            MemoryHeapBase::READ_ONLY, "SurfaceFlinger read-only heap");
+    LOGE_IF(mServerHeap==0, "can't create shared memory dealer");
+    
+    mServerCblk = static_cast<surface_flinger_cblk_t*>(mServerHeap->getBase());
+    LOGE_IF(mServerCblk==0, "can't get to shared control block's address");
+    
+    new(mServerCblk) surface_flinger_cblk_t;
+
     // initialize primary screen
     // (other display should be initialized in the same manner, but
     // asynchronously, as they could come and go. None of this is supported
@@ -450,13 +401,6 @@
      *  We're now ready to accept clients...
      */
 
-    mOrientationAnimation = new OrientationAnimation(this);
-    
-    // start CPU gauge display
-    if (mDebugCpu)
-        mCpuGauge = new CPUGauge(this, ms2ns(500));
-
-    
     // start boot animation
     property_set("ctl.start", "bootanim");
     
@@ -471,45 +415,53 @@
 
 void SurfaceFlinger::waitForEvent()
 {
-    // wait for something to do
-    if (UNLIKELY(isFrozen())) {
-        // wait 5 seconds
-        const nsecs_t freezeDisplayTimeout = ms2ns(5000);
-        const nsecs_t now = systemTime();
-        if (mFreezeDisplayTime == 0) {
-            mFreezeDisplayTime = now;
+    while (true) {
+        nsecs_t timeout = -1;
+        if (UNLIKELY(isFrozen())) {
+            // wait 5 seconds
+            const nsecs_t freezeDisplayTimeout = ms2ns(5000);
+            const nsecs_t now = systemTime();
+            if (mFreezeDisplayTime == 0) {
+                mFreezeDisplayTime = now;
+            }
+            nsecs_t waitTime = freezeDisplayTimeout - (now - mFreezeDisplayTime);
+            timeout = waitTime>0 ? waitTime : 0;
         }
-        nsecs_t waitTime = freezeDisplayTimeout - (now - mFreezeDisplayTime);
-        int err = (waitTime > 0) ? mSyncObject.wait(waitTime) : TIMED_OUT;
-        if (err != NO_ERROR) {
+
+        MessageList::value_type msg = mEventQueue.waitMessage(timeout);
+        if (msg != 0) {
+            mFreezeDisplayTime = 0;
+            switch (msg->what) {
+                case MessageQueue::INVALIDATE:
+                    // invalidate message, just return to the main loop
+                    return;
+            }
+        } else {
+            // we timed out
             if (isFrozen()) {
                 // we timed out and are still frozen
                 LOGW("timeout expired mFreezeDisplay=%d, mFreezeCount=%d",
                         mFreezeDisplay, mFreezeCount);
                 mFreezeCount = 0;
                 mFreezeDisplay = false;
+                return;
             }
         }
-    } else {
-        mFreezeDisplayTime = 0;
-        mSyncObject.wait();
     }
 }
 
 void SurfaceFlinger::signalEvent() {
-    mSyncObject.open();
+    mEventQueue.invalidate();
 }
 
 void SurfaceFlinger::signal() const {
-    mSyncObject.open();
+    // this is the IPC call
+    const_cast<SurfaceFlinger*>(this)->signalEvent();
 }
 
 void SurfaceFlinger::signalDelayedEvent(nsecs_t delay)
 {
-    if (android_atomic_or(1, &mDeplayedTransactionPending) == 0) {
-        sp<DelayedTransaction> delayedEvent(new DelayedTransaction(this, delay));
-        delayedEvent->run("DelayedeEvent", PRIORITY_URGENT_DISPLAY);
-    }
+    mEventQueue.postMessage( new MessageBase(MessageQueue::INVALIDATE), delay);
 }
 
 // ----------------------------------------------------------------------------
@@ -540,24 +492,20 @@
     handlePageFlip();
 
     const DisplayHardware& hw(graphicPlane(0).displayHardware());
-    if (LIKELY(hw.canDraw())) {
+    if (LIKELY(hw.canDraw() && !isFrozen())) {
         // repaint the framebuffer (if needed)
         handleRepaint();
 
+        // inform the h/w that we're done compositing
+        hw.compositionComplete();
+
         // release the clients before we flip ('cause flip might block)
         unlockClients();
-        executeScheduledBroadcasts();
-
-        // sample the cpu gauge
-        if (UNLIKELY(mDebugCpu)) {
-            handleDebugCpu();
-        }
 
         postFramebuffer();
     } else {
         // pretend we did the post
         unlockClients();
-        executeScheduledBroadcasts();
         usleep(16667); // 60 fps period
     }
     return true;
@@ -565,28 +513,14 @@
 
 void SurfaceFlinger::postFramebuffer()
 {
-    const bool skip = mOrientationAnimation->run();
-    if (UNLIKELY(skip)) {
-        return;
-    }
-
     if (!mInvalidRegion.isEmpty()) {
         const DisplayHardware& hw(graphicPlane(0).displayHardware());
-
-        if (UNLIKELY(mDebugFps)) {
-            debugShowFPS();
-        }
-
+        const nsecs_t now = systemTime();
+        mDebugInSwapBuffers = now;
         hw.flip(mInvalidRegion);
-
+        mLastSwapBufferTime = systemTime() - now;
+        mDebugInSwapBuffers = 0;
         mInvalidRegion.clear();
-
-        if (Layer::deletedTextures.size()) {
-            glDeleteTextures(
-                    Layer::deletedTextures.size(),
-                    Layer::deletedTextures.array());
-            Layer::deletedTextures.clear();
-        }
     }
 }
 
@@ -601,15 +535,13 @@
     }
 
     if (mDeferReleaseConsole && hw.canDraw()) {
-        // We got the release signal before the aquire signal
+        // We got the release signal before the acquire signal
         mDeferReleaseConsole = false;
-        revokeGPU();
         hw.releaseScreen();
     }
 
     if (what & eConsoleReleased) {
         if (hw.canDraw()) {
-            revokeGPU();
             hw.releaseScreen();
         } else {
             mDeferReleaseConsole = true;
@@ -621,9 +553,31 @@
 
 void SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
 {
-    Mutex::Autolock _l(mStateLock);
+    Vector< sp<LayerBase> > ditchedLayers;
 
-    const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
+    { // scope for the lock
+        Mutex::Autolock _l(mStateLock);
+        const nsecs_t now = systemTime();
+        mDebugInTransaction = now;
+        handleTransactionLocked(transactionFlags, ditchedLayers);
+        mLastTransactionTime = systemTime() - now;
+        mDebugInTransaction = 0;
+    }
+
+    // do this without lock held
+    const size_t count = ditchedLayers.size();
+    for (size_t i=0 ; i<count ; i++) {
+        if (ditchedLayers[i] != 0) {
+            //LOGD("ditching layer %p", ditchedLayers[i].get());
+            ditchedLayers[i]->ditch();
+        }
+    }
+}
+
+void SurfaceFlinger::handleTransactionLocked(
+        uint32_t transactionFlags, Vector< sp<LayerBase> >& ditchedLayers)
+{
+    const LayerVector& currentLayers(mCurrentState.layersSortedByZ);
     const size_t count = currentLayers.size();
 
     /*
@@ -634,19 +588,13 @@
     const bool layersNeedTransaction = transactionFlags & eTraversalNeeded;
     if (layersNeedTransaction) {
         for (size_t i=0 ; i<count ; i++) {
-            LayerBase* const layer = currentLayers[i];
+            const sp<LayerBase>& layer = currentLayers[i];
             uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded);
             if (!trFlags) continue;
 
             const uint32_t flags = layer->doTransaction(0);
             if (flags & Layer::eVisibleRegion)
                 mVisibleRegionsDirty = true;
-
-            if (flags & Layer::eRestartTransaction) {
-                // restart the transaction, but back-off a little
-                layer->setTransactionFlags(eTransactionNeeded);
-                setTransactionFlags(eTraversalNeeded, ms2ns(8));
-            }
         }
     }
 
@@ -681,7 +629,6 @@
             mVisibleRegionsDirty = true;
             mDirtyRegion.set(hw.bounds());
             mFreezeDisplayTime = 0;
-            mOrientationAnimation->onOrientationChanged(type);
         }
 
         if (mCurrentState.freezeDisplay != mDrawingState.freezeDisplay) {
@@ -689,24 +636,28 @@
             mFreezeDisplay = mCurrentState.freezeDisplay;
         }
 
-        // some layers might have been removed, so
-        // we need to update the regions they're exposing.
-        const SortedVector<LayerBase*>& removedLayers(mRemovedLayers);
-        size_t c = removedLayers.size();
-        if (c) {
-            mVisibleRegionsDirty = true;
-            while (c--) {
-                mDirtyRegionRemovedLayer.orSelf(
-                        removedLayers[c]->visibleRegionScreen);
-            }
-        }
-
-        const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
         if (currentLayers.size() > mDrawingState.layersSortedByZ.size()) {
             // layers have been added
             mVisibleRegionsDirty = true;
         }
 
+        // some layers might have been removed, so
+        // we need to update the regions they're exposing.
+        if (mLayersRemoved) {
+            mLayersRemoved = false;
+            mVisibleRegionsDirty = true;
+            const LayerVector& previousLayers(mDrawingState.layersSortedByZ);
+            const size_t count = previousLayers.size();
+            for (size_t i=0 ; i<count ; i++) {
+                const sp<LayerBase>& layer(previousLayers[i]);
+                if (currentLayers.indexOf( layer ) < 0) {
+                    // this layer is not visible anymore
+                    ditchedLayers.add(layer);
+                    mDirtyRegionRemovedLayer.orSelf(layer->visibleRegionScreen);
+                }
+            }
+        }
+
         // get rid of all resources we don't need anymore
         // (layers and clients)
         free_resources_l();
@@ -734,7 +685,7 @@
 
     size_t i = currentLayers.size();
     while (i--) {
-        LayerBase* const layer = currentLayers[i];
+        const sp<LayerBase>& layer = currentLayers[i];
         layer->validateVisibility(planeTransform);
 
         // start with the whole surface at its current location
@@ -785,7 +736,7 @@
         // accumulate to the screen dirty region
         dirtyRegion.orSelf(dirty);
 
-        // updade aboveOpaqueLayers/aboveCoveredLayers for next (lower) layer
+        // Update aboveOpaqueLayers/aboveCoveredLayers for next (lower) layer
         aboveOpaqueLayers.orSelf(opaqueRegion);
         aboveCoveredLayers.orSelf(visibleRegion);
         
@@ -811,7 +762,8 @@
 void SurfaceFlinger::commitTransaction()
 {
     mDrawingState = mCurrentState;
-    mTransactionCV.signal();
+    mResizeTransationPending = false;
+    mTransactionCV.broadcast();
 }
 
 void SurfaceFlinger::handlePageFlip()
@@ -837,9 +789,9 @@
 {
     bool recomputeVisibleRegions = false;
     size_t count = currentLayers.size();
-    LayerBase* const* layers = currentLayers.array();
+    sp<LayerBase> const* layers = currentLayers.array();
     for (size_t i=0 ; i<count ; i++) {
-        LayerBase* const layer = layers[i];
+        const sp<LayerBase>& layer = layers[i];
         layer->lockPageFlip(recomputeVisibleRegions);
     }
     return recomputeVisibleRegions;
@@ -850,37 +802,58 @@
     const GraphicPlane& plane(graphicPlane(0));
     const Transform& planeTransform(plane.transform());
     size_t count = currentLayers.size();
-    LayerBase* const* layers = currentLayers.array();
+    sp<LayerBase> const* layers = currentLayers.array();
     for (size_t i=0 ; i<count ; i++) {
-        LayerBase* const layer = layers[i];
+        const sp<LayerBase>& layer = layers[i];
         layer->unlockPageFlip(planeTransform, mDirtyRegion);
     }
 }
 
+
 void SurfaceFlinger::handleRepaint()
 {
-    // set the frame buffer
-    const DisplayHardware& hw(graphicPlane(0).displayHardware());
-    glMatrixMode(GL_MODELVIEW);
-    glLoadIdentity();
+    // compute the invalid region
+    mInvalidRegion.orSelf(mDirtyRegion);
+    if (mInvalidRegion.isEmpty()) {
+        // nothing to do
+        return;
+    }
 
     if (UNLIKELY(mDebugRegion)) {
         debugFlashRegions();
     }
 
-    // compute the invalid region
-    mInvalidRegion.orSelf(mDirtyRegion);
+    // set the frame buffer
+    const DisplayHardware& hw(graphicPlane(0).displayHardware());
+    glMatrixMode(GL_MODELVIEW);
+    glLoadIdentity();
 
     uint32_t flags = hw.getFlags();
-    if (flags & DisplayHardware::BUFFER_PRESERVED) {
-        // here we assume DisplayHardware::flip()'s  implementation
-        // performs the copy-back optimization.
-    } else {
-        if (flags & DisplayHardware::UPDATE_ON_DEMAND) {
-            // we need to fully redraw the part that will be updated
+    if ((flags & DisplayHardware::SWAP_RECTANGLE) || 
+        (flags & DisplayHardware::BUFFER_PRESERVED)) 
+    {
+        // we can redraw only what's dirty, but since SWAP_RECTANGLE only
+        // takes a rectangle, we must make sure to update that whole
+        // rectangle in that case
+        if (flags & DisplayHardware::SWAP_RECTANGLE) {
+            // FIXME: we really should be able to pass a region to
+            // SWAP_RECTANGLE so that we don't have to redraw all this.
             mDirtyRegion.set(mInvalidRegion.bounds());
         } else {
-            // we need to redraw everything
+            // in the BUFFER_PRESERVED case, obviously, we can update only
+            // what's needed and nothing more.
+            // NOTE: this is NOT a common case, as preserving the backbuffer
+            // is costly and usually involves copying the whole update back.
+        }
+    } else {
+        if (flags & DisplayHardware::PARTIAL_UPDATES) {
+            // We need to redraw the rectangle that will be updated
+            // (pushed to the framebuffer).
+            // This is needed because PARTIAL_UPDATES only takes one
+            // rectangle instead of a region (see DisplayHardware::flip())
+            mDirtyRegion.set(mInvalidRegion.bounds());
+        } else {
+            // we need to redraw everything (the whole screen)
             mDirtyRegion.set(hw.bounds());
             mInvalidRegion = mDirtyRegion;
         }
@@ -903,9 +876,9 @@
     const SurfaceFlinger& flinger(*this);
     const LayerVector& drawingLayers(mDrawingState.layersSortedByZ);
     const size_t count = drawingLayers.size();
-    LayerBase const* const* const layers = drawingLayers.array();
+    sp<LayerBase> const* const layers = drawingLayers.array();
     for (size_t i=0 ; i<count ; ++i) {
-        LayerBase const * const layer = layers[i];
+        const sp<LayerBase>& layer = layers[i];
         const Region& visibleRegion(layer->visibleRegionScreen);
         if (!visibleRegion.isEmpty())  {
             const Region clip(dirty.intersect(visibleRegion));
@@ -920,67 +893,42 @@
 {
     const LayerVector& drawingLayers(mDrawingState.layersSortedByZ);
     const size_t count = drawingLayers.size();
-    LayerBase* const* const layers = drawingLayers.array();
+    sp<LayerBase> const* const layers = drawingLayers.array();
     for (size_t i=0 ; i<count ; ++i) {
-        LayerBase* const layer = layers[i];
+        const sp<LayerBase>& layer = layers[i];
         layer->finishPageFlip();
     }
 }
 
-void SurfaceFlinger::scheduleBroadcast(Client* client)
-{
-    if (mLastScheduledBroadcast != client) {
-        mLastScheduledBroadcast = client;
-        mScheduledBroadcasts.add(client);
-    }
-}
-
-void SurfaceFlinger::executeScheduledBroadcasts()
-{
-    SortedVector<Client*>& list = mScheduledBroadcasts;
-    size_t count = list.size();
-    while (count--) {
-        per_client_cblk_t* const cblk = list[count]->ctrlblk;
-        if (cblk->lock.tryLock() == NO_ERROR) {
-            cblk->cv.broadcast();
-            list.removeAt(count);
-            cblk->lock.unlock();
-        } else {
-            // schedule another round
-            LOGW("executeScheduledBroadcasts() skipped, "
-                "contention on the client. We'll try again later...");
-            signalDelayedEvent(ms2ns(4));
-        }
-    }
-    mLastScheduledBroadcast = 0;
-}
-
-void SurfaceFlinger::handleDebugCpu()
-{
-    Mutex::Autolock _l(mDebugLock);
-    if (mCpuGauge != 0)
-        mCpuGauge->sample();
-}
-
 void SurfaceFlinger::debugFlashRegions()
 {
-    if (UNLIKELY(!mDirtyRegion.isRect())) {
-        // TODO: do this only if we don't have preserving
-        // swapBuffer. If we don't have update-on-demand,
-        // redraw everything.
-        composeSurfaces(Region(mDirtyRegion.bounds()));
-    }
+     const DisplayHardware& hw(graphicPlane(0).displayHardware());
+     const uint32_t flags = hw.getFlags();
 
+     if (!((flags & DisplayHardware::SWAP_RECTANGLE) ||
+             (flags & DisplayHardware::BUFFER_PRESERVED))) {
+         const Region repaint((flags & DisplayHardware::PARTIAL_UPDATES) ?
+                 mDirtyRegion.bounds() : hw.bounds());
+         composeSurfaces(repaint);
+     }
+    
     glDisable(GL_TEXTURE_2D);
     glDisable(GL_BLEND);
     glDisable(GL_DITHER);
     glDisable(GL_SCISSOR_TEST);
 
-    glColor4x(0x10000, 0, 0x10000, 0x10000);
+    static int toggle = 0;
+    toggle = 1 - toggle;
+    if (toggle) {
+        glColor4x(0x10000, 0, 0x10000, 0x10000);
+    } else {
+        glColor4x(0x10000, 0x10000, 0, 0x10000);
+    }
 
-    Rect r;
-    Region::iterator iterator(mDirtyRegion);
-    while (iterator.iterate(&r)) {
+    Region::const_iterator it = mDirtyRegion.begin();
+    Region::const_iterator const end = mDirtyRegion.end();
+    while (it != end) {
+        const Rect& r = *it++;
         GLfloat vertices[][2] = {
                 { r.left,  r.top },
                 { r.left,  r.bottom },
@@ -990,10 +938,12 @@
         glVertexPointer(2, GL_FLOAT, 0, vertices);
         glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
     }
-
-    const DisplayHardware& hw(graphicPlane(0).displayHardware());
-    hw.flip(mDirtyRegion.merge(mInvalidRegion));
-    mInvalidRegion.clear();
+    
+    if (mInvalidRegion.isEmpty()) {
+        mDirtyRegion.dump("mDirtyRegion");
+        mInvalidRegion.dump("mInvalidRegion");
+    }
+    hw.flip(mInvalidRegion);
 
     if (mDebugRegion > 1)
        usleep(mDebugRegion * 1000);
@@ -1017,9 +967,10 @@
 
     if (LIKELY(!mDebugBackground)) {
         glClearColorx(0,0,0,0);
-        Rect r;
-        Region::iterator iterator(region);
-        while (iterator.iterate(&r)) {
+        Region::const_iterator it = region.begin();
+        Region::const_iterator const end = region.end();
+        while (it != end) {
+            const Rect& r = *it++;
             const GLint sy = height - (r.top + r.height());
             glScissor(r.left, sy, r.width(), r.height());
             glClear(GL_COLOR_BUFFER_BIT);
@@ -1037,9 +988,10 @@
         glMatrixMode(GL_TEXTURE);
         glLoadIdentity();
         glScalef(width*(1.0f/32.0f), height*(1.0f/32.0f), 1);
-        Rect r;
-        Region::iterator iterator(region);
-        while (iterator.iterate(&r)) {
+        Region::const_iterator it = region.begin();
+        Region::const_iterator const end = region.end();
+        while (it != end) {
+            const Rect& r = *it++;
             const GLint sy = height - (r.top + r.height());
             glScissor(r.left, sy, r.width(), r.height());
             glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
@@ -1065,7 +1017,7 @@
     // XXX: mFPS has the value we want
  }
 
-status_t SurfaceFlinger::addLayer(LayerBase* layer)
+status_t SurfaceFlinger::addLayer(const sp<LayerBase>& layer)
 {
     Mutex::Autolock _l(mStateLock);
     addLayer_l(layer);
@@ -1073,91 +1025,77 @@
     return NO_ERROR;
 }
 
-status_t SurfaceFlinger::removeLayer(LayerBase* layer)
+status_t SurfaceFlinger::removeLayer(const sp<LayerBase>& layer)
 {
     Mutex::Autolock _l(mStateLock);
-    removeLayer_l(layer);
-    setTransactionFlags(eTransactionNeeded);
-    return NO_ERROR;
+    status_t err = purgatorizeLayer_l(layer);
+    if (err == NO_ERROR)
+        setTransactionFlags(eTransactionNeeded);
+    return err;
 }
 
-status_t SurfaceFlinger::invalidateLayerVisibility(LayerBase* layer)
+status_t SurfaceFlinger::invalidateLayerVisibility(const sp<LayerBase>& layer)
 {
     layer->forceVisibilityTransaction();
     setTransactionFlags(eTraversalNeeded);
     return NO_ERROR;
 }
 
-status_t SurfaceFlinger::addLayer_l(LayerBase* layer)
+status_t SurfaceFlinger::addLayer_l(const sp<LayerBase>& layer)
 {
+    if (layer == 0)
+        return BAD_VALUE;
     ssize_t i = mCurrentState.layersSortedByZ.add(
                 layer, &LayerBase::compareCurrentStateZ);
-    LayerBaseClient* lbc = LayerBase::dynamicCast<LayerBaseClient*>(layer);
-    if (lbc) {
+    sp<LayerBaseClient> lbc = LayerBase::dynamicCast< LayerBaseClient* >(layer.get());
+    if (lbc != 0) {
         mLayerMap.add(lbc->serverIndex(), lbc);
     }
-    mRemovedLayers.remove(layer);
     return NO_ERROR;
 }
 
-status_t SurfaceFlinger::removeLayer_l(LayerBase* layerBase)
+status_t SurfaceFlinger::removeLayer_l(const sp<LayerBase>& layerBase)
 {
     ssize_t index = mCurrentState.layersSortedByZ.remove(layerBase);
     if (index >= 0) {
-        mRemovedLayers.add(layerBase);
-        LayerBaseClient* layer = LayerBase::dynamicCast<LayerBaseClient*>(layerBase);
-        if (layer) {
+        mLayersRemoved = true;
+        sp<LayerBaseClient> layer =
+            LayerBase::dynamicCast< LayerBaseClient* >(layerBase.get());
+        if (layer != 0) {
             mLayerMap.removeItem(layer->serverIndex());
         }
         return NO_ERROR;
     }
+    return status_t(index);
+}
+
+status_t SurfaceFlinger::purgatorizeLayer_l(const sp<LayerBase>& layerBase)
+{
+    // remove the layer from the main list (through a transaction).
+    ssize_t err = removeLayer_l(layerBase);
+
+    layerBase->onRemoved();
+
     // it's possible that we don't find a layer, because it might
     // have been destroyed already -- this is not technically an error
-    // from the user because there is a race between destroySurface,
-    // destroyclient and destroySurface-from-a-transaction.
-    return (index == NAME_NOT_FOUND) ? status_t(NO_ERROR) : index;
+    // from the user because there is a race between BClient::destroySurface(),
+    // ~BClient() and ~ISurface().
+    return (err == NAME_NOT_FOUND) ? status_t(NO_ERROR) : err;
 }
 
+
 void SurfaceFlinger::free_resources_l()
 {
-    // Destroy layers that were removed
-    destroy_all_removed_layers_l();
-
     // free resources associated with disconnected clients
-    SortedVector<Client*>& scheduledBroadcasts(mScheduledBroadcasts);
-    Vector<Client*>& disconnectedClients(mDisconnectedClients);
+    Vector< sp<Client> >& disconnectedClients(mDisconnectedClients);
     const size_t count = disconnectedClients.size();
     for (size_t i=0 ; i<count ; i++) {
-        Client* client = disconnectedClients[i];
-        // if this client is the scheduled broadcast list,
-        // remove it from there (and we don't need to signal it
-        // since it is dead).
-        int32_t index = scheduledBroadcasts.indexOf(client);
-        if (index >= 0) {
-            scheduledBroadcasts.removeItemsAt(index);
-        }
+        sp<Client> client = disconnectedClients[i];
         mTokens.release(client->cid);
-        delete client;
     }
     disconnectedClients.clear();
 }
 
-void SurfaceFlinger::destroy_all_removed_layers_l()
-{
-    size_t c = mRemovedLayers.size();
-    while (c--) {
-        LayerBase* const removed_layer = mRemovedLayers[c];
-
-        LOGE_IF(mCurrentState.layersSortedByZ.indexOf(removed_layer) >= 0,
-            "layer %p removed but still in the current state list",
-            removed_layer);
-
-        delete removed_layer;
-    }
-    mRemovedLayers.clear();
-}
-
-
 uint32_t SurfaceFlinger::getTransactionFlags(uint32_t flags)
 {
     return android_atomic_and(~flags, &mTransactionFlags) & flags;
@@ -1185,6 +1123,20 @@
 {
     if (android_atomic_dec(&mTransactionCount) == 1) {
         signalEvent();
+
+        // if there is a transaction with a resize, wait for it to 
+        // take effect before returning.
+        Mutex::Autolock _l(mStateLock);
+        while (mResizeTransationPending) {
+            status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
+            if (CC_UNLIKELY(err != NO_ERROR)) {
+                // just in case something goes wrong in SF, return to the
+                // called after a few seconds.
+                LOGW_IF(err == TIMED_OUT, "closeGlobalTransaction timed out!");
+                mResizeTransationPending = false;
+                break;
+            }
+        }
     }
 }
 
@@ -1198,7 +1150,7 @@
     setTransactionFlags(eTransactionNeeded);
 
     // flags is intended to communicate some sort of animation behavior
-    // (for instance fadding)
+    // (for instance fading)
     return NO_ERROR;
 }
 
@@ -1212,7 +1164,7 @@
     setTransactionFlags(eTransactionNeeded);
 
     // flags is intended to communicate some sort of animation behavior
-    // (for instance fadding)
+    // (for instance fading)
     return NO_ERROR;
 }
 
@@ -1241,7 +1193,7 @@
         DisplayID d, uint32_t w, uint32_t h, PixelFormat format,
         uint32_t flags)
 {
-    LayerBaseClient* layer = 0;
+    sp<LayerBaseClient> layer;
     sp<LayerBaseClient::Surface> surfaceHandle;
 
     if (int32_t(w|h) < 0) {
@@ -1251,14 +1203,14 @@
     }
     
     Mutex::Autolock _l(mStateLock);
-    Client* const c = mClientsMap.valueFor(clientId);
-    if (UNLIKELY(!c)) {
+    sp<Client> client = mClientsMap.valueFor(clientId);
+    if (UNLIKELY(client == 0)) {
         LOGE("createSurface() failed, client not found (id=%d)", clientId);
         return surfaceHandle;
     }
 
     //LOGD("createSurface for pid %d (%d x %d)", pid, w, h);
-    int32_t id = c->generateId(pid);
+    int32_t id = client->generateId(pid);
     if (uint32_t(id) >= NUM_LAYERS_MAX) {
         LOGE("createSurface() failed, generateId = %d", id);
         return surfaceHandle;
@@ -1267,32 +1219,40 @@
     switch (flags & eFXSurfaceMask) {
         case eFXSurfaceNormal:
             if (UNLIKELY(flags & ePushBuffers)) {
-                layer = createPushBuffersSurfaceLocked(c, d, id, w, h, flags);
+                layer = createPushBuffersSurfaceLocked(client, d, id,
+                        w, h, flags);
             } else {
-                layer = createNormalSurfaceLocked(c, d, id, w, h, format, flags);
+                layer = createNormalSurfaceLocked(client, d, id,
+                        w, h, flags, format);
             }
             break;
         case eFXSurfaceBlur:
-            layer = createBlurSurfaceLocked(c, d, id, w, h, flags);
+            layer = createBlurSurfaceLocked(client, d, id, w, h, flags);
             break;
         case eFXSurfaceDim:
-            layer = createDimSurfaceLocked(c, d, id, w, h, flags);
+            layer = createDimSurfaceLocked(client, d, id, w, h, flags);
             break;
     }
 
-    if (layer) {
+    if (layer != 0) {
         setTransactionFlags(eTransactionNeeded);
         surfaceHandle = layer->getSurface();
-        if (surfaceHandle != 0)
-            surfaceHandle->getSurfaceData(params);
+        if (surfaceHandle != 0) { 
+            params->token = surfaceHandle->getToken();
+            params->identity = surfaceHandle->getIdentity();
+            params->width = w;
+            params->height = h;
+            params->format = format;
+        }
     }
 
     return surfaceHandle;
 }
 
-LayerBaseClient* SurfaceFlinger::createNormalSurfaceLocked(
-        Client* client, DisplayID display,
-        int32_t id, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags)
+sp<LayerBaseClient> SurfaceFlinger::createNormalSurfaceLocked(
+        const sp<Client>& client, DisplayID display,
+        int32_t id, uint32_t w, uint32_t h, uint32_t flags,
+        PixelFormat& format)
 {
     // initialize the surfaces
     switch (format) { // TODO: take h/w into account
@@ -1305,57 +1265,102 @@
         break;
     }
 
-    Layer* layer = new Layer(this, display, client, id);
-    status_t err = layer->setBuffers(client, w, h, format, flags);
+    sp<Layer> layer = new Layer(this, display, client, id);
+    status_t err = layer->setBuffers(w, h, format, flags);
     if (LIKELY(err == NO_ERROR)) {
         layer->initStates(w, h, flags);
         addLayer_l(layer);
     } else {
         LOGE("createNormalSurfaceLocked() failed (%s)", strerror(-err));
-        delete layer;
-        return 0;
+        layer.clear();
     }
     return layer;
 }
 
-LayerBaseClient* SurfaceFlinger::createBlurSurfaceLocked(
-        Client* client, DisplayID display,
+sp<LayerBaseClient> SurfaceFlinger::createBlurSurfaceLocked(
+        const sp<Client>& client, DisplayID display,
         int32_t id, uint32_t w, uint32_t h, uint32_t flags)
 {
-    LayerBlur* layer = new LayerBlur(this, display, client, id);
+    sp<LayerBlur> layer = new LayerBlur(this, display, client, id);
     layer->initStates(w, h, flags);
     addLayer_l(layer);
     return layer;
 }
 
-LayerBaseClient* SurfaceFlinger::createDimSurfaceLocked(
-        Client* client, DisplayID display,
+sp<LayerBaseClient> SurfaceFlinger::createDimSurfaceLocked(
+        const sp<Client>& client, DisplayID display,
         int32_t id, uint32_t w, uint32_t h, uint32_t flags)
 {
-    LayerDim* layer = new LayerDim(this, display, client, id);
+    sp<LayerDim> layer = new LayerDim(this, display, client, id);
     layer->initStates(w, h, flags);
     addLayer_l(layer);
     return layer;
 }
 
-LayerBaseClient* SurfaceFlinger::createPushBuffersSurfaceLocked(
-        Client* client, DisplayID display,
+sp<LayerBaseClient> SurfaceFlinger::createPushBuffersSurfaceLocked(
+        const sp<Client>& client, DisplayID display,
         int32_t id, uint32_t w, uint32_t h, uint32_t flags)
 {
-    LayerBuffer* layer = new LayerBuffer(this, display, client, id);
+    sp<LayerBuffer> layer = new LayerBuffer(this, display, client, id);
     layer->initStates(w, h, flags);
     addLayer_l(layer);
     return layer;
 }
 
-status_t SurfaceFlinger::destroySurface(SurfaceID index)
+status_t SurfaceFlinger::removeSurface(SurfaceID index)
 {
+    /*
+     * called by the window manager, when a surface should be marked for
+     * destruction.
+     * 
+     * The surface is removed from the current and drawing lists, but placed
+     * in the purgatory queue, so it's not destroyed right-away (we need
+     * to wait for all client's references to go away first).
+     */
+
+    status_t err = NAME_NOT_FOUND;
     Mutex::Autolock _l(mStateLock);
-    LayerBaseClient* const layer = getLayerUser_l(index);
-    status_t err = removeLayer_l(layer);
-    if (err < 0)
-        return err;
-    setTransactionFlags(eTransactionNeeded);
+    sp<LayerBaseClient> layer = getLayerUser_l(index);
+    if (layer != 0) {
+        err = purgatorizeLayer_l(layer);
+        if (err == NO_ERROR) {
+            setTransactionFlags(eTransactionNeeded);
+        }
+    }
+    return err;
+}
+
+status_t SurfaceFlinger::destroySurface(const sp<LayerBaseClient>& layer)
+{
+    // called by ~ISurface() when all references are gone
+    
+    class MessageDestroySurface : public MessageBase {
+        SurfaceFlinger* flinger;
+        sp<LayerBaseClient> layer;
+    public:
+        MessageDestroySurface(
+                SurfaceFlinger* flinger, const sp<LayerBaseClient>& layer)
+            : flinger(flinger), layer(layer) { }
+        virtual bool handler() {
+            sp<LayerBaseClient> l(layer);
+            layer.clear(); // clear it outside of the lock;
+            Mutex::Autolock _l(flinger->mStateLock);
+            /*
+             * remove the layer from the current list -- chances are that it's 
+             * not in the list anyway, because it should have been removed 
+             * already upon request of the client (eg: window manager). 
+             * However, a buggy client could have not done that.
+             * Since we know we don't have any more clients, we don't need
+             * to use the purgatory.
+             */
+            status_t err = flinger->removeLayer_l(l);
+            LOGE_IF(err<0 && err != NAME_NOT_FOUND,
+                    "error removing layer=%p (%s)", l.get(), strerror(-err));
+            return true;
+        }
+    };
+
+    mEventQueue.postMessage( new MessageDestroySurface(this, layer) );
     return NO_ERROR;
 }
 
@@ -1369,18 +1374,9 @@
     cid <<= 16;
     for (int i=0 ; i<count ; i++) {
         const layer_state_t& s = states[i];
-        LayerBaseClient* layer = getLayerUser_l(s.surface | cid);
-        if (layer) {
+        sp<LayerBaseClient> layer(getLayerUser_l(s.surface | cid));
+        if (layer != 0) {
             const uint32_t what = s.what;
-            // check if it has been destroyed first
-            if (what & eDestroyed) {
-                if (removeLayer_l(layer) == NO_ERROR) {
-                    flags |= eTransactionNeeded;
-                    // we skip everything else... well, no, not really
-                    // we skip ONLY that transaction.
-                    continue;
-                }
-            }
             if (what & ePositionChanged) {
                 if (layer->setPosition(s.x, s.y))
                     flags |= eTraversalNeeded;
@@ -1395,8 +1391,10 @@
                 }
             }
             if (what & eSizeChanged) {
-                if (layer->setSize(s.w, s.h))
+                if (layer->setSize(s.w, s.h)) {
                     flags |= eTraversalNeeded;
+                    mResizeTransationPending = true;
+                }
             }
             if (what & eAlphaChanged) {
                 if (layer->setAlpha(uint8_t(255.0f*s.alpha+0.5f)))
@@ -1422,9 +1420,10 @@
     return NO_ERROR;
 }
 
-LayerBaseClient* SurfaceFlinger::getLayerUser_l(SurfaceID s) const
+sp<LayerBaseClient> SurfaceFlinger::getLayerUser_l(SurfaceID s) const
 {
-    return mLayerMap.valueFor(s);
+    sp<LayerBaseClient> layer = mLayerMap.valueFor(s);
+    return layer;
 }
 
 void SurfaceFlinger::screenReleased(int dpy)
@@ -1446,20 +1445,40 @@
     const size_t SIZE = 1024;
     char buffer[SIZE];
     String8 result;
-    if (checkCallingPermission(
-            String16("android.permission.DUMP")) == false)
-    { // not allowed
+    if (!mDump.checkCalling()) {
         snprintf(buffer, SIZE, "Permission Denial: "
                 "can't dump SurfaceFlinger from pid=%d, uid=%d\n",
                 IPCThreadState::self()->getCallingPid(),
                 IPCThreadState::self()->getCallingUid());
         result.append(buffer);
     } else {
-        Mutex::Autolock _l(mStateLock);
+
+        // figure out if we're stuck somewhere
+        const nsecs_t now = systemTime();
+        const nsecs_t inSwapBuffers(mDebugInSwapBuffers);
+        const nsecs_t inTransaction(mDebugInTransaction);
+        nsecs_t inSwapBuffersDuration = (inSwapBuffers) ? now-inSwapBuffers : 0;
+        nsecs_t inTransactionDuration = (inTransaction) ? now-inTransaction : 0;
+
+        // Try to get the main lock, but don't insist if we can't
+        // (this would indicate SF is stuck, but we want to be able to
+        // print something in dumpsys).
+        int retry = 3;
+        while (mStateLock.tryLock()<0 && --retry>=0) {
+            usleep(1000000);
+        }
+        const bool locked(retry >= 0);
+        if (!locked) {
+            snprintf(buffer, SIZE, 
+                    "SurfaceFlinger appears to be unresponsive, "
+                    "dumping anyways (no locks held)\n");
+            result.append(buffer);
+        }
+
         size_t s = mClientsMap.size();
         char name[64];
         for (size_t i=0 ; i<s ; i++) {
-            Client* client = mClientsMap.valueAt(i);
+            sp<Client> client = mClientsMap.valueAt(i);
             sprintf(name, "  Client (id=0x%08x)", client->cid);
             client->dump(name);
         }
@@ -1467,51 +1486,66 @@
         const size_t count = currentLayers.size();
         for (size_t i=0 ; i<count ; i++) {
             /*** LayerBase ***/
-            LayerBase const * const layer = currentLayers[i];
+            const sp<LayerBase>& layer = currentLayers[i];
             const Layer::State& s = layer->drawingState();
             snprintf(buffer, SIZE,
                     "+ %s %p\n"
                     "      "
                     "z=%9d, pos=(%4d,%4d), size=(%4d,%4d), "
-                    "needsBlending=%1d, invalidate=%1d, "
+                    "needsBlending=%1d, needsDithering=%1d, invalidate=%1d, "
                     "alpha=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n",
-                    layer->getTypeID(), layer,
+                    layer->getTypeID(), layer.get(),
                     s.z, layer->tx(), layer->ty(), s.w, s.h,
-                    layer->needsBlending(), layer->contentDirty,
+                    layer->needsBlending(), layer->needsDithering(),
+                    layer->contentDirty,
                     s.alpha, s.flags,
                     s.transform[0], s.transform[1],
                     s.transform[2], s.transform[3]);
             result.append(buffer);
             buffer[0] = 0;
             /*** LayerBaseClient ***/
-            LayerBaseClient* const lbc =
-                LayerBase::dynamicCast<LayerBaseClient*>((LayerBase*)layer);
-            if (lbc) {
+            sp<LayerBaseClient> lbc =
+                LayerBase::dynamicCast< LayerBaseClient* >(layer.get());
+            if (lbc != 0) {
+                sp<Client> client(lbc->client.promote());
                 snprintf(buffer, SIZE,
                         "      "
                         "id=0x%08x, client=0x%08x, identity=%u\n",
-                        lbc->clientIndex(), lbc->client ? lbc->client->cid : 0,
+                        lbc->clientIndex(), client.get() ? client->cid : 0,
                         lbc->getIdentity());
+
+                result.append(buffer);
+                buffer[0] = 0;
             }
-            result.append(buffer);
-            buffer[0] = 0;
             /*** Layer ***/
-            Layer* const l = LayerBase::dynamicCast<Layer*>((LayerBase*)layer);
-            if (l) {
-                const LayerBitmap& buf0(l->getBuffer(0));
-                const LayerBitmap& buf1(l->getBuffer(1));
+            sp<Layer> l = LayerBase::dynamicCast< Layer* >(layer.get());
+            if (l != 0) {
+                SharedBufferStack::Statistics stats = l->lcblk->getStats();
+                result.append( l->lcblk->dump("      ") );
+                sp<const GraphicBuffer> buf0(l->getBuffer(0));
+                sp<const GraphicBuffer> buf1(l->getBuffer(1));
+                uint32_t w0=0, h0=0, s0=0;
+                uint32_t w1=0, h1=0, s1=0;
+                if (buf0 != 0) {
+                    w0 = buf0->getWidth();
+                    h0 = buf0->getHeight();
+                    s0 = buf0->getStride();
+                }
+                if (buf1 != 0) {
+                    w1 = buf1->getWidth();
+                    h1 = buf1->getHeight();
+                    s1 = buf1->getStride();
+                }
                 snprintf(buffer, SIZE,
                         "      "
-                        "format=%2d, [%3ux%3u:%3u] [%3ux%3u:%3u], mTextureName=%d,"
-                        " freezeLock=%p, swapState=0x%08x\n",
+                        "format=%2d, [%3ux%3u:%3u] [%3ux%3u:%3u],"
+                        " freezeLock=%p, dq-q-time=%u us\n",
                         l->pixelFormat(),
-                        buf0.width(), buf0.height(), buf0.stride(),
-                        buf1.width(), buf1.height(), buf1.stride(),
-                        l->getTextureName(), l->getFreezeLock().get(),
-                        l->lcblk->swapState);
+                        w0, h0, s0, w1, h1, s1,
+                        l->getFreezeLock().get(), stats.totalTime);
+                result.append(buffer);
+                buffer[0] = 0;
             }
-            result.append(buffer);
-            buffer[0] = 0;
             s.transparentRegion.dump(result, "transparentRegion");
             layer->transparentRegionScreen.dump(result, "transparentRegionScreen");
             layer->visibleRegionScreen.dump(result, "visibleRegionScreen");
@@ -1523,19 +1557,28 @@
                 mFreezeDisplay?"yes":"no", mFreezeCount,
                 mCurrentState.orientation, hw.canDraw());
         result.append(buffer);
-
-        sp<AllocatorInterface> allocator;
-        if (mGPU != 0) {
-            snprintf(buffer, SIZE, "  GPU owner: %d\n", mGPU->getOwner());
+        snprintf(buffer, SIZE,
+                "  last eglSwapBuffers() time: %f us\n"
+                "  last transaction time     : %f us\n",
+                mLastSwapBufferTime/1000.0, mLastTransactionTime/1000.0);
+        result.append(buffer);
+        if (inSwapBuffersDuration || !locked) {
+            snprintf(buffer, SIZE, "  eglSwapBuffers time: %f us\n",
+                    inSwapBuffersDuration/1000.0);
             result.append(buffer);
-            allocator = mGPU->getAllocator();
-            if (allocator != 0) {
-                allocator->dump(result, "GPU Allocator");
-            }
         }
-        allocator = mSurfaceHeapManager->getAllocator(NATIVE_MEMORY_TYPE_PMEM);
-        if (allocator != 0) {
-            allocator->dump(result, "PMEM Allocator");
+        if (inTransactionDuration || !locked) {
+            snprintf(buffer, SIZE, "  transaction time: %f us\n",
+                    inTransactionDuration/1000.0);
+            result.append(buffer);
+        }
+        snprintf(buffer, SIZE, "  client count: %d\n", mClientsMap.size());
+        result.append(buffer);
+        const GraphicBufferAllocator& alloc(GraphicBufferAllocator::get());
+        alloc.dump(result);
+
+        if (locked) {
+            mStateLock.unlock();
         }
     }
     write(fd, result.string(), result.size());
@@ -1553,57 +1596,34 @@
         case FREEZE_DISPLAY:
         case UNFREEZE_DISPLAY:
         case BOOT_FINISHED:
-        case REVOKE_GPU:
         {
             // codes that require permission check
             IPCThreadState* ipc = IPCThreadState::self();
             const int pid = ipc->getCallingPid();
             const int uid = ipc->getCallingUid();
-            const int self_pid = getpid();
-            if (UNLIKELY(pid != self_pid && uid != AID_GRAPHICS)) {
-                // we're called from a different process, do the real check
-                if (!checkCallingPermission(
-                        String16("android.permission.ACCESS_SURFACE_FLINGER")))
-                {
-                    LOGE("Permission Denial: "
-                            "can't access SurfaceFlinger pid=%d, uid=%d", pid, uid);
-                    return PERMISSION_DENIED;
-                }
+            if ((uid != AID_GRAPHICS) && !mAccessSurfaceFlinger.check(pid, uid)) {
+                LOGE("Permission Denial: "
+                        "can't access SurfaceFlinger pid=%d, uid=%d", pid, uid);
+                return PERMISSION_DENIED;
             }
         }
     }
-
     status_t err = BnSurfaceComposer::onTransact(code, data, reply, flags);
     if (err == UNKNOWN_TRANSACTION || err == PERMISSION_DENIED) {
-        // HARDWARE_TEST stuff...
-        if (UNLIKELY(checkCallingPermission(
-                String16("android.permission.HARDWARE_TEST")) == false))
-        { // not allowed
-            LOGE("Permission Denial: pid=%d, uid=%d\n",
-                    IPCThreadState::self()->getCallingPid(),
-                    IPCThreadState::self()->getCallingUid());
+        CHECK_INTERFACE(ISurfaceComposer, data, reply);
+        if (UNLIKELY(!mHardwareTest.checkCalling())) {
+            IPCThreadState* ipc = IPCThreadState::self();
+            const int pid = ipc->getCallingPid();
+            const int uid = ipc->getCallingUid();
+            LOGE("Permission Denial: "
+                    "can't access SurfaceFlinger pid=%d, uid=%d", pid, uid);
             return PERMISSION_DENIED;
         }
         int n;
         switch (code) {
-            case 1000: // SHOW_CPU
-                n = data.readInt32();
-                mDebugCpu = n ? 1 : 0;
-                if (mDebugCpu) {
-                    if (mCpuGauge == 0) {
-                        mCpuGauge = new CPUGauge(this, ms2ns(500));
-                    }
-                } else {
-                    if (mCpuGauge != 0) {
-                        mCpuGauge->requestExitAndWait();
-                        Mutex::Autolock _l(mDebugLock);
-                        mCpuGauge.clear();
-                    }
-                }
+            case 1000: // SHOW_CPU, NOT SUPPORTED ANYMORE
                 return NO_ERROR;
-            case 1001:  // SHOW_FPS
-                n = data.readInt32();
-                mDebugFps = n ? 1 : 0;
+            case 1001:  // SHOW_FPS, NOT SUPPORTED ANYMORE
                 return NO_ERROR;
             case 1002:  // SHOW_UPDATES
                 n = data.readInt32();
@@ -1618,23 +1638,17 @@
                 const DisplayHardware& hw(graphicPlane(0).displayHardware());
                 mDirtyRegion.set(hw.bounds()); // careful that's not thread-safe
                 signalEvent();
+                return NO_ERROR;
             }
-            return NO_ERROR;
-            case 1005: // ask GPU revoke
-                if (mGPU != 0) {
-                    mGPU->friendlyRevoke();
-                }
+            case 1005:{ // force transaction
+                setTransactionFlags(eTransactionNeeded|eTraversalNeeded);
                 return NO_ERROR;
-            case 1006: // revoke GPU
-                if (mGPU != 0) {
-                    mGPU->unconditionalRevoke();
-                }
-                return NO_ERROR;
+            }
             case 1007: // set mFreezeCount
                 mFreezeCount = data.readInt32();
                 return NO_ERROR;
             case 1010:  // interrogate.
-                reply->writeInt32(mDebugCpu);
+                reply->writeInt32(0);
                 reply->writeInt32(0);
                 reply->writeInt32(mDebugRegion);
                 reply->writeInt32(mDebugBackground);
@@ -1658,30 +1672,24 @@
 Client::Client(ClientID clientID, const sp<SurfaceFlinger>& flinger)
     : ctrlblk(0), cid(clientID), mPid(0), mBitmap(0), mFlinger(flinger)
 {
-    mSharedHeapAllocator = getSurfaceHeapManager()->createHeap();
     const int pgsize = getpagesize();
-    const int cblksize=((sizeof(per_client_cblk_t)+(pgsize-1))&~(pgsize-1));
-    mCblkHeap = new MemoryDealer(cblksize);
-    mCblkMemory = mCblkHeap->allocate(cblksize);
-    if (mCblkMemory != 0) {
-        ctrlblk = static_cast<per_client_cblk_t *>(mCblkMemory->pointer());
-        if (ctrlblk) { // construct the shared structure in-place.
-            new(ctrlblk) per_client_cblk_t;
-        }
+    const int cblksize = ((sizeof(SharedClient)+(pgsize-1))&~(pgsize-1));
+
+    mCblkHeap = new MemoryHeapBase(cblksize, 0,
+            "SurfaceFlinger Client control-block");
+
+    ctrlblk = static_cast<SharedClient *>(mCblkHeap->getBase());
+    if (ctrlblk) { // construct the shared structure in-place.
+        new(ctrlblk) SharedClient;
     }
 }
 
 Client::~Client() {
     if (ctrlblk) {
-        const int pgsize = getpagesize();
-        ctrlblk->~per_client_cblk_t();  // destroy our shared-structure.
+        ctrlblk->~SharedClient();  // destroy our shared-structure.
     }
 }
 
-const sp<SurfaceHeapManager>& Client::getSurfaceHeapManager() const {
-    return mFlinger->getSurfaceHeapManager();
-}
-
 int32_t Client::generateId(int pid)
 {
     const uint32_t i = clz( ~mBitmap );
@@ -1693,13 +1701,15 @@
     mBitmap |= 1<<(31-i);
     return i;
 }
-status_t Client::bindLayer(LayerBaseClient* layer, int32_t id)
+
+status_t Client::bindLayer(const sp<LayerBaseClient>& layer, int32_t id)
 {
     ssize_t idx = mInUse.indexOf(id);
     if (idx < 0)
         return NAME_NOT_FOUND;
     return mLayers.insertAt(layer, idx);
 }
+
 void Client::free(int32_t id)
 {
     ssize_t idx = mInUse.remove(uint8_t(id));
@@ -1709,27 +1719,18 @@
     }
 }
 
-sp<MemoryDealer> Client::createAllocator(uint32_t flags)
-{
-    sp<MemoryDealer> allocator;
-    allocator = getSurfaceHeapManager()->createHeap(
-            flags, getClientPid(), mSharedHeapAllocator);
-    return allocator;
-}
-
 bool Client::isValid(int32_t i) const {
     return (uint32_t(i)<NUM_LAYERS_MAX) && (mBitmap & (1<<(31-i)));
 }
-const uint8_t* Client::inUseArray() const {
-    return mInUse.array();
-}
-size_t Client::numActiveLayers() const {
-    return mInUse.size();
-}
-LayerBaseClient* Client::getLayerUser(int32_t i) const {
+
+sp<LayerBaseClient> Client::getLayerUser(int32_t i) const {
+    sp<LayerBaseClient> lbc;
     ssize_t idx = mInUse.indexOf(uint8_t(i));
-    if (idx<0) return 0;
-    return mLayers[idx];
+    if (idx >= 0) {
+        lbc = mLayers[idx].promote();
+        LOGE_IF(lbc==0, "getLayerUser(i=%d), idx=%d is dead", int(i), int(idx));
+    }
+    return lbc;
 }
 
 void Client::dump(const char* what)
@@ -1741,7 +1742,7 @@
 #pragma mark -
 #endif
 
-BClient::BClient(SurfaceFlinger *flinger, ClientID cid, const sp<IMemory>& cblk)
+BClient::BClient(SurfaceFlinger *flinger, ClientID cid, const sp<IMemoryHeap>& cblk)
     : mId(cid), mFlinger(flinger), mCblk(cblk)
 {
 }
@@ -1751,8 +1752,8 @@
     mFlinger->destroyConnection(mId);
 }
 
-void BClient::getControlBlocks(sp<IMemory>* ctrl) const {
-    *ctrl = mCblk;
+sp<IMemoryHeap> BClient::getControlBlock() const {
+    return mCblk;
 }
 
 sp<ISurface> BClient::createSurface(
@@ -1766,7 +1767,7 @@
 status_t BClient::destroySurface(SurfaceID sid)
 {
     sid |= (mId << 16); // add the client-part to id
-    return mFlinger->destroySurface(sid);
+    return mFlinger->removeSurface(sid);
 }
 
 status_t BClient::setState(int32_t count, const layer_state_t* states)
@@ -1866,6 +1867,10 @@
     return mGlobalTransform;
 }
 
+EGLDisplay GraphicPlane::getEGLDisplay() const {
+    return mHw->getEGLDisplay();
+}
+
 // ---------------------------------------------------------------------------
 
 }; // namespace android
diff --git a/libs/surfaceflinger/SurfaceFlinger.h b/libs/surfaceflinger/SurfaceFlinger.h
index 0d63e1d..f9bfe6c 100644
--- a/libs/surfaceflinger/SurfaceFlinger.h
+++ b/libs/surfaceflinger/SurfaceFlinger.h
@@ -25,21 +25,24 @@
 #include <utils/threads.h>
 #include <utils/Atomic.h>
 #include <utils/Errors.h>
-#include <utils/MemoryDealer.h>
+#include <utils/RefBase.h>
+
+#include <binder/IMemory.h>
+#include <binder/Permission.h>
 
 #include <ui/PixelFormat.h>
 #include <ui/ISurfaceComposer.h>
 #include <ui/ISurfaceFlingerClient.h>
 
-#include <private/ui/SharedState.h>
+#include <private/ui/SharedBufferStack.h>
 #include <private/ui/LayerState.h>
-#include <private/ui/SurfaceFlingerSynchro.h>
 
 #include "Barrier.h"
-#include "CPUGauge.h"
 #include "Layer.h"
 #include "Tokenizer.h"
 
+#include "MessageQueue.h"
+
 struct copybit_device_t;
 struct overlay_device_t;
 
@@ -51,13 +54,8 @@
 class BClient;
 class DisplayHardware;
 class FreezeLock;
-class GPUHardwareInterface;
-class IGPUCallback;
 class Layer;
 class LayerBuffer;
-class LayerOrientationAnim;
-class OrientationAnimation;
-class SurfaceHeapManager;
 
 typedef int32_t ClientID;
 
@@ -66,7 +64,7 @@
 
 // ---------------------------------------------------------------------------
 
-class Client
+class Client : public RefBase
 {
 public:
             Client(ClientID cid, const sp<SurfaceFlinger>& flinger);
@@ -74,35 +72,34 @@
 
             int32_t                 generateId(int pid);
             void                    free(int32_t id);
-            status_t                bindLayer(LayerBaseClient* layer, int32_t id);
-            sp<MemoryDealer>        createAllocator(uint32_t memory_type);
+            status_t                bindLayer(const sp<LayerBaseClient>& layer, int32_t id);
 
     inline  bool                    isValid(int32_t i) const;
-    inline  const uint8_t*          inUseArray() const;
-    inline  size_t                  numActiveLayers() const;
-    LayerBaseClient*                getLayerUser(int32_t i) const;
-    const Vector<LayerBaseClient*>& getLayers() const { return mLayers; }
-    const sp<IMemory>&              controlBlockMemory() const { return mCblkMemory; }
+    sp<LayerBaseClient>             getLayerUser(int32_t i) const;
     void                            dump(const char* what);
-    const sp<SurfaceHeapManager>&   getSurfaceHeapManager() const;
+    
+    const Vector< wp<LayerBaseClient> >& getLayers() const { 
+        return mLayers; 
+    }
+    
+    const sp<IMemoryHeap>& getControlBlockMemory() const {
+        return mCblkHeap; 
+    }
     
     // pointer to this client's control block
-    per_client_cblk_t*      ctrlblk;
+    SharedClient*           ctrlblk;
     ClientID                cid;
 
     
 private:
-    int                     getClientPid() const { return mPid; }
+    int getClientPid() const { return mPid; }
         
-    int                         mPid;
-    uint32_t                    mBitmap;
-    SortedVector<uint8_t>       mInUse;
-    Vector<LayerBaseClient*>    mLayers;
-    sp<MemoryDealer>            mCblkHeap;
-    sp<SurfaceFlinger>          mFlinger;
-    sp<MemoryDealer>            mSharedHeapAllocator;
-    sp<MemoryDealer>            mPMemAllocator;
-    sp<IMemory>                 mCblkMemory;
+    int                             mPid;
+    uint32_t                        mBitmap;
+    SortedVector<uint8_t>           mInUse;
+    Vector< wp<LayerBaseClient> >   mLayers;
+    sp<IMemoryHeap>                 mCblkHeap;
+    sp<SurfaceFlinger>              mFlinger;
 };
 
 // ---------------------------------------------------------------------------
@@ -125,6 +122,8 @@
 
         const DisplayHardware&  displayHardware() const;
         const Transform&        transform() const;
+        EGLDisplay              getEGLDisplay() const;
+        
 private:
                                 GraphicPlane(const GraphicPlane&);
         GraphicPlane            operator = (const GraphicPlane&);
@@ -160,7 +159,7 @@
 
     // ISurfaceComposer interface
     virtual sp<ISurfaceFlingerClient>   createConnection();
-    virtual sp<IMemory>                 getCblk() const;
+    virtual sp<IMemoryHeap>             getCblk() const;
     virtual void                        bootFinished();
     virtual void                        openGlobalTransaction();
     virtual void                        closeGlobalTransaction();
@@ -168,56 +167,52 @@
     virtual status_t                    unfreezeDisplay(DisplayID dpy, uint32_t flags);
     virtual int                         setOrientation(DisplayID dpy, int orientation, uint32_t flags);
     virtual void                        signal() const;
-    virtual status_t requestGPU(const sp<IGPUCallback>& callback, 
-            gpu_info_t* gpu);
-    virtual status_t revokeGPU();
 
             void                        screenReleased(DisplayID dpy);
             void                        screenAcquired(DisplayID dpy);
 
-            const sp<SurfaceHeapManager>& getSurfaceHeapManager() const { 
-                return mSurfaceHeapManager; 
-            }
-
-            const sp<GPUHardwareInterface>& getGPU() const {
-                return mGPU; 
-            }
-
-            copybit_device_t* getBlitEngine() const;
             overlay_control_device_t* getOverlayEngine() const;
 
             
-    status_t removeLayer(LayerBase* layer);
-    status_t addLayer(LayerBase* layer);
-    status_t invalidateLayerVisibility(LayerBase* layer);
+    status_t removeLayer(const sp<LayerBase>& layer);
+    status_t addLayer(const sp<LayerBase>& layer);
+    status_t invalidateLayerVisibility(const sp<LayerBase>& layer);
     
 private:
     friend class BClient;
     friend class LayerBase;
     friend class LayerBuffer;
     friend class LayerBaseClient;
+    friend class LayerBaseClient::Surface;
     friend class Layer;
     friend class LayerBlur;
+    friend class LayerDim;
 
     sp<ISurface> createSurface(ClientID client, int pid, 
             ISurfaceFlingerClient::surface_data_t* params,
             DisplayID display, uint32_t w, uint32_t h, PixelFormat format,
             uint32_t flags);
 
-    LayerBaseClient* createNormalSurfaceLocked(Client* client, DisplayID display,
-            int32_t id, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags);
+    sp<LayerBaseClient> createNormalSurfaceLocked(
+            const sp<Client>& client, DisplayID display,
+            int32_t id, uint32_t w, uint32_t h, uint32_t flags,
+            PixelFormat& format);
 
-    LayerBaseClient* createBlurSurfaceLocked(Client* client, DisplayID display,
+    sp<LayerBaseClient> createBlurSurfaceLocked(
+            const sp<Client>& client, DisplayID display,
             int32_t id, uint32_t w, uint32_t h, uint32_t flags);
 
-    LayerBaseClient* createDimSurfaceLocked(Client* client, DisplayID display,
+    sp<LayerBaseClient> createDimSurfaceLocked(
+            const sp<Client>& client, DisplayID display,
             int32_t id, uint32_t w, uint32_t h, uint32_t flags);
 
-    LayerBaseClient* createPushBuffersSurfaceLocked(Client* client, DisplayID display,
+    sp<LayerBaseClient> createPushBuffersSurfaceLocked(
+            const sp<Client>& client, DisplayID display,
             int32_t id, uint32_t w, uint32_t h, uint32_t flags);
 
-    status_t    destroySurface(SurfaceID surface_id);
-    status_t    setClientState(ClientID cid, int32_t count, const layer_state_t* states);
+    status_t removeSurface(SurfaceID surface_id);
+    status_t destroySurface(const sp<LayerBaseClient>& layer);
+    status_t setClientState(ClientID cid, int32_t count, const layer_state_t* states);
 
 
     class LayerVector {
@@ -225,15 +220,15 @@
         inline              LayerVector() { }
                             LayerVector(const LayerVector&);
         inline size_t       size() const { return layers.size(); }
-        inline LayerBase*const* array() const { return layers.array(); }
-        ssize_t             add(LayerBase*, Vector<LayerBase*>::compar_t);
-        ssize_t             remove(LayerBase*);
-        ssize_t             reorder(LayerBase*, Vector<LayerBase*>::compar_t);
-        ssize_t             indexOf(LayerBase* key, size_t guess=0) const;
-        inline LayerBase*   operator [] (size_t i) const { return layers[i]; }
+        inline sp<LayerBase> const* array() const { return layers.array(); }
+        ssize_t             add(const sp<LayerBase>&, Vector< sp<LayerBase> >::compar_t);
+        ssize_t             remove(const sp<LayerBase>&);
+        ssize_t             reorder(const sp<LayerBase>&, Vector< sp<LayerBase> >::compar_t);
+        ssize_t             indexOf(const sp<LayerBase>& key, size_t guess=0) const;
+        inline sp<LayerBase> operator [] (size_t i) const { return layers[i]; }
     private:
-        KeyedVector<LayerBase*, size_t> lookup;
-        Vector<LayerBase*>              layers;
+        KeyedVector< sp<LayerBase> , size_t> lookup;
+        Vector< sp<LayerBase> >              layers;
     };
 
     struct State {
@@ -247,38 +242,26 @@
         uint8_t         freezeDisplay;
     };
 
-    class DelayedTransaction : public Thread
-    {
-        friend class SurfaceFlinger;
-        sp<SurfaceFlinger>  mFlinger;
-        nsecs_t             mDelay;
-    public:
-        DelayedTransaction(const sp<SurfaceFlinger>& flinger, nsecs_t delay)
-            : Thread(false), mFlinger(flinger), mDelay(delay) {
-        }
-        virtual bool threadLoop() {
-            usleep(mDelay / 1000);
-            if (android_atomic_and(~1,
-                    &mFlinger->mDeplayedTransactionPending) == 1) {
-                mFlinger->signalEvent();
-            }
-            return false;
-        }
-    };
-
     virtual bool        threadLoop();
     virtual status_t    readyToRun();
     virtual void        onFirstRef();
 
+public:     // hack to work around gcc 4.0.3 bug
     const GraphicPlane&     graphicPlane(int dpy) const;
           GraphicPlane&     graphicPlane(int dpy);
+private:
 
             void        waitForEvent();
+public:     // hack to work around gcc 4.0.3 bug
             void        signalEvent();
+private:
             void        signalDelayedEvent(nsecs_t delay);
 
             void        handleConsoleEvents();
             void        handleTransaction(uint32_t transactionFlags);
+            void        handleTransactionLocked(
+                            uint32_t transactionFlags, 
+                            Vector< sp<LayerBase> >& ditchedLayers);
 
             void        computeVisibleRegions(
                             LayerVector& currentLayers,
@@ -289,19 +272,16 @@
             bool        lockPageFlip(const LayerVector& currentLayers);
             void        unlockPageFlip(const LayerVector& currentLayers);
             void        handleRepaint();
-            void        handleDebugCpu();
-            void        scheduleBroadcast(Client* client);
-            void        executeScheduledBroadcasts();
             void        postFramebuffer();
             void        composeSurfaces(const Region& dirty);
             void        unlockClients();
 
 
             void        destroyConnection(ClientID cid);
-            LayerBaseClient* getLayerUser_l(SurfaceID index) const;
-            status_t    addLayer_l(LayerBase* layer);
-            status_t    removeLayer_l(LayerBase* layer);
-            void        destroy_all_removed_layers_l();
+            sp<LayerBaseClient> getLayerUser_l(SurfaceID index) const;
+            status_t    addLayer_l(const sp<LayerBase>& layer);
+            status_t    removeLayer_l(const sp<LayerBase>& layer);
+            status_t    purgatorizeLayer_l(const sp<LayerBase>& layer);
             void        free_resources_l();
 
             uint32_t    getTransactionFlags(uint32_t flags);
@@ -315,7 +295,7 @@
             inline void decFreezeCount() { if (mFreezeCount > 0) mFreezeCount--; }
             inline bool hasFreezeRequest() const { return mFreezeDisplay; }
             inline bool isFrozen() const { 
-                return mFreezeDisplay || mFreezeCount>0;
+                return (mFreezeDisplay || mFreezeCount>0) && mBootFinished;
             }
 
             
@@ -323,6 +303,11 @@
             void        debugShowFPS() const;
             void        drawWormhole() const;
            
+
+    mutable     MessageQueue    mEventQueue;
+    
+                
+                
                 // access must be protected by mStateLock
     mutable     Mutex                   mStateLock;
                 State                   mCurrentState;
@@ -330,23 +315,24 @@
     volatile    int32_t                 mTransactionFlags;
     volatile    int32_t                 mTransactionCount;
                 Condition               mTransactionCV;
-
+                bool                    mResizeTransationPending;
+                
                 // protected by mStateLock (but we could use another lock)
                 Tokenizer                               mTokens;
-                DefaultKeyedVector<ClientID, Client*>   mClientsMap;
-                DefaultKeyedVector<SurfaceID, LayerBaseClient*>   mLayerMap;
+                DefaultKeyedVector<ClientID, sp<Client> >   mClientsMap;
+                DefaultKeyedVector<SurfaceID, sp<LayerBaseClient> >   mLayerMap;
                 GraphicPlane                            mGraphicPlanes[1];
-                SortedVector<LayerBase*>                mRemovedLayers;
-                Vector<Client*>                         mDisconnectedClients;
+                bool                                    mLayersRemoved;
+                Vector< sp<Client> >                    mDisconnectedClients;
 
                 // constant members (no synchronization needed for access)
-                sp<MemoryDealer>            mServerHeap;
-                sp<IMemory>                 mServerCblkMemory;
+                sp<IMemoryHeap>             mServerHeap;
                 surface_flinger_cblk_t*     mServerCblk;
-                sp<SurfaceHeapManager>      mSurfaceHeapManager;
-                sp<GPUHardwareInterface>    mGPU;
                 GLuint                      mWormholeTexName;
                 nsecs_t                     mBootTime;
+                Permission                  mHardwareTest;
+                Permission                  mAccessSurfaceFlinger;
+                Permission                  mDump;
                 
                 // Can only accessed from the main thread, these members
                 // don't need synchronization
@@ -354,30 +340,23 @@
                 Region                      mDirtyRegionRemovedLayer;
                 Region                      mInvalidRegion;
                 Region                      mWormholeRegion;
-                Client*                     mLastScheduledBroadcast;
-                SortedVector<Client*>       mScheduledBroadcasts;
                 bool                        mVisibleRegionsDirty;
                 bool                        mDeferReleaseConsole;
                 bool                        mFreezeDisplay;
                 int32_t                     mFreezeCount;
                 nsecs_t                     mFreezeDisplayTime;
-                friend class OrientationAnimation;
-                OrientationAnimation*       mOrientationAnimation;
-
-                // access protected by mDebugLock
-    mutable     Mutex                       mDebugLock;
-                sp<CPUGauge>                mCpuGauge;
 
                 // don't use a lock for these, we don't care
                 int                         mDebugRegion;
-                int                         mDebugCpu;
-                int                         mDebugFps;
                 int                         mDebugBackground;
+                volatile nsecs_t            mDebugInSwapBuffers;
+                nsecs_t                     mLastSwapBufferTime;
+                volatile nsecs_t            mDebugInTransaction;
+                nsecs_t                     mLastTransactionTime;
+                bool                        mBootFinished;
 
                 // these are thread safe
     mutable     Barrier                     mReadyToRunBarrier;
-    mutable     SurfaceFlingerSynchro       mSyncObject;
-    volatile    int32_t                     mDeplayedTransactionPending;
 
                 // atomic variables
                 enum {
@@ -410,11 +389,11 @@
 {
 public:
     BClient(SurfaceFlinger *flinger, ClientID cid,
-            const sp<IMemory>& cblk);
+            const sp<IMemoryHeap>& cblk);
     ~BClient();
 
     // ISurfaceFlingerClient interface
-    virtual void getControlBlocks(sp<IMemory>* ctrl) const;
+    virtual sp<IMemoryHeap> getControlBlock() const;
 
     virtual sp<ISurface> createSurface(
             surface_data_t* params, int pid,
@@ -427,7 +406,7 @@
 private:
     ClientID            mId;
     SurfaceFlinger*     mFlinger;
-    sp<IMemory>         mCblk;
+    sp<IMemoryHeap>     mCblk;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/libs/surfaceflinger/Tokenizer.cpp b/libs/surfaceflinger/Tokenizer.cpp
index ef51d6a..be3a239 100644
--- a/libs/surfaceflinger/Tokenizer.cpp
+++ b/libs/surfaceflinger/Tokenizer.cpp
@@ -162,9 +162,10 @@
 {
     const run_t* ranges = mRanges.array();
     const size_t c = mRanges.size();
-    printf("Tokenizer (%p, size = %lu)\n", this, c);
+    printf("Tokenizer (%p, size = %d)\n", this, int(c));
     for (size_t i=0 ; i<c ; i++) {
-        printf("%lu: (%u, %u)\n", i, ranges[i].first, ranges[i].length);
+        printf("%u: (%u, %u)\n", i,
+                uint32_t(ranges[i].first), uint32_t(ranges[i].length));
     }
 }
 
diff --git a/libs/surfaceflinger/Transform.cpp b/libs/surfaceflinger/Transform.cpp
index e8b0f45..1501536 100644
--- a/libs/surfaceflinger/Transform.cpp
+++ b/libs/surfaceflinger/Transform.cpp
@@ -177,10 +177,10 @@
     Region out;
     if (UNLIKELY(transformed())) {
         if (LIKELY(preserveRects())) {
-            Rect r;
-            Region::iterator iterator(reg);
-            while (iterator.iterate(&r)) {
-                out.orSelf(transform(r));
+            Region::const_iterator it = reg.begin();
+            Region::const_iterator const end = reg.end();
+            while (it != end) {
+                out.orSelf(transform(*it++));
             }
         } else {
             out.set(transform(reg.bounds()));
diff --git a/libs/surfaceflinger/Transform.h b/libs/surfaceflinger/Transform.h
index 4c4528e..78f5c19 100644
--- a/libs/surfaceflinger/Transform.h
+++ b/libs/surfaceflinger/Transform.h
@@ -50,6 +50,14 @@
                 ROT_INVALID = 0x80000000
             };
 
+            enum type_mask {
+                IDENTITY            = 0,
+                TRANSLATE           = 0x1,
+                SCALE               = 0x2,
+                AFFINE              = 0x4,
+                PERSPECTIVE         = 0x8
+            };
+
             bool    transformed() const;
             int32_t getOrientation() const;
             bool    preserveRects() const;
diff --git a/libs/surfaceflinger/VRamHeap.cpp b/libs/surfaceflinger/VRamHeap.cpp
deleted file mode 100644
index 5f633bd..0000000
--- a/libs/surfaceflinger/VRamHeap.cpp
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * 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 "SurfaceFlinger"
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <math.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-
-#include <cutils/log.h>
-#include <cutils/properties.h>
-
-#include <utils/MemoryDealer.h>
-#include <utils/MemoryBase.h>
-#include <utils/MemoryHeapPmem.h>
-#include <utils/MemoryHeapBase.h>
-
-#include <EGL/eglnatives.h>
-
-#include "GPUHardware/GPUHardware.h"
-#include "SurfaceFlinger.h"
-#include "VRamHeap.h"
-
-#if HAVE_ANDROID_OS
-#include <linux/android_pmem.h>
-#endif
-
-
-namespace android {
-
-// ---------------------------------------------------------------------------
-
-/*
- * Amount of memory we reserve for surface, per client in PMEM
- * (PMEM is used for 2D acceleration)
- * 8 MB of address space per client should be enough.
- */
-static const int PMEM_SIZE = int(8 * 1024 * 1024);
-
-int SurfaceHeapManager::global_pmem_heap = 0;
-
-// ---------------------------------------------------------------------------
-
-SurfaceHeapManager::SurfaceHeapManager(const sp<SurfaceFlinger>& flinger, 
-        size_t clientHeapSize)
-    : mFlinger(flinger), mClientHeapSize(clientHeapSize)
-{
-    SurfaceHeapManager::global_pmem_heap = 1;
-}
-
-SurfaceHeapManager::~SurfaceHeapManager()
-{
-}
-
-void SurfaceHeapManager::onFirstRef()
-{
-    if (global_pmem_heap) {
-        const char* device = "/dev/pmem";
-        mPMemHeap = new PMemHeap(device, PMEM_SIZE);
-        if (mPMemHeap->base() == MAP_FAILED) {
-            mPMemHeap.clear();
-            global_pmem_heap = 0;
-        }
-    }
-}
-
-sp<MemoryDealer> SurfaceHeapManager::createHeap(
-        uint32_t flags,
-        pid_t client_pid,
-        const sp<MemoryDealer>& defaultAllocator)
-{
-    sp<MemoryDealer> dealer; 
-
-    if (flags & ISurfaceComposer::eGPU) {
-        // don't grant GPU memory if GPU is disabled
-        char value[PROPERTY_VALUE_MAX];
-        property_get("debug.egl.hw", value, "1");
-        if (atoi(value) == 0) {
-            flags &= ~ISurfaceComposer::eGPU;
-        }
-    }
-
-    if ((flags & ISurfaceComposer::eGPU) && (mFlinger->getGPU() != 0)) {
-        // FIXME: this is msm7201A specific, where gpu surfaces may not be secure
-        if (!(flags & ISurfaceComposer::eSecure)) {
-            // if GPU doesn't work, we try eHardware
-            flags |= ISurfaceComposer::eHardware;
-            // asked for GPU memory, try that first
-            dealer = mFlinger->getGPU()->request(client_pid);
-        }
-    }
-
-    if (dealer == NULL) {
-        if (defaultAllocator != NULL)
-            // if a default allocator is given, use that
-            dealer = defaultAllocator;
-    }
-    
-    if (dealer == NULL) {
-        // always try h/w accelerated memory first
-        if (global_pmem_heap) {
-            const sp<PMemHeap>& heap(mPMemHeap);
-            if (dealer == NULL && heap != NULL) {
-                dealer = new MemoryDealer( 
-                        heap->createClientHeap(),
-                        heap->getAllocator());
-            }
-        }
-    }
-
-    if (dealer == NULL) {
-        // return the ashmem allocator (software rendering)
-        dealer = new MemoryDealer(mClientHeapSize, 0, "SFNativeHeap");
-    }
-    return dealer;
-}
-
-sp<SimpleBestFitAllocator> SurfaceHeapManager::getAllocator(int type) const 
-{
-    Mutex::Autolock _l(mLock);
-    sp<SimpleBestFitAllocator> allocator;
-
-    // this is only used for debugging
-    switch (type) {
-        case NATIVE_MEMORY_TYPE_PMEM:
-            if (mPMemHeap != 0) {
-                allocator = mPMemHeap->getAllocator();
-            }
-            break;
-    }
-    return allocator;
-}
-
-// ---------------------------------------------------------------------------
-
-PMemHeap::PMemHeap(const char* const device, size_t size, size_t reserved)
-    : MemoryHeapBase(device, size)
-{
-    //LOGD("%s, %p, mFD=%d", __PRETTY_FUNCTION__, this, heapID());
-    if (base() != MAP_FAILED) {
-        //LOGD("%s, %u bytes", device, virtualSize());
-        if (reserved == 0)
-            reserved = virtualSize();
-        mAllocator = new SimpleBestFitAllocator(reserved);
-    }
-}
-
-PMemHeap::~PMemHeap() {
-    //LOGD("%s, %p, mFD=%d", __PRETTY_FUNCTION__, this, heapID());
-}
-
-sp<MemoryHeapPmem> PMemHeap::createClientHeap() {
-    sp<MemoryHeapBase> parentHeap(this);
-    return new MemoryHeapPmem(parentHeap);
-}
-
-// ---------------------------------------------------------------------------
-}; // namespace android
diff --git a/libs/surfaceflinger/VRamHeap.h b/libs/surfaceflinger/VRamHeap.h
deleted file mode 100644
index 9140167..0000000
--- a/libs/surfaceflinger/VRamHeap.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef ANDROID_VRAM_HEAP_H
-#define ANDROID_VRAM_HEAP_H
-
-#include <stdint.h>
-#include <sys/types.h>
-#include <utils/MemoryDealer.h>
-
-namespace android {
-
-// ---------------------------------------------------------------------------
-
-class PMemHeap;
-class MemoryHeapPmem;
-class SurfaceFlinger; 
-
-// ---------------------------------------------------------------------------
-
-class SurfaceHeapManager  : public RefBase
-{
-public:
-    SurfaceHeapManager(const sp<SurfaceFlinger>& flinger, size_t clientHeapSize);
-    virtual ~SurfaceHeapManager();
-    virtual void onFirstRef();
-    /* use ISurfaceComposer flags eGPU|eHArdware|eSecure */
-    sp<MemoryDealer> createHeap(uint32_t flags=0, pid_t client_pid = 0,
-            const sp<MemoryDealer>& defaultAllocator = 0);
-    
-    // used for debugging only...
-    sp<SimpleBestFitAllocator> getAllocator(int type) const;
-
-private:
-    sp<PMemHeap> getHeap(int type) const;
-
-    sp<SurfaceFlinger> mFlinger;
-    mutable Mutex   mLock;
-    size_t          mClientHeapSize;
-    sp<PMemHeap>    mPMemHeap;
-    static int global_pmem_heap;
-};
-
-// ---------------------------------------------------------------------------
-
-class PMemHeap : public MemoryHeapBase
-{
-public:
-                PMemHeap(const char* const vram,
-                        size_t size=0, size_t reserved=0);
-    virtual     ~PMemHeap();
-    
-    virtual const sp<SimpleBestFitAllocator>& getAllocator() const {
-        return mAllocator; 
-    }
-    virtual sp<MemoryHeapPmem> createClientHeap();
-    
-private:
-    sp<SimpleBestFitAllocator>  mAllocator;
-};
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-
-#endif // ANDROID_VRAM_HEAP_H
diff --git a/libs/surfaceflinger/tests/overlays/overlays.cpp b/libs/surfaceflinger/tests/overlays/overlays.cpp
index f3c046f..0b9322e 100644
--- a/libs/surfaceflinger/tests/overlays/overlays.cpp
+++ b/libs/surfaceflinger/tests/overlays/overlays.cpp
@@ -1,6 +1,6 @@
-#include <utils/IPCThreadState.h>
-#include <utils/ProcessState.h>
-#include <utils/IServiceManager.h>
+#include <binder/IPCThreadState.h>
+#include <binder/ProcessState.h>
+#include <binder/IServiceManager.h>
 #include <utils/Log.h>
 
 #include <ui/Surface.h>
diff --git a/libs/surfaceflinger/tests/resize/Android.mk b/libs/surfaceflinger/tests/resize/Android.mk
new file mode 100644
index 0000000..ef1532f
--- /dev/null
+++ b/libs/surfaceflinger/tests/resize/Android.mk
@@ -0,0 +1,16 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+	resize.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+	libcutils \
+	libutils \
+    libui
+
+LOCAL_MODULE:= test-resize
+
+LOCAL_MODULE_TAGS := tests
+
+include $(BUILD_EXECUTABLE)
diff --git a/libs/surfaceflinger/tests/resize/resize.cpp b/libs/surfaceflinger/tests/resize/resize.cpp
new file mode 100644
index 0000000..21c6ab6
--- /dev/null
+++ b/libs/surfaceflinger/tests/resize/resize.cpp
@@ -0,0 +1,60 @@
+#include <cutils/memory.h>
+
+#include <utils/IPCThreadState.h>
+#include <utils/ProcessState.h>
+#include <utils/IServiceManager.h>
+#include <utils/Log.h>
+
+#include <ui/Surface.h>
+#include <ui/ISurface.h>
+#include <ui/Overlay.h>
+#include <ui/SurfaceComposerClient.h>
+
+using namespace android;
+
+namespace android {
+class Test {
+public:
+    static const sp<ISurface>& getISurface(const sp<Surface>& s) {
+        return s->getISurface();
+    }
+};
+};
+
+int main(int argc, char** argv)
+{
+    // set up the thread-pool
+    sp<ProcessState> proc(ProcessState::self());
+    ProcessState::self()->startThreadPool();
+
+    // create a client to surfaceflinger
+    sp<SurfaceComposerClient> client = new SurfaceComposerClient();
+    
+    // create pushbuffer surface
+    sp<Surface> surface = client->createSurface(getpid(), 0, 160, 240, 
+            PIXEL_FORMAT_RGB_565);
+
+
+    client->openTransaction();
+    surface->setLayer(100000);
+    client->closeTransaction();
+
+    Surface::SurfaceInfo info;
+    surface->lock(&info);
+    ssize_t bpr = info.s * bytesPerPixel(info.format);
+    android_memset16((uint16_t*)info.bits, 0xF800, bpr*info.h);
+    surface->unlockAndPost();
+
+    surface->lock(&info);
+    android_memset16((uint16_t*)info.bits, 0x07E0, bpr*info.h);
+    surface->unlockAndPost();
+
+    client->openTransaction();
+    surface->setSize(320, 240);
+    client->closeTransaction();
+
+    
+    IPCThreadState::self()->joinThreadPool();
+    
+    return 0;
+}
diff --git a/libs/ui/Android.mk b/libs/ui/Android.mk
index 7bbe38b..84aec61 100644
--- a/libs/ui/Android.mk
+++ b/libs/ui/Android.mk
@@ -4,10 +4,13 @@
 LOCAL_SRC_FILES:= \
 	Camera.cpp \
 	CameraParameters.cpp \
-	EGLDisplaySurface.cpp \
-	EGLNativeWindowSurface.cpp \
+	EGLUtils.cpp \
 	EventHub.cpp \
 	EventRecurrence.cpp \
+	FramebufferNativeWindow.cpp \
+	GraphicBuffer.cpp \
+	GraphicBufferAllocator.cpp \
+	GraphicBufferMapper.cpp \
 	KeyLayoutMap.cpp \
 	KeyCharacterMap.cpp \
 	ICamera.cpp \
@@ -22,18 +25,23 @@
 	PixelFormat.cpp \
 	Rect.cpp \
 	Region.cpp \
+	SharedBufferStack.cpp \
 	Surface.cpp \
-	SurfaceComposerClient.cpp \
-	SurfaceFlingerSynchro.cpp 
+	SurfaceComposerClient.cpp
 
 LOCAL_SHARED_LIBRARIES := \
-	libcorecg \
 	libcutils \
 	libutils \
+	libEGL \
+	libbinder \
 	libpixelflinger \
 	libhardware \
 	libhardware_legacy
 
 LOCAL_MODULE:= libui
 
+ifeq ($(TARGET_SIMULATOR),true)
+    LOCAL_LDLIBS += -lpthread
+endif
+
 include $(BUILD_SHARED_LIBRARY)
diff --git a/libs/ui/Camera.cpp b/libs/ui/Camera.cpp
index 5015379..09a36f1 100644
--- a/libs/ui/Camera.cpp
+++ b/libs/ui/Camera.cpp
@@ -19,9 +19,9 @@
 //#define LOG_NDEBUG 0
 #define LOG_TAG "Camera"
 #include <utils/Log.h>
-#include <utils/IServiceManager.h>
+#include <binder/IServiceManager.h>
 #include <utils/threads.h>
-#include <utils/IMemory.h>
+#include <binder/IMemory.h>
 #include <ui/Surface.h>
 #include <ui/Camera.h>
 #include <ui/ICameraService.h>
@@ -242,6 +242,14 @@
     return c->autoFocus();
 }
 
+status_t Camera::cancelAutoFocus()
+{
+    LOGV("cancelAutoFocus");
+    sp <ICamera> c = mCamera;
+    if (c == 0) return NO_INIT;
+    return c->cancelAutoFocus();
+}
+
 // take a picture
 status_t Camera::takePicture()
 {
@@ -270,6 +278,15 @@
     return params;
 }
 
+// send command to camera driver
+status_t Camera::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2)
+{
+    LOGD("sendCommand");
+    sp <ICamera> c = mCamera;
+    if (c == 0) return NO_INIT;
+    return c->sendCommand(cmd, arg1, arg2);
+}
+
 void Camera::setListener(const sp<CameraListener>& listener)
 {
     Mutex::Autolock _l(mLock);
diff --git a/libs/ui/CameraParameters.cpp b/libs/ui/CameraParameters.cpp
index 6c25836..8f1749d 100644
--- a/libs/ui/CameraParameters.cpp
+++ b/libs/ui/CameraParameters.cpp
@@ -2,16 +2,16 @@
 **
 ** 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 
+** 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 
+**     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 
+** 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.
 */
 
@@ -23,6 +23,103 @@
 #include <ui/CameraParameters.h>
 
 namespace android {
+// Parameter keys to communicate between camera application and driver.
+const char CameraParameters::KEY_PREVIEW_SIZE[] = "preview-size";
+const char CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES[] = "preview-size-values";
+const char CameraParameters::KEY_PREVIEW_FORMAT[] = "preview-format";
+const char CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS[] = "preview-format-values";
+const char CameraParameters::KEY_PREVIEW_FRAME_RATE[] = "preview-frame-rate";
+const char CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES[] = "preview-frame-rate-values";
+const char CameraParameters::KEY_PICTURE_SIZE[] = "picture-size";
+const char CameraParameters::KEY_SUPPORTED_PICTURE_SIZES[] = "picture-size-values";
+const char CameraParameters::KEY_PICTURE_FORMAT[] = "picture-format";
+const char CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS[] = "picture-format-values";
+const char CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH[] = "jpeg-thumbnail-width";
+const char CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT[] = "jpeg-thumbnail-height";
+const char CameraParameters::KEY_SUPPORTED_THUMBNAIL_SIZES[] = "jpeg-thumbnail-size-values";
+const char CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY[] = "jpeg-thumbnail-quality";
+const char CameraParameters::KEY_JPEG_QUALITY[] = "jpeg-quality";
+const char CameraParameters::KEY_ROTATION[] = "rotation";
+const char CameraParameters::KEY_GPS_LATITUDE[] = "gps-latitude";
+const char CameraParameters::KEY_GPS_LONGITUDE[] = "gps-longitude";
+const char CameraParameters::KEY_GPS_ALTITUDE[] = "gps-altitude";
+const char CameraParameters::KEY_GPS_TIMESTAMP[] = "gps-timestamp";
+const char CameraParameters::KEY_WHITE_BALANCE[] = "whitebalance";
+const char CameraParameters::KEY_SUPPORTED_WHITE_BALANCE[] = "whitebalance-values";
+const char CameraParameters::KEY_EFFECT[] = "effect";
+const char CameraParameters::KEY_SUPPORTED_EFFECTS[] = "effect-values";
+const char CameraParameters::KEY_ANTIBANDING[] = "antibanding";
+const char CameraParameters::KEY_SUPPORTED_ANTIBANDING[] = "antibanding-values";
+const char CameraParameters::KEY_SCENE_MODE[] = "scene-mode";
+const char CameraParameters::KEY_SUPPORTED_SCENE_MODES[] = "scene-mode-values";
+const char CameraParameters::KEY_FLASH_MODE[] = "flash-mode";
+const char CameraParameters::KEY_SUPPORTED_FLASH_MODES[] = "flash-mode-values";
+const char CameraParameters::KEY_FOCUS_MODE[] = "focus-mode";
+const char CameraParameters::KEY_SUPPORTED_FOCUS_MODES[] = "focus-mode-values";
+
+// Values for white balance settings.
+const char CameraParameters::WHITE_BALANCE_AUTO[] = "auto";
+const char CameraParameters::WHITE_BALANCE_INCANDESCENT[] = "incandescent";
+const char CameraParameters::WHITE_BALANCE_FLUORESCENT[] = "fluorescent";
+const char CameraParameters::WHITE_BALANCE_WARM_FLUORESCENT[] = "warm-fluorescent";
+const char CameraParameters::WHITE_BALANCE_DAYLIGHT[] = "daylight";
+const char CameraParameters::WHITE_BALANCE_CLOUDY_DAYLIGHT[] = "cloudy-daylight";
+const char CameraParameters::WHITE_BALANCE_TWILIGHT[] = "twilight";
+const char CameraParameters::WHITE_BALANCE_SHADE[] = "shade";
+
+// Values for effect settings.
+const char CameraParameters::EFFECT_NONE[] = "none";
+const char CameraParameters::EFFECT_MONO[] = "mono";
+const char CameraParameters::EFFECT_NEGATIVE[] = "negative";
+const char CameraParameters::EFFECT_SOLARIZE[] = "solarize";
+const char CameraParameters::EFFECT_SEPIA[] = "sepia";
+const char CameraParameters::EFFECT_POSTERIZE[] = "posterize";
+const char CameraParameters::EFFECT_WHITEBOARD[] = "whiteboard";
+const char CameraParameters::EFFECT_BLACKBOARD[] = "blackboard";
+const char CameraParameters::EFFECT_AQUA[] = "aqua";
+
+// Values for antibanding settings.
+const char CameraParameters::ANTIBANDING_AUTO[] = "auto";
+const char CameraParameters::ANTIBANDING_50HZ[] = "50hz";
+const char CameraParameters::ANTIBANDING_60HZ[] = "60hz";
+const char CameraParameters::ANTIBANDING_OFF[] = "off";
+
+// Values for flash mode settings.
+const char CameraParameters::FLASH_MODE_OFF[] = "off";
+const char CameraParameters::FLASH_MODE_AUTO[] = "auto";
+const char CameraParameters::FLASH_MODE_ON[] = "on";
+const char CameraParameters::FLASH_MODE_RED_EYE[] = "red-eye";
+const char CameraParameters::FLASH_MODE_TORCH[] = "torch";
+
+// Values for scene mode settings.
+const char CameraParameters::SCENE_MODE_AUTO[] = "auto";
+const char CameraParameters::SCENE_MODE_ACTION[] = "action";
+const char CameraParameters::SCENE_MODE_PORTRAIT[] = "portrait";
+const char CameraParameters::SCENE_MODE_LANDSCAPE[] = "landscape";
+const char CameraParameters::SCENE_MODE_NIGHT[] = "night";
+const char CameraParameters::SCENE_MODE_NIGHT_PORTRAIT[] = "night-portrait";
+const char CameraParameters::SCENE_MODE_THEATRE[] = "theatre";
+const char CameraParameters::SCENE_MODE_BEACH[] = "beach";
+const char CameraParameters::SCENE_MODE_SNOW[] = "snow";
+const char CameraParameters::SCENE_MODE_SUNSET[] = "sunset";
+const char CameraParameters::SCENE_MODE_STEADYPHOTO[] = "steadyphoto";
+const char CameraParameters::SCENE_MODE_FIREWORKS[] = "fireworks";
+const char CameraParameters::SCENE_MODE_SPORTS[] = "sports";
+const char CameraParameters::SCENE_MODE_PARTY[] = "party";
+const char CameraParameters::SCENE_MODE_CANDLELIGHT[] = "candlelight";
+
+// Formats for setPreviewFormat and setPictureFormat.
+const char CameraParameters::PIXEL_FORMAT_YUV422SP[] = "yuv422sp";
+const char CameraParameters::PIXEL_FORMAT_YUV420SP[] = "yuv420sp";
+const char CameraParameters::PIXEL_FORMAT_YUV422I[] = "yuv422i-yuyv";
+const char CameraParameters::PIXEL_FORMAT_RGB565[] = "rgb565";
+const char CameraParameters::PIXEL_FORMAT_JPEG[] = "jpeg";
+
+// Values for focus mode settings.
+const char CameraParameters::FOCUS_MODE_AUTO[] = "auto";
+const char CameraParameters::FOCUS_MODE_INFINITY[] = "infinity";
+const char CameraParameters::FOCUS_MODE_MACRO[] = "macro";
+const char CameraParameters::FOCUS_MODE_FIXED[] = "fixed";
 
 static const char* portrait = "portrait";
 static const char* landscape = "landscape";
@@ -91,7 +188,7 @@
 
 void CameraParameters::set(const char *key, const char *value)
 {
-    // XXX i think i can do this with strspn() 
+    // XXX i think i can do this with strspn()
     if (strchr(key, '=') || strchr(key, ';')) {
         //XXX LOGE("Key \"%s\"contains invalid character (= or ;)", key);
         return;
@@ -150,7 +247,7 @@
 {
     char str[32];
     sprintf(str, "%dx%d", width, height);
-    set("preview-size", str);
+    set(KEY_PREVIEW_SIZE, str);
 }
 
 void CameraParameters::getPreviewSize(int *width, int *height) const
@@ -159,7 +256,7 @@
     *height = -1;
 
     // Get the current string, if it doesn't exist, leave the -1x-1
-    const char *p = get("preview-size");
+    const char *p = get(KEY_PREVIEW_SIZE);
     if (p == 0)
         return;
 
@@ -172,17 +269,17 @@
 
 void CameraParameters::setPreviewFrameRate(int fps)
 {
-    set("preview-frame-rate", fps);
+    set(KEY_PREVIEW_FRAME_RATE, fps);
 }
 
 int CameraParameters::getPreviewFrameRate() const
 {
-    return getInt("preview-frame-rate");
+    return getInt(KEY_PREVIEW_FRAME_RATE);
 }
 
 void CameraParameters::setPreviewFormat(const char *format)
 {
-    set("preview-format", format);
+    set(KEY_PREVIEW_FORMAT, format);
 }
 
 int CameraParameters::getOrientation() const
@@ -196,22 +293,22 @@
 void CameraParameters::setOrientation(int orientation)
 {
     if (orientation == CAMERA_ORIENTATION_PORTRAIT) {
-        set("preview-format", portrait);
+        set("orientation", portrait);
     } else {
-        set("preview-format", landscape);
+        set("orientation", landscape);
     }
 }
 
 const char *CameraParameters::getPreviewFormat() const
 {
-    return get("preview-format");
+    return get(KEY_PREVIEW_FORMAT);
 }
 
 void CameraParameters::setPictureSize(int width, int height)
 {
     char str[32];
     sprintf(str, "%dx%d", width, height);
-    set("picture-size", str);
+    set(KEY_PICTURE_SIZE, str);
 }
 
 void CameraParameters::getPictureSize(int *width, int *height) const
@@ -220,7 +317,7 @@
     *height = -1;
 
     // Get the current string, if it doesn't exist, leave the -1x-1
-    const char *p = get("picture-size");
+    const char *p = get(KEY_PICTURE_SIZE);
     if (p == 0)
         return;
 
@@ -233,12 +330,12 @@
 
 void CameraParameters::setPictureFormat(const char *format)
 {
-    set("picture-format", format);
+    set(KEY_PICTURE_FORMAT, format);
 }
 
 const char *CameraParameters::getPictureFormat() const
 {
-    return get("picture-format");
+    return get(KEY_PICTURE_FORMAT);
 }
 
 void CameraParameters::dump() const
diff --git a/libs/ui/EGLDisplaySurface.cpp b/libs/ui/EGLDisplaySurface.cpp
deleted file mode 100644
index d06c98b..0000000
--- a/libs/ui/EGLDisplaySurface.cpp
+++ /dev/null
@@ -1,519 +0,0 @@
-/*
- **
- ** 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
deleted file mode 100644
index f1071cf..0000000
--- a/libs/ui/EGLNativeWindowSurface.cpp
+++ /dev/null
@@ -1,161 +0,0 @@
-/* 
-**
-** 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/EGLUtils.cpp b/libs/ui/EGLUtils.cpp
new file mode 100644
index 0000000..1663313
--- /dev/null
+++ b/libs/ui/EGLUtils.cpp
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2009 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 "EGLUtils"
+
+#include <cutils/log.h>
+#include <utils/Errors.h>
+
+#include <ui/EGLUtils.h>
+
+#include <EGL/egl.h>
+
+#include <private/ui/android_natives_priv.h>
+
+// ----------------------------------------------------------------------------
+namespace android {
+// ----------------------------------------------------------------------------
+
+const char *EGLUtils::strerror(EGLint err)
+{
+    switch (err){
+        case EGL_SUCCESS:           return "EGL_SUCCESS";
+        case EGL_NOT_INITIALIZED:   return "EGL_NOT_INITIALIZED";
+        case EGL_BAD_ACCESS:        return "EGL_BAD_ACCESS";
+        case EGL_BAD_ALLOC:         return "EGL_BAD_ALLOC";
+        case EGL_BAD_ATTRIBUTE:     return "EGL_BAD_ATTRIBUTE";
+        case EGL_BAD_CONFIG:        return "EGL_BAD_CONFIG";
+        case EGL_BAD_CONTEXT:       return "EGL_BAD_CONTEXT";
+        case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE";
+        case EGL_BAD_DISPLAY:       return "EGL_BAD_DISPLAY";
+        case EGL_BAD_MATCH:         return "EGL_BAD_MATCH";
+        case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP";
+        case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW";
+        case EGL_BAD_PARAMETER:     return "EGL_BAD_PARAMETER";
+        case EGL_BAD_SURFACE:       return "EGL_BAD_SURFACE";
+        case EGL_CONTEXT_LOST:      return "EGL_CONTEXT_LOST";
+        default: return "UNKNOWN";
+    }
+}
+
+status_t EGLUtils::selectConfigForPixelFormat(
+        EGLDisplay dpy,
+        EGLint const* attrs,
+        PixelFormat format,
+        EGLConfig* outConfig)
+{
+    EGLint numConfigs = -1, n=0;
+
+    if (!attrs)
+        return BAD_VALUE;
+
+    if (outConfig == NULL)
+        return BAD_VALUE;
+    
+    int err;
+    PixelFormatInfo fbFormatInfo;
+    if ((err = getPixelFormatInfo(PixelFormat(format), &fbFormatInfo)) < 0) {
+        return err;
+    }
+
+    // Get all the "potential match" configs...
+    if (eglGetConfigs(dpy, NULL, 0, &numConfigs) == EGL_FALSE)
+        return BAD_VALUE;
+
+    EGLConfig* const configs = (EGLConfig*)malloc(sizeof(EGLConfig)*numConfigs);
+    if (eglChooseConfig(dpy, attrs, configs, numConfigs, &n) == EGL_FALSE) {
+        free(configs);
+        return BAD_VALUE;
+    }
+
+    const int fbSzA = fbFormatInfo.getSize(PixelFormatInfo::INDEX_ALPHA);
+    const int fbSzR = fbFormatInfo.getSize(PixelFormatInfo::INDEX_RED);
+    const int fbSzG = fbFormatInfo.getSize(PixelFormatInfo::INDEX_GREEN);
+    const int fbSzB = fbFormatInfo.getSize(PixelFormatInfo::INDEX_BLUE); 
+    
+    int i;
+    EGLConfig config = NULL;
+    for (i=0 ; i<n ; i++) {
+        EGLint r,g,b,a;
+        EGLConfig curr = configs[i];
+        eglGetConfigAttrib(dpy, curr, EGL_RED_SIZE,   &r);
+        eglGetConfigAttrib(dpy, curr, EGL_GREEN_SIZE, &g);
+        eglGetConfigAttrib(dpy, curr, EGL_BLUE_SIZE,  &b);
+        eglGetConfigAttrib(dpy, curr, EGL_ALPHA_SIZE, &a);
+        if (fbSzA == a && fbSzR == r && fbSzG == g && fbSzB  == b) {
+            config = curr;
+            break;
+        }
+    }
+
+    free(configs);
+    
+    if (i<n) {
+        *outConfig = config;
+        return NO_ERROR;
+    }
+
+    return NAME_NOT_FOUND;
+}
+
+status_t EGLUtils::selectConfigForNativeWindow(
+        EGLDisplay dpy,
+        EGLint const* attrs,
+        EGLNativeWindowType window,
+        EGLConfig* outConfig)
+{
+    int err;
+    int format;
+    
+    if (!window)
+        return BAD_VALUE;
+    
+    if ((err = window->query(window, NATIVE_WINDOW_FORMAT, &format)) < 0) {
+        return err;
+    }
+
+    return selectConfigForPixelFormat(dpy, attrs, format, outConfig);
+}
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+// ----------------------------------------------------------------------------
diff --git a/libs/ui/EventHub.cpp b/libs/ui/EventHub.cpp
index 7c2fc8e..e39a357 100644
--- a/libs/ui/EventHub.cpp
+++ b/libs/ui/EventHub.cpp
@@ -16,13 +16,14 @@
 //#define LOG_NDEBUG 0
 
 #include <ui/EventHub.h>
+#include <ui/KeycodeLabels.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 <utils/threads.h>
+#include <utils/Errors.h>
 
 #include <stdlib.h>
 #include <stdio.h>
@@ -58,6 +59,18 @@
 #define SEQ_SHIFT 16
 #define id_to_index(id)         ((id&ID_MASK)+1)
 
+#ifndef ABS_MT_TOUCH_MAJOR
+#define ABS_MT_TOUCH_MAJOR      0x30    /* Major axis of touching ellipse */
+#endif
+
+#ifndef ABS_MT_POSITION_X
+#define ABS_MT_POSITION_X       0x35    /* Center X ellipse position */
+#endif
+
+#ifndef ABS_MT_POSITION_Y
+#define ABS_MT_POSITION_Y       0x36    /* Center Y ellipse position */
+#endif
+
 namespace android {
 
 static const char *WAKE_LOCK_ID = "KeyEvents";
@@ -69,8 +82,8 @@
     return (v1 > v2) ? v1 : v2;
 }
 
-EventHub::device_t::device_t(int32_t _id, const char* _path)
-    : id(_id), path(_path), classes(0)
+EventHub::device_t::device_t(int32_t _id, const char* _path, const char* name)
+    : id(_id), path(_path), name(name), classes(0)
     , keyBitmask(NULL), layoutMap(new KeyLayoutMap()), next(NULL) {
 }
 
@@ -83,7 +96,7 @@
     : mError(NO_INIT), mHaveFirstKeyboard(false), mFirstKeyboardId(0)
     , mDevicesById(0), mNumDevicesById(0)
     , mOpeningDevices(0), mClosingDevices(0)
-    , mDevices(0), mFDs(0), mFDCount(0)
+    , mDevices(0), mFDs(0), mFDCount(0), mOpened(false)
 {
     acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
 #ifdef EV_SW
@@ -100,11 +113,6 @@
     // we should free stuff here...
 }
 
-void EventHub::onFirstRef()
-{
-    mError = openPlatformInput() ? NO_ERROR : UNKNOWN_ERROR;
-}
-
 status_t EventHub::errorCheck() const
 {
     return mError;
@@ -239,6 +247,41 @@
     return 0;
 }
 
+status_t EventHub::scancodeToKeycode(int32_t deviceId, int scancode,
+        int32_t* outKeycode, uint32_t* outFlags) const
+{
+    AutoMutex _l(mLock);
+    device_t* device = getDevice(deviceId);
+    
+    if (device != NULL && device->layoutMap != NULL) {
+        status_t err = device->layoutMap->map(scancode, outKeycode, outFlags);
+        if (err == NO_ERROR) {
+            return NO_ERROR;
+        }
+    }
+    
+    if (mHaveFirstKeyboard) {
+        device = getDevice(mFirstKeyboardId);
+        
+        if (device != NULL && device->layoutMap != NULL) {
+            status_t err = device->layoutMap->map(scancode, outKeycode, outFlags);
+            if (err == NO_ERROR) {
+                return NO_ERROR;
+            }
+        }
+    }
+    
+    *outKeycode = 0;
+    *outFlags = 0;
+    return NAME_NOT_FOUND;
+}
+
+void EventHub::addExcludedDevice(const char* deviceName)
+{
+    String8 name(deviceName);
+    mExcludedDevices.push_back(name);
+}
+
 EventHub::device_t* EventHub::getDevice(int32_t deviceId) const
 {
     if (deviceId == 0) deviceId = mFirstKeyboardId;
@@ -276,7 +319,12 @@
 
     // Note that we only allow one caller to getEvent(), so don't need
     // to do locking here...  only when adding/removing devices.
-    
+
+    if (!mOpened) {
+        mError = openPlatformInput() ? NO_ERROR : UNKNOWN_ERROR;
+        mOpened = true;
+    }
+
     while(1) {
 
         // First, report any devices that had last been added/removed.
@@ -474,6 +522,20 @@
         //fprintf(stderr, "could not get device name for %s, %s\n", deviceName, strerror(errno));
         name[0] = '\0';
     }
+
+    // check to see if the device is on our excluded list
+    List<String8>::iterator iter = mExcludedDevices.begin();
+    List<String8>::iterator end = mExcludedDevices.end();
+    for ( ; iter != end; iter++) {
+        const char* test = *iter;
+        if (strcmp(name, test) == 0) {
+            LOGI("ignoring event id %s driver %s\n", deviceName, test);
+            close(fd);
+            fd = -1;
+            return -1;
+        }
+    }
+
     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';
@@ -531,7 +593,7 @@
         version >> 16, (version >> 8) & 0xff, version & 0xff);
 #endif
 
-    device_t* device = new device_t(devid|mDevicesById[devid].seq, deviceName);
+    device_t* device = new device_t(devid|mDevicesById[devid].seq, deviceName, name);
     if (device == NULL) {
         LOGE("out of memory");
         return -1;
@@ -541,6 +603,8 @@
     mFDs[mFDCount].events = POLLIN;
 
     // figure out the kinds of events the device reports
+    
+    // See if this is a keyboard, and classify it.
     uint8_t key_bitmask[(KEY_MAX+1)/8];
     memset(key_bitmask, 0, sizeof(key_bitmask));
     LOGV("Getting keys...");
@@ -552,15 +616,11 @@
         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];
+            device->keyBitmask = new uint8_t[sizeof(key_bitmask)];
             if (device->keyBitmask != NULL) {
                 memcpy(device->keyBitmask, key_bitmask, sizeof(key_bitmask));
             } else {
@@ -570,6 +630,8 @@
             }
         }
     }
+    
+    // See if this is a trackball.
     if (test_bit(BTN_MOUSE, key_bitmask)) {
         uint8_t rel_bitmask[(REL_MAX+1)/8];
         memset(rel_bitmask, 0, sizeof(rel_bitmask));
@@ -581,16 +643,22 @@
             }
         }
     }
-    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;
-            }
-        }
+    
+    uint8_t abs_bitmask[(ABS_MAX+1)/8];
+    memset(abs_bitmask, 0, sizeof(abs_bitmask));
+    LOGV("Getting absolute controllers...");
+    ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(abs_bitmask)), abs_bitmask);
+    
+    // Is this a new modern multi-touch driver?
+    if (test_bit(ABS_MT_TOUCH_MAJOR, abs_bitmask)
+            && test_bit(ABS_MT_POSITION_X, abs_bitmask)
+            && test_bit(ABS_MT_POSITION_Y, abs_bitmask)) {
+        device->classes |= CLASS_TOUCHSCREEN | CLASS_TOUCHSCREEN_MT;
+        
+    // Is this an old style single-touch driver?
+    } else if (test_bit(BTN_TOUCH, key_bitmask)
+            && test_bit(ABS_X, abs_bitmask) && test_bit(ABS_Y, abs_bitmask)) {
+        device->classes |= CLASS_TOUCHSCREEN;
     }
 
 #ifdef EV_SW
@@ -609,21 +677,15 @@
     }
 #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 tmpfn[sizeof(name)];
         char keylayoutFilename[300];
 
         // a more descriptive name
-        ioctl(mFDs[mFDCount].fd, EVIOCGNAME(sizeof(devname)-1), devname);
-        devname[sizeof(devname)-1] = 0;
-        device->name = devname;
+        device->name = name;
 
         // replace all the spaces with underscores
-        strcpy(tmpfn, devname);
+        strcpy(tmpfn, name);
         for (char *p = strchr(tmpfn, ' '); p && *p; p = strchr(tmpfn, ' '))
             *p = '_';
 
@@ -656,12 +718,29 @@
         }
         char propName[100];
         sprintf(propName, "hw.keyboards.%u.devname", publicID);
-        property_set(propName, devname);
+        property_set(propName, name);
 
-        LOGI("New keyboard: publicID=%d device->id=%d devname='%s' propName='%s' keylayout='%s'\n",
-                publicID, device->id, devname, propName, keylayoutFilename);
+        // 'Q' key support = cheap test of whether this is an alpha-capable kbd
+        if (hasKeycode(device, kKeyCodeQ)) {
+            device->classes |= CLASS_ALPHAKEY;
+        }
+        
+        // See if this has a DPAD.
+        if (hasKeycode(device, kKeyCodeDpadUp) &&
+                hasKeycode(device, kKeyCodeDpadDown) &&
+                hasKeycode(device, kKeyCodeDpadLeft) &&
+                hasKeycode(device, kKeyCodeDpadRight) &&
+                hasKeycode(device, kKeyCodeDpadCenter)) {
+            device->classes |= CLASS_DPAD;
+        }
+        
+        LOGI("New keyboard: publicID=%d device->id=0x%x devname='%s' propName='%s' keylayout='%s'\n",
+                publicID, device->id, name, propName, keylayoutFilename);
     }
 
+    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);
+         
     LOGV("Adding device %s %p at %d, id = %d, classes = 0x%x\n",
          deviceName, device, mFDCount, devid, device->classes);
 
@@ -674,6 +753,25 @@
     return 0;
 }
 
+bool EventHub::hasKeycode(device_t* device, int keycode) const
+{
+    if (device->keyBitmask == NULL || device->layoutMap == NULL) {
+        return false;
+    }
+    
+    Vector<int32_t> scanCodes;
+    device->layoutMap->findScancodes(keycode, &scanCodes);
+    const size_t N = scanCodes.size();
+    for (size_t i=0; i<N && i<=KEY_MAX; i++) {
+        int32_t sc = scanCodes.itemAt(i);
+        if (sc >= 0 && sc <= KEY_MAX && test_bit(sc, device->keyBitmask)) {
+            return true;
+        }
+    }
+    
+    return false;
+}
+
 int EventHub::close_device(const char *deviceName)
 {
     AutoMutex _l(mLock);
@@ -683,11 +781,21 @@
         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;
+            
+            LOGI("Removed device: path=%s name=%s id=0x%x (of 0x%x) index=%d fd=%d classes=0x%x\n",
+                 device->path.string(), device->name.string(), device->id,
+                 mNumDevicesById, mFDCount, mFDs[i].fd, device->classes);
+         
+            // Clear this device's entry.
             int index = (device->id&ID_MASK);
             mDevicesById[index].device = NULL;
+            
+            // Close the file descriptor and compact the fd array.
+            close(mFDs[i].fd);
+            int count = mFDCount - i - 1;
             memmove(mDevices + i, mDevices + i + 1, sizeof(mDevices[0]) * count);
             memmove(mFDs + i, mFDs + i + 1, sizeof(mFDs[0]) * count);
+            mFDCount--;
 
 #ifdef EV_SW
             for (int j=0; j<EV_SW; j++) {
@@ -700,8 +808,6 @@
             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",
@@ -718,7 +824,7 @@
             return 0;
         }
     }
-    LOGE("remote device: %s not found\n", deviceName);
+    LOGE("remove device: %s not found\n", deviceName);
     return -1;
 }
 
@@ -733,6 +839,7 @@
     int event_pos = 0;
     struct inotify_event *event;
 
+    LOGV("EventHub::read_notify nfd: %d\n", nfd);
     res = read(nfd, event_buf, sizeof(event_buf));
     if(res < (int)sizeof(*event)) {
         if(errno == EINTR)
diff --git a/libs/ui/FramebufferNativeWindow.cpp b/libs/ui/FramebufferNativeWindow.cpp
new file mode 100644
index 0000000..0efba9c
--- /dev/null
+++ b/libs/ui/FramebufferNativeWindow.cpp
@@ -0,0 +1,279 @@
+/* 
+**
+** 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 "FramebufferNativeWindow"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include <cutils/log.h>
+#include <cutils/atomic.h>
+#include <utils/threads.h>
+#include <utils/RefBase.h>
+
+#include <ui/SurfaceComposerClient.h>
+#include <ui/Rect.h>
+#include <ui/FramebufferNativeWindow.h>
+
+#include <EGL/egl.h>
+
+#include <pixelflinger/format.h>
+#include <pixelflinger/pixelflinger.h>
+
+#include <hardware/hardware.h>
+#include <hardware/gralloc.h>
+
+#include <private/ui/android_natives_priv.h>
+
+// ----------------------------------------------------------------------------
+namespace android {
+// ----------------------------------------------------------------------------
+
+class NativeBuffer 
+    : public EGLNativeBase<
+        android_native_buffer_t, 
+        NativeBuffer, 
+        LightRefBase<NativeBuffer> >
+{
+public:
+    NativeBuffer(int w, int h, int f, int u) : BASE() {
+        android_native_buffer_t::width  = w;
+        android_native_buffer_t::height = h;
+        android_native_buffer_t::format = f;
+        android_native_buffer_t::usage  = u;
+    }
+private:
+    friend class LightRefBase<NativeBuffer>;    
+    ~NativeBuffer() { }; // this class cannot be overloaded
+};
+
+
+/*
+ * This implements the (main) framebuffer management. This class is used
+ * mostly by SurfaceFlinger, but also by command line GL application.
+ * 
+ * In fact this is an implementation of android_native_window_t on top of
+ * the framebuffer.
+ * 
+ * Currently it is pretty simple, it manages only two buffers (the front and 
+ * back buffer).
+ * 
+ */
+
+FramebufferNativeWindow::FramebufferNativeWindow() 
+    : BASE(), fbDev(0), grDev(0), mUpdateOnDemand(false)
+{
+    hw_module_t const* module;
+    if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) {
+        int stride;
+        int err;
+        err = framebuffer_open(module, &fbDev);
+        LOGE_IF(err, "couldn't open framebuffer HAL (%s)", strerror(-err));
+        
+        err = gralloc_open(module, &grDev);
+        LOGE_IF(err, "couldn't open gralloc HAL (%s)", strerror(-err));
+
+        // bail out if we can't initialize the modules
+        if (!fbDev || !grDev)
+            return;
+        
+        mUpdateOnDemand = (fbDev->setUpdateRect != 0);
+        
+        // initialize the buffer FIFO
+        mNumBuffers = 2;
+        mNumFreeBuffers = 2;
+        mBufferHead = mNumBuffers-1;
+        buffers[0] = new NativeBuffer(
+                fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB);
+        buffers[1] = new NativeBuffer(
+                fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB);
+        
+        err = grDev->alloc(grDev,
+                fbDev->width, fbDev->height, fbDev->format, 
+                GRALLOC_USAGE_HW_FB, &buffers[0]->handle, &buffers[0]->stride);
+
+        LOGE_IF(err, "fb buffer 0 allocation failed w=%d, h=%d, err=%s",
+                fbDev->width, fbDev->height, strerror(-err));
+
+        err = grDev->alloc(grDev,
+                fbDev->width, fbDev->height, fbDev->format, 
+                GRALLOC_USAGE_HW_FB, &buffers[1]->handle, &buffers[1]->stride);
+
+        LOGE_IF(err, "fb buffer 1 allocation failed w=%d, h=%d, err=%s",
+                fbDev->width, fbDev->height, strerror(-err));
+
+        LOGE("xDpi %d", fbDev->xdpi);
+        LOGE("yDpi %d", fbDev->ydpi);
+        const_cast<uint32_t&>(android_native_window_t::flags) = fbDev->flags; 
+        const_cast<float&>(android_native_window_t::xdpi) = fbDev->xdpi;
+        const_cast<float&>(android_native_window_t::ydpi) = fbDev->ydpi;
+        const_cast<int&>(android_native_window_t::minSwapInterval) = 
+            fbDev->minSwapInterval;
+        const_cast<int&>(android_native_window_t::maxSwapInterval) = 
+            fbDev->maxSwapInterval;
+    } else {
+        LOGE("Couldn't get gralloc module");
+    }
+
+    android_native_window_t::setSwapInterval = setSwapInterval;
+    android_native_window_t::dequeueBuffer = dequeueBuffer;
+    android_native_window_t::lockBuffer = lockBuffer;
+    android_native_window_t::queueBuffer = queueBuffer;
+    android_native_window_t::query = query;
+    android_native_window_t::perform = perform;
+}
+
+FramebufferNativeWindow::~FramebufferNativeWindow() 
+{
+    if (grDev) {
+        if (buffers[0] != NULL)
+            grDev->free(grDev, buffers[0]->handle);
+        if (buffers[1] != NULL)
+            grDev->free(grDev, buffers[1]->handle);
+        gralloc_close(grDev);
+    }
+
+    if (fbDev) {
+        framebuffer_close(fbDev);
+    }
+}
+
+status_t FramebufferNativeWindow::setUpdateRectangle(const Rect& r) 
+{
+    if (!mUpdateOnDemand) {
+        return INVALID_OPERATION;
+    }
+    return fbDev->setUpdateRect(fbDev, r.left, r.top, r.width(), r.height());
+}
+
+status_t FramebufferNativeWindow::compositionComplete()
+{
+    if (fbDev->compositionComplete) {
+        return fbDev->compositionComplete(fbDev);
+    }
+    return INVALID_OPERATION;
+}
+
+int FramebufferNativeWindow::setSwapInterval(
+        android_native_window_t* window, int interval) 
+{
+    framebuffer_device_t* fb = getSelf(window)->fbDev;
+    return fb->setSwapInterval(fb, interval);
+}
+
+int FramebufferNativeWindow::dequeueBuffer(android_native_window_t* window, 
+        android_native_buffer_t** buffer)
+{
+    FramebufferNativeWindow* self = getSelf(window);
+    Mutex::Autolock _l(self->mutex);
+    framebuffer_device_t* fb = self->fbDev;
+
+    // wait for a free buffer
+    while (!self->mNumFreeBuffers) {
+        self->mCondition.wait(self->mutex);
+    }
+    // get this buffer
+    self->mNumFreeBuffers--;
+    int index = self->mBufferHead++;
+    if (self->mBufferHead >= self->mNumBuffers)
+        self->mBufferHead = 0;
+
+    *buffer = self->buffers[index].get();
+
+    return 0;
+}
+
+int FramebufferNativeWindow::lockBuffer(android_native_window_t* window, 
+        android_native_buffer_t* buffer)
+{
+    FramebufferNativeWindow* self = getSelf(window);
+    Mutex::Autolock _l(self->mutex);
+
+    // wait that the buffer we're locking is not front anymore
+    while (self->front == buffer) {
+        self->mCondition.wait(self->mutex);
+    }
+
+    return NO_ERROR;
+}
+
+int FramebufferNativeWindow::queueBuffer(android_native_window_t* window, 
+        android_native_buffer_t* buffer)
+{
+    FramebufferNativeWindow* self = getSelf(window);
+    Mutex::Autolock _l(self->mutex);
+    framebuffer_device_t* fb = self->fbDev;
+    buffer_handle_t handle = static_cast<NativeBuffer*>(buffer)->handle;
+    int res = fb->post(fb, handle);
+    self->front = static_cast<NativeBuffer*>(buffer);
+    self->mNumFreeBuffers++;
+    self->mCondition.broadcast();
+    return res;
+}
+
+int FramebufferNativeWindow::query(android_native_window_t* window,
+        int what, int* value) 
+{
+    FramebufferNativeWindow* self = getSelf(window);
+    Mutex::Autolock _l(self->mutex);
+    framebuffer_device_t* fb = self->fbDev;
+    switch (what) {
+        case NATIVE_WINDOW_WIDTH:
+            *value = fb->width;
+            return NO_ERROR;
+        case NATIVE_WINDOW_HEIGHT:
+            *value = fb->height;
+            return NO_ERROR;
+        case NATIVE_WINDOW_FORMAT:
+            *value = fb->format;
+            return NO_ERROR;
+    }
+    *value = 0;
+    return BAD_VALUE;
+}
+
+int FramebufferNativeWindow::perform(android_native_window_t* window,
+        int operation, ...)
+{
+    switch (operation) {
+        case NATIVE_WINDOW_SET_USAGE:
+            break;
+        default:
+            return NAME_NOT_FOUND;
+    }
+    return NO_ERROR;
+}
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+// ----------------------------------------------------------------------------
+
+using namespace android;
+
+EGLNativeWindowType android_createDisplaySurface(void)
+{
+    FramebufferNativeWindow* w;
+    w = new FramebufferNativeWindow();
+    if (w->getDevice() == NULL) {
+        // get a ref so it can be destroyed when we exit this block
+        sp<FramebufferNativeWindow> ref(w);
+        return NULL;
+    }
+    return (EGLNativeWindowType)w;
+}
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
new file mode 100644
index 0000000..6a5c8a9
--- /dev/null
+++ b/libs/ui/GraphicBuffer.cpp
@@ -0,0 +1,239 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <binder/Parcel.h>
+
+#include <utils/Errors.h>
+#include <utils/Log.h>
+
+#include <ui/GraphicBuffer.h>
+#include <ui/GraphicBufferAllocator.h>
+#include <ui/GraphicBufferMapper.h>
+#include <ui/PixelFormat.h>
+
+#include <pixelflinger/pixelflinger.h>
+
+namespace android {
+
+// ===========================================================================
+// Buffer and implementation of android_native_buffer_t
+// ===========================================================================
+
+GraphicBuffer::GraphicBuffer()
+    : BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()),
+      mInitCheck(NO_ERROR),  mVStride(0), mIndex(-1)
+{
+    width  = 
+    height = 
+    stride = 
+    format = 
+    usage  = 0;
+    handle = NULL;
+}
+
+GraphicBuffer::GraphicBuffer(uint32_t w, uint32_t h, 
+        PixelFormat reqFormat, uint32_t reqUsage)
+    : BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()),
+      mInitCheck(NO_ERROR),  mVStride(0), mIndex(-1)
+{
+    width  = 
+    height = 
+    stride = 
+    format = 
+    usage  = 0;
+    handle = NULL;
+    mInitCheck = initSize(w, h, reqFormat, reqUsage);
+}
+
+GraphicBuffer::GraphicBuffer(uint32_t w, uint32_t h,
+        PixelFormat inFormat, uint32_t inUsage,
+        uint32_t inStride, native_handle_t* inHandle, bool keepOwnership)
+    : BASE(), mOwner(keepOwnership ? ownHandle : ownNone),
+      mBufferMapper(GraphicBufferMapper::get()),
+      mInitCheck(NO_ERROR),  mVStride(0), mIndex(-1)
+{
+    width  = w;
+    height = h;
+    stride = inStride;
+    format = inFormat;
+    usage  = inUsage;
+    handle = inHandle;
+}
+
+GraphicBuffer::GraphicBuffer(const Parcel& data) 
+    : BASE(), mOwner(ownHandle), mBufferMapper(GraphicBufferMapper::get()),
+      mInitCheck(NO_ERROR),  mVStride(0), mIndex(-1)
+{
+    // we own the handle in this case
+    width  = data.readInt32();
+    if (width < 0) {
+        width = height = stride = format = usage = 0;
+        handle = 0;
+    } else {
+        height = data.readInt32();
+        stride = data.readInt32();
+        format = data.readInt32();
+        usage  = data.readInt32();
+        handle = data.readNativeHandle();
+    }
+}
+
+GraphicBuffer::~GraphicBuffer()
+{
+    if (handle) {
+        if (mOwner == ownHandle) {
+            native_handle_close(handle);
+            native_handle_delete(const_cast<native_handle*>(handle));
+        } else if (mOwner == ownData) {
+            GraphicBufferAllocator& allocator(GraphicBufferAllocator::get());
+            allocator.free(handle);
+        }
+    }
+}
+
+status_t GraphicBuffer::initCheck() const {
+    return mInitCheck;
+}
+
+android_native_buffer_t* GraphicBuffer::getNativeBuffer() const
+{
+    return static_cast<android_native_buffer_t*>(
+            const_cast<GraphicBuffer*>(this));
+}
+
+status_t GraphicBuffer::reallocate(uint32_t w, uint32_t h, PixelFormat f,
+        uint32_t reqUsage)
+{
+    if (mOwner != ownData)
+        return INVALID_OPERATION;
+
+    if (handle) {
+        GraphicBufferAllocator& allocator(GraphicBufferAllocator::get());
+        allocator.free(handle);
+        handle = 0;
+    }
+    return initSize(w, h, f, reqUsage);
+}
+
+status_t GraphicBuffer::initSize(uint32_t w, uint32_t h, PixelFormat format,
+        uint32_t reqUsage)
+{
+    if (format == PIXEL_FORMAT_RGBX_8888)
+        format = PIXEL_FORMAT_RGBA_8888;
+
+    GraphicBufferAllocator& allocator = GraphicBufferAllocator::get();
+    status_t err = allocator.alloc(w, h, format, reqUsage, &handle, &stride);
+    if (err == NO_ERROR) {
+        this->width  = w;
+        this->height = h;
+        this->format = format;
+        this->usage  = reqUsage;
+        mVStride = 0;
+    }
+    return err;
+}
+
+status_t GraphicBuffer::lock(uint32_t usage, void** vaddr)
+{
+    const Rect lockBounds(width, height);
+    status_t res = lock(usage, lockBounds, vaddr);
+    return res;
+}
+
+status_t GraphicBuffer::lock(uint32_t usage, const Rect& rect, void** vaddr)
+{
+    if (rect.left < 0 || rect.right  > this->width || 
+        rect.top  < 0 || rect.bottom > this->height) {
+        LOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)",
+                rect.left, rect.top, rect.right, rect.bottom, 
+                this->width, this->height);
+        return BAD_VALUE;
+    }
+    status_t res = getBufferMapper().lock(handle, usage, rect, vaddr);
+    return res;
+}
+
+status_t GraphicBuffer::unlock()
+{
+    status_t res = getBufferMapper().unlock(handle);
+    return res;
+}
+
+status_t GraphicBuffer::lock(GGLSurface* sur, uint32_t usage) 
+{
+    void* vaddr;
+    status_t res = GraphicBuffer::lock(usage, &vaddr);
+    if (res == NO_ERROR && sur) {
+        sur->version = sizeof(GGLSurface);
+        sur->width = width;
+        sur->height = height;
+        sur->stride = stride;
+        sur->format = format;
+        sur->vstride = mVStride;
+        sur->data = static_cast<GGLubyte*>(vaddr);
+    }
+    return res;
+}
+
+
+status_t GraphicBuffer::writeToParcel(Parcel* reply, 
+        android_native_buffer_t const* buffer)
+{
+    if (buffer == NULL)
+        return BAD_VALUE;
+
+    if (buffer->width < 0 || buffer->height < 0)
+        return BAD_VALUE;
+
+    status_t err = NO_ERROR;
+    if (buffer->handle == NULL) {
+        // this buffer doesn't have a handle
+        reply->writeInt32(NO_MEMORY);
+    } else {
+        reply->writeInt32(buffer->width);
+        reply->writeInt32(buffer->height);
+        reply->writeInt32(buffer->stride);
+        reply->writeInt32(buffer->format);
+        reply->writeInt32(buffer->usage);
+        err = reply->writeNativeHandle(buffer->handle);
+    }
+    return err;
+}
+
+
+void GraphicBuffer::setIndex(int index) {
+    mIndex = index;
+}
+
+int GraphicBuffer::getIndex() const {
+    return mIndex;
+}
+
+void GraphicBuffer::setVerticalStride(uint32_t vstride) {
+    mVStride = vstride;
+}
+
+uint32_t GraphicBuffer::getVerticalStride() const {
+    return mVStride;
+}
+
+// ---------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/libs/ui/GraphicBufferAllocator.cpp b/libs/ui/GraphicBufferAllocator.cpp
new file mode 100644
index 0000000..57d5fc3
--- /dev/null
+++ b/libs/ui/GraphicBufferAllocator.cpp
@@ -0,0 +1,141 @@
+/* 
+**
+** Copyright 2009, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License"); 
+** you may not use this file except in compliance with the License. 
+** You may obtain a copy of the License at 
+**
+**     http://www.apache.org/licenses/LICENSE-2.0 
+**
+** Unless required by applicable law or agreed to in writing, software 
+** distributed under the License is distributed on an "AS IS" BASIS, 
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+** See the License for the specific language governing permissions and 
+** limitations under the License.
+*/
+
+#include <cutils/log.h>
+
+#include <utils/Singleton.h>
+#include <utils/String8.h>
+
+#include <ui/GraphicBufferAllocator.h>
+
+#include <private/ui/sw_gralloc_handle.h>
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+ANDROID_SINGLETON_STATIC_INSTANCE( GraphicBufferAllocator )
+
+Mutex GraphicBufferAllocator::sLock;
+KeyedVector<buffer_handle_t,
+    GraphicBufferAllocator::alloc_rec_t> GraphicBufferAllocator::sAllocList;
+
+GraphicBufferAllocator::GraphicBufferAllocator()
+    : mAllocDev(0)
+{
+    hw_module_t const* module;
+    int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
+    LOGE_IF(err, "FATAL: can't find the %s module", GRALLOC_HARDWARE_MODULE_ID);
+    if (err == 0) {
+        gralloc_open(module, &mAllocDev);
+    }
+}
+
+GraphicBufferAllocator::~GraphicBufferAllocator()
+{
+    gralloc_close(mAllocDev);
+}
+
+void GraphicBufferAllocator::dump(String8& result) const
+{
+    Mutex::Autolock _l(sLock);
+    KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList);
+    size_t total = 0;
+    const size_t SIZE = 512;
+    char buffer[SIZE];
+    snprintf(buffer, SIZE, "Allocated buffers:\n");
+    result.append(buffer);
+    const size_t c = list.size();
+    for (size_t i=0 ; i<c ; i++) {
+        const alloc_rec_t& rec(list.valueAt(i));
+        snprintf(buffer, SIZE, "%10p: %7.2f KiB | %4u x %4u | %2d | 0x%08x\n",
+            list.keyAt(i), rec.size/1024.0f, 
+            rec.w, rec.h, rec.format, rec.usage);
+        result.append(buffer);
+        total += rec.size;
+    }
+    snprintf(buffer, SIZE, "Total allocated: %.2f KB\n", total/1024.0f);
+    result.append(buffer);
+}
+
+static inline uint32_t clamp(uint32_t c) {
+    return c>0 ? c : 1;
+}
+
+status_t GraphicBufferAllocator::alloc(uint32_t w, uint32_t h, PixelFormat format,
+        int usage, buffer_handle_t* handle, int32_t* stride)
+{
+    Mutex::Autolock _l(mLock);
+
+    // make sure to not allocate a 0 x 0 buffer
+    w = clamp(w);
+    h = clamp(h);
+
+    // we have a h/w allocator and h/w buffer is requested
+    status_t err; 
+    
+    if (usage & GRALLOC_USAGE_HW_MASK) {
+        err = mAllocDev->alloc(mAllocDev, w, h, format, usage, handle, stride);
+    } else {
+        err = sw_gralloc_handle_t::alloc(w, h, format, usage, handle, stride);
+    }
+
+    LOGW_IF(err, "alloc(%u, %u, %d, %08x, ...) failed %d (%s)",
+            w, h, format, usage, err, strerror(-err));
+    
+    if (err == NO_ERROR) {
+        Mutex::Autolock _l(sLock);
+        KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList);
+        alloc_rec_t rec;
+        rec.w = w;
+        rec.h = h;
+        rec.format = format;
+        rec.usage = usage;
+        rec.vaddr = 0;
+        rec.size = h * stride[0] * bytesPerPixel(format);
+        list.add(*handle, rec);
+    } else {
+        String8 s;
+        dump(s);
+        LOGD("%s", s.string());
+    }
+
+    return err;
+}
+
+status_t GraphicBufferAllocator::free(buffer_handle_t handle)
+{
+    Mutex::Autolock _l(mLock);
+
+    status_t err;
+    if (sw_gralloc_handle_t::validate(handle) < 0) {
+        err = mAllocDev->free(mAllocDev, handle);
+    } else {
+        err = sw_gralloc_handle_t::free((sw_gralloc_handle_t*)handle);
+    }
+
+    LOGW_IF(err, "free(...) failed %d (%s)", err, strerror(-err));
+    if (err == NO_ERROR) {
+        Mutex::Autolock _l(sLock);
+        KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList);
+        list.removeItem(handle);
+    }
+
+    return err;
+}
+
+// ---------------------------------------------------------------------------
+}; // namespace android
diff --git a/libs/ui/GraphicBufferMapper.cpp b/libs/ui/GraphicBufferMapper.cpp
new file mode 100644
index 0000000..ce2acd0
--- /dev/null
+++ b/libs/ui/GraphicBufferMapper.cpp
@@ -0,0 +1,228 @@
+/*
+ * 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 "GraphicBufferMapper"
+
+#include <stdint.h>
+#ifdef HAVE_ANDROID_OS      // just want PAGE_SIZE define
+# include <asm/page.h>
+#else
+# include <sys/user.h>
+#endif
+#include <errno.h>
+#include <sys/mman.h>
+
+#include <cutils/ashmem.h>
+
+#include <utils/Errors.h>
+#include <utils/Log.h>
+
+#include <ui/GraphicBufferMapper.h>
+#include <ui/Rect.h>
+
+#include <hardware/gralloc.h>
+
+#include <private/ui/sw_gralloc_handle.h>
+
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+ANDROID_SINGLETON_STATIC_INSTANCE( GraphicBufferMapper )
+
+GraphicBufferMapper::GraphicBufferMapper()
+    : mAllocMod(0)
+{
+    hw_module_t const* module;
+    int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
+    LOGE_IF(err, "FATAL: can't find the %s module", GRALLOC_HARDWARE_MODULE_ID);
+    if (err == 0) {
+        mAllocMod = (gralloc_module_t const *)module;
+    }
+}
+
+status_t GraphicBufferMapper::registerBuffer(buffer_handle_t handle)
+{
+    status_t err;
+    if (sw_gralloc_handle_t::validate(handle) < 0) {
+        err = mAllocMod->registerBuffer(mAllocMod, handle);
+    } else {
+        err = sw_gralloc_handle_t::registerBuffer((sw_gralloc_handle_t*)handle);
+    }
+    LOGW_IF(err, "registerBuffer(%p) failed %d (%s)",
+            handle, err, strerror(-err));
+    return err;
+}
+
+status_t GraphicBufferMapper::unregisterBuffer(buffer_handle_t handle)
+{
+    status_t err;
+    if (sw_gralloc_handle_t::validate(handle) < 0) {
+        err = mAllocMod->unregisterBuffer(mAllocMod, handle);
+    } else {
+        err = sw_gralloc_handle_t::unregisterBuffer((sw_gralloc_handle_t*)handle);
+    }
+    LOGW_IF(err, "unregisterBuffer(%p) failed %d (%s)",
+            handle, err, strerror(-err));
+    return err;
+}
+
+status_t GraphicBufferMapper::lock(buffer_handle_t handle, 
+        int usage, const Rect& bounds, void** vaddr)
+{
+    status_t err;
+    if (sw_gralloc_handle_t::validate(handle) < 0) {
+        err = mAllocMod->lock(mAllocMod, handle, usage,
+                bounds.left, bounds.top, bounds.width(), bounds.height(),
+                vaddr);
+    } else {
+        err = sw_gralloc_handle_t::lock((sw_gralloc_handle_t*)handle, usage,
+                bounds.left, bounds.top, bounds.width(), bounds.height(),
+                vaddr);
+    }
+    LOGW_IF(err, "lock(...) failed %d (%s)", err, strerror(-err));
+    return err;
+}
+
+status_t GraphicBufferMapper::unlock(buffer_handle_t handle)
+{
+    status_t err;
+    if (sw_gralloc_handle_t::validate(handle) < 0) {
+        err = mAllocMod->unlock(mAllocMod, handle);
+    } else {
+        err = sw_gralloc_handle_t::unlock((sw_gralloc_handle_t*)handle);
+    }
+    LOGW_IF(err, "unlock(...) failed %d (%s)", err, strerror(-err));
+    return err;
+}
+
+// ---------------------------------------------------------------------------
+
+status_t sw_gralloc_handle_t::alloc(uint32_t w, uint32_t h, int format,
+        int usage, buffer_handle_t* pHandle, int32_t* pStride)
+{
+    int align = 4;
+    int bpp = 0;
+    switch (format) {
+        case HAL_PIXEL_FORMAT_RGBA_8888:
+        case HAL_PIXEL_FORMAT_RGBX_8888:
+        case HAL_PIXEL_FORMAT_BGRA_8888:
+            bpp = 4;
+            break;
+        case HAL_PIXEL_FORMAT_RGB_888:
+            bpp = 3;
+            break;
+        case HAL_PIXEL_FORMAT_RGB_565:
+        case HAL_PIXEL_FORMAT_RGBA_5551:
+        case HAL_PIXEL_FORMAT_RGBA_4444:
+            bpp = 2;
+            break;
+        default:
+            return -EINVAL;
+    }
+    size_t bpr = (w*bpp + (align-1)) & ~(align-1);
+    size_t size = bpr * h;
+    size_t stride = bpr / bpp;
+    size = (size + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1);
+    
+    int fd = ashmem_create_region("sw-gralloc-buffer", size);
+    if (fd < 0) {
+        LOGE("ashmem_create_region(size=%d) failed (%s)",
+                size, strerror(-errno));
+        return -errno;
+    }
+    
+    int prot = PROT_READ;
+    if (usage & GRALLOC_USAGE_SW_WRITE_MASK)
+        prot |= PROT_WRITE;
+    
+    if (ashmem_set_prot_region(fd, prot) < 0) {
+        LOGE("ashmem_set_prot_region(fd=%d, prot=%x) failed (%s)",
+                fd, prot, strerror(-errno));
+        close(fd);
+        return -errno;
+    }
+
+    void* base = mmap(0, size, prot, MAP_SHARED, fd, 0);
+    if (base == MAP_FAILED) {
+        LOGE("alloc mmap(fd=%d, size=%d, prot=%x) failed (%s)",
+                fd, size, prot, strerror(-errno));
+        close(fd);
+        return -errno;
+    }
+
+    sw_gralloc_handle_t* hnd = new sw_gralloc_handle_t();
+    hnd->fd = fd;
+    hnd->size = size;
+    hnd->base = intptr_t(base);
+    hnd->prot = prot;
+    *pStride = stride;
+    *pHandle = hnd; 
+    
+    return NO_ERROR;
+}
+
+status_t sw_gralloc_handle_t::free(sw_gralloc_handle_t* hnd)
+{
+    if (hnd->base) {
+        munmap((void*)hnd->base, hnd->size);
+    }
+    if (hnd->fd >= 0) {
+        close(hnd->fd);
+    }
+    delete hnd;    
+    return NO_ERROR;
+}
+
+status_t sw_gralloc_handle_t::registerBuffer(sw_gralloc_handle_t* hnd)
+{
+    if (hnd->pid != getpid()) {
+        void* base = mmap(0, hnd->size, hnd->prot, MAP_SHARED, hnd->fd, 0);
+        if (base == MAP_FAILED) {
+            LOGE("registerBuffer mmap(fd=%d, size=%d, prot=%x) failed (%s)",
+                    hnd->fd, hnd->size, hnd->prot, strerror(-errno));
+            return -errno;
+        }
+        hnd->base = intptr_t(base);
+    }
+    return NO_ERROR;
+}
+
+status_t sw_gralloc_handle_t::unregisterBuffer(sw_gralloc_handle_t* hnd)
+{
+    if (hnd->pid != getpid()) {
+        if (hnd->base) {
+            munmap((void*)hnd->base, hnd->size);
+        }
+        hnd->base = 0;
+    }
+    return NO_ERROR;
+}
+
+status_t sw_gralloc_handle_t::lock(sw_gralloc_handle_t* hnd, int usage,
+        int l, int t, int w, int h, void** vaddr)
+{
+    *vaddr = (void*)hnd->base;
+    return NO_ERROR;
+}
+
+status_t sw_gralloc_handle_t::unlock(sw_gralloc_handle_t* hnd)
+{
+    return NO_ERROR;
+}
+
+// ---------------------------------------------------------------------------
+}; // namespace android
diff --git a/libs/ui/ICamera.cpp b/libs/ui/ICamera.cpp
index ab0fef1..e1b3ec7 100644
--- a/libs/ui/ICamera.cpp
+++ b/libs/ui/ICamera.cpp
@@ -20,7 +20,7 @@
 #include <utils/Log.h>
 #include <stdint.h>
 #include <sys/types.h>
-#include <utils/Parcel.h>
+#include <binder/Parcel.h>
 #include <ui/ICamera.h>
 
 namespace android {
@@ -32,9 +32,11 @@
     START_PREVIEW,
     STOP_PREVIEW,
     AUTO_FOCUS,
+    CANCEL_AUTO_FOCUS,
     TAKE_PICTURE,
     SET_PARAMETERS,
     GET_PARAMETERS,
+    SEND_COMMAND,
     CONNECT,
     LOCK,
     UNLOCK,
@@ -162,6 +164,17 @@
         return ret;
     }
 
+    // cancel focus
+    status_t cancelAutoFocus()
+    {
+        LOGV("cancelAutoFocus");
+        Parcel data, reply;
+        data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
+        remote()->transact(CANCEL_AUTO_FOCUS, data, &reply);
+        status_t ret = reply.readInt32();
+        return ret;
+    }
+
     // take a picture - returns an IMemory (ref-counted mmap)
     status_t takePicture()
     {
@@ -193,6 +206,17 @@
         remote()->transact(GET_PARAMETERS, data, &reply);
         return reply.readString8();
     }
+    virtual status_t sendCommand(int32_t cmd, int32_t arg1, int32_t arg2)
+    {
+        LOGD("sendCommand");
+        Parcel data, reply;
+        data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
+        data.writeInt32(cmd);
+        data.writeInt32(arg1);
+        data.writeInt32(arg2);
+        remote()->transact(SEND_COMMAND, data, &reply);
+        return reply.readInt32();
+    }
     virtual status_t connect(const sp<ICameraClient>& cameraClient)
     {
         Parcel data, reply;
@@ -221,12 +245,6 @@
 
 // ----------------------------------------------------------------------
 
-#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)
 {
@@ -300,6 +318,12 @@
             reply->writeInt32(autoFocus());
             return NO_ERROR;
         } break;
+        case CANCEL_AUTO_FOCUS: {
+            LOGV("CANCEL_AUTO_FOCUS");
+            CHECK_INTERFACE(ICamera, data, reply);
+            reply->writeInt32(cancelAutoFocus());
+            return NO_ERROR;
+        } break;
         case TAKE_PICTURE: {
             LOGV("TAKE_PICTURE");
             CHECK_INTERFACE(ICamera, data, reply);
@@ -319,6 +343,15 @@
              reply->writeString8(getParameters());
             return NO_ERROR;
          } break;
+        case SEND_COMMAND: {
+            LOGD("SEND_COMMAND");
+            CHECK_INTERFACE(ICamera, data, reply);
+            int command = data.readInt32();
+            int arg1 = data.readInt32();
+            int arg2 = data.readInt32();
+            reply->writeInt32(sendCommand(command, arg1, arg2));
+            return NO_ERROR;
+         } break;
         case CONNECT: {
             CHECK_INTERFACE(ICamera, data, reply);
             sp<ICameraClient> cameraClient = interface_cast<ICameraClient>(data.readStrongBinder());
diff --git a/libs/ui/ICameraClient.cpp b/libs/ui/ICameraClient.cpp
index 59a6cf2..42b4da4 100644
--- a/libs/ui/ICameraClient.cpp
+++ b/libs/ui/ICameraClient.cpp
@@ -78,12 +78,6 @@
 
 // ----------------------------------------------------------------------
 
-#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)
 {
diff --git a/libs/ui/ICameraService.cpp b/libs/ui/ICameraService.cpp
index e5687fe..84986c6 100644
--- a/libs/ui/ICameraService.cpp
+++ b/libs/ui/ICameraService.cpp
@@ -18,9 +18,9 @@
 #include <stdint.h>
 #include <sys/types.h>
 
-#include <utils/Parcel.h>
-#include <utils/IPCThreadState.h>
-#include <utils/IServiceManager.h>
+#include <binder/Parcel.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
 
 #include <ui/ICameraService.h>
 
@@ -49,12 +49,6 @@
 
 // ----------------------------------------------------------------------
 
-#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)
 {
diff --git a/libs/ui/IOverlay.cpp b/libs/ui/IOverlay.cpp
index fed47c2..65e6b4f 100644
--- a/libs/ui/IOverlay.cpp
+++ b/libs/ui/IOverlay.cpp
@@ -18,8 +18,8 @@
 #include <stdint.h>
 #include <sys/types.h>
 
-#include <utils/Parcel.h>
-#include <utils/IInterface.h>
+#include <binder/Parcel.h>
+#include <binder/IInterface.h>
 
 #include <ui/IOverlay.h>
 
@@ -49,12 +49,6 @@
 
 // ----------------------------------------------------------------------
 
-#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)
 {
diff --git a/libs/ui/ISurface.cpp b/libs/ui/ISurface.cpp
index d5e9f81..4fb38ed 100644
--- a/libs/ui/ISurface.cpp
+++ b/libs/ui/ISurface.cpp
@@ -14,19 +14,25 @@
  * limitations under the License.
  */
 
+#define LOG_TAG "ISurface"
+
 #include <stdio.h>
 #include <stdint.h>
 #include <sys/types.h>
 
-#include <utils/Parcel.h>
-#include <utils/IMemory.h>
+#include <binder/Parcel.h>
+#include <binder/IMemory.h>
 
 #include <ui/ISurface.h>
 #include <ui/Overlay.h>
+#include <ui/Surface.h>
 
+#include <ui/GraphicBuffer.h>
 
 namespace android {
 
+// ----------------------------------------------------------------------
+
 ISurface::BufferHeap::BufferHeap() 
     : w(0), h(0), hor_stride(0), ver_stride(0), format(0),
     transform(0), flags(0) 
@@ -55,6 +61,8 @@
 {     
 }
 
+// ----------------------------------------------------------------------
+
 class BpSurface : public BpInterface<ISurface>
 {
 public:
@@ -63,6 +71,17 @@
     {
     }
 
+    virtual sp<GraphicBuffer> requestBuffer(int bufferIdx, int usage)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurface::getInterfaceDescriptor());
+        data.writeInt32(bufferIdx);
+        data.writeInt32(usage);
+        remote()->transact(REQUEST_BUFFER, data, &reply);
+        sp<GraphicBuffer> buffer = new GraphicBuffer(reply);
+        return buffer;
+    }
+
     virtual status_t registerBuffers(const BufferHeap& buffers)
     {
         Parcel data, reply;
@@ -112,16 +131,17 @@
 
 // ----------------------------------------------------------------------
 
-#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 REQUEST_BUFFER: {
+            CHECK_INTERFACE(ISurface, data, reply);
+            int bufferIdx = data.readInt32();
+            int usage = data.readInt32();
+            sp<GraphicBuffer> buffer(requestBuffer(bufferIdx, usage));
+            return GraphicBuffer::writeToParcel(reply, buffer.get());
+        }
         case REGISTER_BUFFERS: {
             CHECK_INTERFACE(ISurface, data, reply);
             BufferHeap buffer;
diff --git a/libs/ui/ISurfaceComposer.cpp b/libs/ui/ISurfaceComposer.cpp
index 76597e1..fd2a590 100644
--- a/libs/ui/ISurfaceComposer.cpp
+++ b/libs/ui/ISurfaceComposer.cpp
@@ -20,10 +20,10 @@
 #include <stdint.h>
 #include <sys/types.h>
 
-#include <utils/Parcel.h>
-#include <utils/IMemory.h>
-#include <utils/IPCThreadState.h>
-#include <utils/IServiceManager.h>
+#include <binder/Parcel.h>
+#include <binder/IMemory.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
 
 #include <ui/ISurfaceComposer.h>
 #include <ui/DisplayInfo.h>
@@ -54,12 +54,12 @@
         return interface_cast<ISurfaceFlingerClient>(reply.readStrongBinder());
     }
 
-    virtual sp<IMemory> getCblk() const
+    virtual sp<IMemoryHeap> getCblk() const
     {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
         remote()->transact(BnSurfaceComposer::GET_CBLK, data, &reply);
-        return interface_cast<IMemory>(reply.readStrongBinder());
+        return interface_cast<IMemoryHeap>(reply.readStrongBinder());
     }
 
     virtual void openGlobalTransaction()
@@ -114,36 +114,6 @@
         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;
@@ -156,124 +126,61 @@
 
 // ----------------------------------------------------------------------
 
-#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: {
+            CHECK_INTERFACE(ISurfaceComposer, data, reply);
             sp<IBinder> b = createConnection()->asBinder();
             reply->writeStrongBinder(b);
         } break;
         case OPEN_GLOBAL_TRANSACTION: {
+            CHECK_INTERFACE(ISurfaceComposer, data, reply);
             openGlobalTransaction();
         } break;
         case CLOSE_GLOBAL_TRANSACTION: {
+            CHECK_INTERFACE(ISurfaceComposer, data, reply);
             closeGlobalTransaction();
         } break;
         case SET_ORIENTATION: {
+            CHECK_INTERFACE(ISurfaceComposer, data, reply);
             DisplayID dpy = data.readInt32();
             int orientation = data.readInt32();
             uint32_t flags = data.readInt32();
             reply->writeInt32( setOrientation(dpy, orientation, flags) );
         } break;
         case FREEZE_DISPLAY: {
+            CHECK_INTERFACE(ISurfaceComposer, data, reply);
             DisplayID dpy = data.readInt32();
             uint32_t flags = data.readInt32();
             reply->writeInt32( freezeDisplay(dpy, flags) );
         } break;
         case UNFREEZE_DISPLAY: {
+            CHECK_INTERFACE(ISurfaceComposer, data, reply);
             DisplayID dpy = data.readInt32();
             uint32_t flags = data.readInt32();
             reply->writeInt32( unfreezeDisplay(dpy, flags) );
         } break;
         case BOOT_FINISHED: {
+            CHECK_INTERFACE(ISurfaceComposer, data, reply);
             bootFinished();
         } break;
-        case REVOKE_GPU: {
-            reply->writeInt32( revokeGPU() );
-        } break;
         case SIGNAL: {
+            CHECK_INTERFACE(ISurfaceComposer, data, reply);
             signal();
         } break;
         case GET_CBLK: {
+            CHECK_INTERFACE(ISurfaceComposer, data, reply);
             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 BBinder::onTransact(code, data, reply, flags);
     }
     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
index dab5f71..4a6a1d7 100644
--- a/libs/ui/ISurfaceFlingerClient.cpp
+++ b/libs/ui/ISurfaceFlingerClient.cpp
@@ -21,10 +21,10 @@
 #include <stdint.h>
 #include <sys/types.h>
 
-#include <utils/Parcel.h>
-#include <utils/IMemory.h>
-#include <utils/IPCThreadState.h>
-#include <utils/IServiceManager.h>
+#include <binder/Parcel.h>
+#include <binder/IMemory.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
 
 #include <ui/ISurface.h>
 #include <ui/ISurfaceFlingerClient.h>
@@ -64,12 +64,12 @@
     {
     }
 
-    virtual void getControlBlocks(sp<IMemory>* ctl) const
+    virtual sp<IMemoryHeap> getControlBlock() const
     {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceFlingerClient::getInterfaceDescriptor());
         remote()->transact(GET_CBLK, data, &reply);
-        *ctl  = interface_cast<IMemory>(reply.readStrongBinder());
+        return interface_cast<IMemoryHeap>(reply.readStrongBinder());
     }
 
     virtual sp<ISurface> createSurface( surface_data_t* params,
@@ -118,12 +118,6 @@
 
 // ----------------------------------------------------------------------
 
-#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)
 {
@@ -132,8 +126,7 @@
     switch(code) {
         case GET_CBLK: {
             CHECK_INTERFACE(ISurfaceFlingerClient, data, reply);
-            sp<IMemory> ctl;
-            getControlBlocks(&ctl);
+            sp<IMemoryHeap> ctl(getControlBlock());
             reply->writeStrongBinder(ctl->asBinder());
             return NO_ERROR;
         } break;
@@ -196,10 +189,11 @@
 
 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());
+    token    = parcel.readInt32();
+    identity = parcel.readInt32();
+    width    = parcel.readInt32();
+    height   = parcel.readInt32();
+    format   = parcel.readInt32();
     return NO_ERROR;
 }
 
@@ -207,8 +201,9 @@
 {
     parcel->writeInt32(token);
     parcel->writeInt32(identity);
-    parcel->writeStrongBinder(heap[0]!=0 ? heap[0]->asBinder() : NULL);
-    parcel->writeStrongBinder(heap[1]!=0 ? heap[1]->asBinder() : NULL);
+    parcel->writeInt32(width);
+    parcel->writeInt32(height);
+    parcel->writeInt32(format);
     return NO_ERROR;
 }
 
diff --git a/libs/ui/LayerState.cpp b/libs/ui/LayerState.cpp
index 0b6374b..a53ffb7 100644
--- a/libs/ui/LayerState.cpp
+++ b/libs/ui/LayerState.cpp
@@ -15,7 +15,7 @@
  */
 
 #include <utils/Errors.h>
-#include <utils/Parcel.h>
+#include <binder/Parcel.h>
 #include <private/ui/LayerState.h>
 
 namespace android {
diff --git a/libs/ui/Overlay.cpp b/libs/ui/Overlay.cpp
index 59c6514..3aa8950 100644
--- a/libs/ui/Overlay.cpp
+++ b/libs/ui/Overlay.cpp
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-#include <utils/IMemory.h>
-#include <utils/Parcel.h>
+#include <binder/IMemory.h>
+#include <binder/Parcel.h>
 #include <utils/Errors.h>
-#include <utils/MemoryHeapBase.h>
+#include <binder/MemoryHeapBase.h>
 
 #include <ui/IOverlay.h>
 #include <ui/Overlay.h>
@@ -59,6 +59,30 @@
     return mOverlayData->queueBuffer(mOverlayData, buffer);
 }
 
+status_t Overlay::resizeInput(uint32_t width, uint32_t height)
+{
+    if (mStatus != NO_ERROR) return mStatus;
+    return mOverlayData->resizeInput(mOverlayData, width, height);
+}
+
+status_t Overlay::setParameter(int param, int value)
+{
+    if (mStatus != NO_ERROR) return mStatus;
+    return mOverlayData->setParameter(mOverlayData, param, value);
+}
+
+status_t Overlay::setCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h)
+{
+    if (mStatus != NO_ERROR) return mStatus;
+    return mOverlayData->setCrop(mOverlayData, x, y, w, h);
+}
+
+status_t Overlay::getCrop(uint32_t* x, uint32_t* y, uint32_t* w, uint32_t* h)
+{
+    if (mStatus != NO_ERROR) return mStatus;
+    return mOverlayData->getCrop(mOverlayData, x, y, w, h);
+}
+
 int32_t Overlay::getBufferCount() const
 {
     if (mStatus != NO_ERROR) return mStatus;
@@ -73,6 +97,15 @@
 
 void Overlay::destroy() {  
     if (mStatus != NO_ERROR) return;
+
+    // Must delete the objects in reverse creation order, thus the
+    //  data side must be closed first and then the destroy send to
+    //  the control side.
+    if (mOverlayData) {
+        overlay_data_close(mOverlayData);
+        mOverlayData = NULL;
+    }
+
     mOverlayRef->mOverlayChannel->destroy();
 }
 
diff --git a/libs/ui/Region.cpp b/libs/ui/Region.cpp
index 26e694a..d21ed57 100644
--- a/libs/ui/Region.cpp
+++ b/libs/ui/Region.cpp
@@ -16,295 +16,661 @@
 
 #define LOG_TAG "Region"
 
-#include <stdio.h>
-#include <utils/Atomic.h>
-#include <utils/Debug.h>
+#include <limits.h>
+
+#include <utils/Log.h>
 #include <utils/String8.h>
+
+#include <ui/Rect.h>
 #include <ui/Region.h>
+#include <ui/Point.h>
+
+#include <private/ui/RegionHelper.h>
+
+// ----------------------------------------------------------------------------
+#define VALIDATE_REGIONS        (false)
+#define VALIDATE_WITH_CORECG    (false)
+// ----------------------------------------------------------------------------
+
+#if VALIDATE_WITH_CORECG
+#include <core/SkRegion.h>
+#endif
 
 namespace android {
+// ----------------------------------------------------------------------------
+
+enum {
+    op_nand = region_operator<Rect>::op_nand,
+    op_and  = region_operator<Rect>::op_and,
+    op_or   = region_operator<Rect>::op_or,
+    op_xor  = region_operator<Rect>::op_xor
+};
 
 // ----------------------------------------------------------------------------
 
 Region::Region()
+    : mBounds(0,0)
 {
 }
 
 Region::Region(const Region& rhs)
-    : mRegion(rhs.mRegion)
+    : mBounds(rhs.mBounds), mStorage(rhs.mStorage)
 {
 }
 
-Region::Region(const SkRegion& rhs)
-    : mRegion(rhs)
+Region::Region(const Rect& rhs)
+    : mBounds(rhs)
 {
 }
 
+Region::Region(const Parcel& parcel)
+{
+    status_t err = read(parcel);
+    LOGE_IF(err<0, "error %s reading Region from parcel", strerror(err));
+}
+
+Region::Region(const void* buffer)
+{
+    status_t err = read(buffer);
+    LOGE_IF(err<0, "error %s reading Region from parcel", strerror(err));
+}
+
 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;
+#if VALIDATE_REGIONS
+    validate(rhs, "operator=");
+#endif
+    mBounds = rhs.mBounds;
+    mStorage = rhs.mStorage;
     return *this;
 }
 
-const SkRegion& Region::toSkRegion() const
+Region& Region::makeBoundsSelf()
 {
-    return mRegion;
-}
-
-Rect Region::bounds() const
-{
-    const SkIRect& b(mRegion.getBounds());
-    return Rect(b.fLeft, b.fTop, b.fRight, b.fBottom);
+    mStorage.clear();
+    return *this;
 }
 
 void Region::clear()
 {
-    mRegion.setEmpty();
+    mBounds.clear();
+    mStorage.clear();
 }
 
 void Region::set(const Rect& r)
 {
-    SkIRect ir;
-    ir.set(r.left, r.top, r.right, r.bottom);
-    mRegion.setRect(ir);
+    mBounds = r;
+    mStorage.clear();
+}
+
+void Region::set(uint32_t w, uint32_t h)
+{
+    mBounds = Rect(int(w), int(h));
+    mStorage.clear();
 }
 
 // ----------------------------------------------------------------------------
 
-Region& Region::orSelf(const Rect& r)
+void Region::addRectUnchecked(int l, int t, int r, int b)
 {
-    SkIRect ir;
-    ir.set(r.left, r.top, r.right, r.bottom);
-    mRegion.op(ir, SkRegion::kUnion_Op);
-    return *this;
+    mStorage.add(Rect(l,t,r,b));
+#if VALIDATE_REGIONS
+    validate(*this, "addRectUnchecked");
+#endif
 }
 
-Region& Region::andSelf(const Rect& r)
-{
-    SkIRect ir;
-    ir.set(r.left, r.top, r.right, r.bottom);
-    mRegion.op(ir, SkRegion::kIntersect_Op);
+// ----------------------------------------------------------------------------
+
+Region& Region::orSelf(const Rect& r) {
+    return operationSelf(r, op_or);
+}
+Region& Region::andSelf(const Rect& r) {
+    return operationSelf(r, op_and);
+}
+Region& Region::subtractSelf(const Rect& r) {
+    return operationSelf(r, op_nand);
+}
+Region& Region::operationSelf(const Rect& r, int op) {
+    Region lhs(*this);
+    boolean_operation(op, *this, lhs, r);
     return *this;
 }
 
 // ----------------------------------------------------------------------------
 
 Region& Region::orSelf(const Region& rhs) {
-    mRegion.op(rhs.mRegion, SkRegion::kUnion_Op);
-    return *this;
+    return operationSelf(rhs, op_or);
 }
-
 Region& Region::andSelf(const Region& rhs) {
-    mRegion.op(rhs.mRegion, SkRegion::kIntersect_Op);
-    return *this;
+    return operationSelf(rhs, op_and);
 }
-
 Region& Region::subtractSelf(const Region& rhs) {
-    mRegion.op(rhs.mRegion, SkRegion::kDifference_Op);
+    return operationSelf(rhs, op_nand);
+}
+Region& Region::operationSelf(const Region& rhs, int op) {
+    Region lhs(*this);
+    boolean_operation(op, *this, lhs, rhs);
     return *this;
 }
 
 Region& Region::translateSelf(int x, int y) {
-    if (x|y) mRegion.translate(x, y);
+    if (x|y) translate(*this, x, y);
     return *this;
 }
 
-Region Region::merge(const Region& rhs) const {
+// ----------------------------------------------------------------------------
+
+const Region Region::merge(const Rect& rhs) const {
+    return operation(rhs, op_or);
+}
+const Region Region::intersect(const Rect& rhs) const {
+    return operation(rhs, op_and);
+}
+const Region Region::subtract(const Rect& rhs) const {
+    return operation(rhs, op_nand);
+}
+const Region Region::operation(const Rect& rhs, int op) const {
     Region result;
-    result.mRegion.op(mRegion, rhs.mRegion, SkRegion::kUnion_Op);
+    boolean_operation(op, result, *this, rhs);
     return result;
 }
 
-Region Region::intersect(const Region& rhs) const {
+// ----------------------------------------------------------------------------
+
+const Region Region::merge(const Region& rhs) const {
+    return operation(rhs, op_or);
+}
+const Region Region::intersect(const Region& rhs) const {
+    return operation(rhs, op_and);
+}
+const Region Region::subtract(const Region& rhs) const {
+    return operation(rhs, op_nand);
+}
+const Region Region::operation(const Region& rhs, int op) const {
     Region result;
-    result.mRegion.op(mRegion, rhs.mRegion, SkRegion::kIntersect_Op);
+    boolean_operation(op, result, *this, rhs);
     return result;
 }
 
-Region Region::subtract(const Region& rhs) const {
+const Region Region::translate(int x, int y) 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);
+    translate(result, *this, x, y);
     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;
+    return operationSelf(rhs, dx, dy, op_or);
 }
-
 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;
+    return operationSelf(rhs, dx, dy, op_and);
 }
-
 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 operationSelf(rhs, dx, dy, op_nand);
+}
+Region& Region::operationSelf(const Region& rhs, int dx, int dy, int op) {
+    Region lhs(*this);
+    boolean_operation(op, *this, lhs, rhs, dx, dy);
     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;
+const Region Region::merge(const Region& rhs, int dx, int dy) const {
+    return operation(rhs, dx, dy, op_or);
 }
-
-Region Region::subtract(const Region& rhs, int dx, int dy) const {
+const Region Region::intersect(const Region& rhs, int dx, int dy) const {
+    return operation(rhs, dx, dy, op_and);
+}
+const Region Region::subtract(const Region& rhs, int dx, int dy) const {
+    return operation(rhs, dx, dy, op_nand);
+}
+const Region Region::operation(const Region& rhs, int dx, int dy, int op) const {
     Region result;
-    SkRegion r(rhs.mRegion);
-    r.translate(dx, dy);
-    result.mRegion.op(mRegion, r, SkRegion::kDifference_Op);
+    boolean_operation(op, result, *this, rhs, dx, dy);
     return result;
 }
 
 // ----------------------------------------------------------------------------
 
-Region::iterator::iterator(const Region& r)
-    : mIt(r.mRegion)
+// This is our region rasterizer, which merges rects and spans together
+// to obtain an optimal region.
+class Region::rasterizer : public region_operator<Rect>::region_rasterizer 
 {
+    Rect& bounds;
+    Vector<Rect>& storage;
+    Rect* head;
+    Rect* tail;
+    Vector<Rect> span;
+    Rect* cur;
+public:
+    rasterizer(Region& reg) 
+        : bounds(reg.mBounds), storage(reg.mStorage), head(), tail(), cur() {
+        bounds.top = bounds.bottom = 0;
+        bounds.left   = INT_MAX;
+        bounds.right  = INT_MIN;
+        storage.clear();
+    }
+
+    ~rasterizer() {
+        if (span.size()) {
+            flushSpan();
+        }
+        if (storage.size()) {
+            bounds.top = storage.itemAt(0).top;
+            bounds.bottom = storage.top().bottom;
+            if (storage.size() == 1) {
+                storage.clear();
+            }
+        } else {
+            bounds.left  = 0;
+            bounds.right = 0;
+        }
+    }
+    
+    virtual void operator()(const Rect& rect) {
+        //LOGD(">>> %3d, %3d, %3d, %3d", 
+        //        rect.left, rect.top, rect.right, rect.bottom);
+        if (span.size()) {
+            if (cur->top != rect.top) {
+                flushSpan();
+            } else if (cur->right == rect.left) {
+                cur->right = rect.right;
+                return;
+            }
+        }
+        span.add(rect);
+        cur = span.editArray() + (span.size() - 1);
+    }
+private:
+    template<typename T> 
+    static inline T min(T rhs, T lhs) { return rhs < lhs ? rhs : lhs; }
+    template<typename T> 
+    static inline T max(T rhs, T lhs) { return rhs > lhs ? rhs : lhs; }
+    void flushSpan() {
+        bool merge = false;
+        if (tail-head == ssize_t(span.size())) {
+            Rect const* p = cur;
+            Rect const* q = head;
+            if (p->top == q->bottom) {
+                merge = true;
+                while (q != tail) {
+                    if ((p->left != q->left) || (p->right != q->right)) {
+                        merge = false;
+                        break;
+                    }
+                    p++, q++;
+                }
+            }
+        }
+        if (merge) {
+            const int bottom = span[0].bottom;
+            Rect* r = head;
+            while (r != tail) {
+                r->bottom = bottom;
+                r++;
+            }
+        } else {
+            bounds.left = min(span.itemAt(0).left, bounds.left);
+            bounds.right = max(span.top().right, bounds.right);
+            storage.appendVector(span);
+            tail = storage.editArray() + storage.size();
+            head = tail - span.size();
+        }
+        span.clear();
+    }
+};
+
+bool Region::validate(const Region& reg, const char* name)
+{
+    bool result = true;
+    const_iterator cur = reg.begin();
+    const_iterator const tail = reg.end();
+    const_iterator prev = cur++;
+    Rect b(*prev);
+    while (cur != tail) {
+        b.left   = b.left   < cur->left   ? b.left   : cur->left;
+        b.top    = b.top    < cur->top    ? b.top    : cur->top;
+        b.right  = b.right  > cur->right  ? b.right  : cur->right;
+        b.bottom = b.bottom > cur->bottom ? b.bottom : cur->bottom;
+        if (cur->top == prev->top) {
+            if (cur->bottom != prev->bottom) {
+                LOGE("%s: invalid span %p", name, cur);
+                result = false;
+            } else if (cur->left < prev->right) {
+                LOGE("%s: spans overlap horizontally prev=%p, cur=%p",
+                        name, prev, cur);
+                result = false;
+            }
+        } else if (cur->top < prev->bottom) {
+            LOGE("%s: spans overlap vertically prev=%p, cur=%p",
+                    name, prev, cur);
+            result = false;
+        }
+        prev = cur;
+        cur++;
+    }
+    if (b != reg.getBounds()) {
+        result = false;
+        LOGE("%s: invalid bounds [%d,%d,%d,%d] vs. [%d,%d,%d,%d]", name,
+                b.left, b.top, b.right, b.bottom,
+                reg.getBounds().left, reg.getBounds().top, 
+                reg.getBounds().right, reg.getBounds().bottom);
+    }
+    if (result == false) {
+        reg.dump(name);
+    }
+    return result;
 }
 
-int Region::iterator::iterate(Rect* rect)
+void Region::boolean_operation(int op, Region& dst,
+        const Region& lhs,
+        const Region& rhs, int dx, int dy)
 {
-    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;
+    size_t lhs_count;
+    Rect const * const lhs_rects = lhs.getArray(&lhs_count);
+
+    size_t rhs_count;
+    Rect const * const rhs_rects = rhs.getArray(&rhs_count);
+
+    region_operator<Rect>::region lhs_region(lhs_rects, lhs_count);
+    region_operator<Rect>::region rhs_region(rhs_rects, rhs_count, dx, dy);
+    region_operator<Rect> operation(op, lhs_region, rhs_region);
+    { // scope for rasterizer (dtor has side effects)
+        rasterizer r(dst);
+        operation(r);
+    }
+
+#if VALIDATE_REGIONS
+    validate(lhs, "boolean_operation: lhs");
+    validate(rhs, "boolean_operation: rhs");
+    validate(dst, "boolean_operation: dst");
+#endif
+
+#if VALIDATE_WITH_CORECG
+    SkRegion sk_lhs;
+    SkRegion sk_rhs;
+    SkRegion sk_dst;
+    
+    for (size_t i=0 ; i<lhs_count ; i++)
+        sk_lhs.op(
+                lhs_rects[i].left   + dx,
+                lhs_rects[i].top    + dy,
+                lhs_rects[i].right  + dx,
+                lhs_rects[i].bottom + dy,
+                SkRegion::kUnion_Op);
+    
+    for (size_t i=0 ; i<rhs_count ; i++)
+        sk_rhs.op(
+                rhs_rects[i].left   + dx,
+                rhs_rects[i].top    + dy,
+                rhs_rects[i].right  + dx,
+                rhs_rects[i].bottom + dy,
+                SkRegion::kUnion_Op);
+ 
+    const char* name = "---";
+    SkRegion::Op sk_op;
+    switch (op) {
+        case op_or: sk_op = SkRegion::kUnion_Op; name="OR"; break;
+        case op_and: sk_op = SkRegion::kIntersect_Op; name="AND"; break;
+        case op_nand: sk_op = SkRegion::kDifference_Op; name="NAND"; break;
+    }
+    sk_dst.op(sk_lhs, sk_rhs, sk_op);
+
+    if (sk_dst.isEmpty() && dst.isEmpty())
+        return;
+    
+    bool same = true;
+    Region::const_iterator head = dst.begin();
+    Region::const_iterator const tail = dst.end();
+    SkRegion::Iterator it(sk_dst);
+    while (!it.done()) {
+        if (head != tail) {
+            if (
+                    head->left != it.rect().fLeft ||     
+                    head->top != it.rect().fTop ||     
+                    head->right != it.rect().fRight ||     
+                    head->bottom != it.rect().fBottom
+            ) {
+                same = false;
+                break;
+            }
+        } else {
+            same = false;
+            break;
+        }
+        head++;
+        it.next();
+    }
+    
+    if (head != tail) {
+        same = false;
+    }
+    
+    if(!same) {
+        LOGD("---\nregion boolean %s failed", name);
+        lhs.dump("lhs");
+        rhs.dump("rhs");
+        dst.dump("dst");
+        LOGD("should be");
+        SkRegion::Iterator it(sk_dst);
+        while (!it.done()) {
+            LOGD("    [%3d, %3d, %3d, %3d]",
+                it.rect().fLeft,
+                it.rect().fTop,
+                it.rect().fRight,
+                it.rect().fBottom);
+            it.next();
+        }
+    }
+#endif
+}
+
+void Region::boolean_operation(int op, Region& dst,
+        const Region& lhs,
+        const Rect& rhs, int dx, int dy)
+{
+#if VALIDATE_WITH_CORECG || VALIDATE_REGIONS
+    boolean_operation(op, dst, lhs, Region(rhs), dx, dy);
+#else
+    size_t lhs_count;
+    Rect const * const lhs_rects = lhs.getArray(&lhs_count);
+
+    region_operator<Rect>::region lhs_region(lhs_rects, lhs_count);
+    region_operator<Rect>::region rhs_region(&rhs, 1, dx, dy);
+    region_operator<Rect> operation(op, lhs_region, rhs_region);
+    { // scope for rasterizer (dtor has side effects)
+        rasterizer r(dst);
+        operation(r);
+    }
+
+#endif
+}
+
+void Region::boolean_operation(int op, Region& dst,
+        const Region& lhs, const Region& rhs)
+{
+    boolean_operation(op, dst, lhs, rhs, 0, 0);
+}
+
+void Region::boolean_operation(int op, Region& dst,
+        const Region& lhs, const Rect& rhs)
+{
+    boolean_operation(op, dst, lhs, rhs, 0, 0);
+}
+
+void Region::translate(Region& reg, int dx, int dy)
+{
+    if (!reg.isEmpty()) {
+#if VALIDATE_REGIONS
+        validate(reg, "translate (before)");
+#endif
+        reg.mBounds.translate(dx, dy);
+        size_t count = reg.mStorage.size();
+        Rect* rects = reg.mStorage.editArray();
+        while (count) {
+            rects->translate(dx, dy);
+            rects++;
+            count--;
+        }
+#if VALIDATE_REGIONS
+        validate(reg, "translate (after)");
+#endif
+    }
+}
+
+void Region::translate(Region& dst, const Region& reg, int dx, int dy)
+{
+    dst = reg;
+    translate(dst, dx, dy);
 }
 
 // ----------------------------------------------------------------------------
 
-// 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));
+#if VALIDATE_REGIONS
+    validate(*this, "write(Parcel)");
+#endif
+    status_t err;
+    const size_t count = mStorage.size();
+    const size_t sizeNeeded = sizeof(int32_t) + (1+count)*sizeof(Rect);
+    void* buffer = parcel.writeInplace(sizeNeeded);
+    if (!buffer) return NO_MEMORY;
+    ssize_t written = Region::write(buffer, sizeNeeded);
+    if (written < 0) return status_t(written);
     return NO_ERROR;
 }
 
 status_t Region::read(const Parcel& parcel)
 {
-    size_t size = parcel.readInt32();
-    mRegion.unflatten(parcel.readInplace(size));
+    void const* buffer = parcel.readInplace(sizeof(int32_t));
+    if (!buffer) return NO_MEMORY;
+    const size_t count = *static_cast<int32_t const *>(buffer);
+    void const* dummy = parcel.readInplace((1+count)*sizeof(Rect));
+    if (!dummy) return NO_MEMORY;
+    const size_t sizeNeeded = sizeof(int32_t) + (1+count)*sizeof(Rect);
+    const ssize_t read = Region::read(buffer);
+    if (read < 0) return status_t(read);
+#if VALIDATE_REGIONS
+    validate(*this, "read(Parcel)");
+#endif
     return NO_ERROR;
 }
 
 ssize_t Region::write(void* buffer, size_t size) const
 {
-    size_t sizeNeeded = mRegion.flatten(NULL);
+#if VALIDATE_REGIONS
+    validate(*this, "write(buffer)");
+#endif
+    const size_t count = mStorage.size();
+    const size_t sizeNeeded = sizeof(int32_t) + (1+count)*sizeof(Rect);
     if (sizeNeeded > size) return NO_MEMORY;
-    return mRegion.flatten(buffer);
+    int32_t* const p = static_cast<int32_t*>(buffer); 
+    *p = count;
+    memcpy(p+1, &mBounds, sizeof(Rect));
+    if (count) {
+        memcpy(p+5, mStorage.array(), count*sizeof(Rect));
+    }
+    return ssize_t(sizeNeeded);
 }
 
 ssize_t Region::read(const void* buffer)
 {
-    return mRegion.unflatten(buffer);
+    int32_t const* const p = static_cast<int32_t const*>(buffer); 
+    const size_t count = *p;
+    memcpy(&mBounds, p+1, sizeof(Rect));
+    mStorage.clear();
+    if (count) {
+        mStorage.insertAt(0, count);
+        memcpy(mStorage.editArray(), p+5, count*sizeof(Rect));
+    }
+#if VALIDATE_REGIONS
+    validate(*this, "read(buffer)");
+#endif
+    return ssize_t(sizeof(int32_t) + (1+count)*sizeof(Rect));
 }
 
 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;
+    const size_t sizeNeeded = sizeof(int32_t) + sizeof(Rect);
+    if (sizeNeeded > size) return NO_MEMORY;
+    int32_t* const p = static_cast<int32_t*>(buffer); 
+    memset(p, 0, sizeNeeded);
+    return ssize_t(sizeNeeded);
 }
 
 bool Region::isEmpty(void* buffer)
 {
-    // this needs to stay in sync with SkRegion
-    return *static_cast<int32_t*>(buffer) == -1;
+    int32_t const* const p = static_cast<int32_t const*>(buffer); 
+    Rect const* const b = reinterpret_cast<Rect const *>(p+1);
+    return b->isEmpty();
 }
 
-size_t Region::rects(Vector<Rect>& rectList) const
+// ----------------------------------------------------------------------------
+
+Region::const_iterator Region::begin() const {
+    return isRect() ? &mBounds : mStorage.array();
+}
+
+Region::const_iterator Region::end() const {
+    return isRect() ? ((&mBounds) + 1) : (mStorage.array() + mStorage.size());
+}
+
+Rect const* Region::getArray(size_t* count) const {
+    const_iterator const b(begin());
+    const_iterator const e(end());
+    if (count) *count = e-b;
+    return b;
+}
+
+size_t Region::getRects(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();
-        }
+    rectList = mStorage;
+    if (rectList.isEmpty()) {
+        rectList.clear();
+        rectList.add(mBounds);
     }
     return rectList.size();
 }
 
+// ----------------------------------------------------------------------------
+
 void Region::dump(String8& out, const char* what, uint32_t flags) const
 {
     (void)flags;
-    Vector<Rect> r;
-    rects(r);
-    
+    const_iterator head = begin();
+    const_iterator const tail = end();
+
     size_t SIZE = 256;
     char buffer[SIZE];
-    
-    snprintf(buffer, SIZE, "  Region %s (this=%p, count=%d)\n", what, this, r.size());
+
+    snprintf(buffer, SIZE, "  Region %s (this=%p, count=%d)\n",
+            what, this, tail-head);
     out.append(buffer);
-    for (size_t i=0 ; i<r.size() ; i++) {
+    while (head != tail) {
         snprintf(buffer, SIZE, "    [%3d, %3d, %3d, %3d]\n",
-            r[i].left, r[i].top,r[i].right,r[i].bottom);
+                head->left, head->top, head->right, head->bottom);
         out.append(buffer);
+        head++;
     }
 }
 
 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++) {
+    const_iterator head = begin();
+    const_iterator const tail = end();
+    LOGD("  Region %s (this=%p, count=%d)\n", what, this, tail-head);
+    while (head != tail) {
         LOGD("    [%3d, %3d, %3d, %3d]\n",
-            r[i].left, r[i].top,r[i].right,r[i].bottom);
+                head->left, head->top, head->right, head->bottom);
+        head++;
     }
 }
 
diff --git a/libs/ui/SharedBufferStack.cpp b/libs/ui/SharedBufferStack.cpp
new file mode 100644
index 0000000..46b6766
--- /dev/null
+++ b/libs/ui/SharedBufferStack.cpp
@@ -0,0 +1,424 @@
+/*
+ * 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 "SharedBufferStack"
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Debug.h>
+#include <utils/Log.h>
+#include <utils/threads.h>
+
+#include <private/ui/SharedBufferStack.h>
+
+#include <ui/Rect.h>
+#include <ui/Region.h>
+
+#define DEBUG_ATOMICS 0
+
+namespace android {
+// ----------------------------------------------------------------------------
+
+SharedClient::SharedClient()
+    : lock(Mutex::SHARED)
+{
+}
+
+SharedClient::~SharedClient() {
+}
+
+
+// these functions are used by the clients
+status_t SharedClient::validate(size_t i) const {
+    if (uint32_t(i) >= uint32_t(NUM_LAYERS_MAX))
+        return BAD_INDEX;
+    return surfaces[i].status;
+}
+
+uint32_t SharedClient::getIdentity(size_t token) const {
+    return uint32_t(surfaces[token].identity);
+}
+
+// ----------------------------------------------------------------------------
+
+
+SharedBufferStack::SharedBufferStack()
+{
+}
+
+void SharedBufferStack::init(int32_t i)
+{
+    inUse = -1;
+    status = NO_ERROR;
+    identity = i;
+}
+
+status_t SharedBufferStack::setDirtyRegion(int buffer, const Region& dirty)
+{
+    if (uint32_t(buffer) >= NUM_BUFFER_MAX)
+        return BAD_INDEX;
+
+    // in the current implementation we only send a single rectangle
+    const Rect bounds(dirty.getBounds());
+    FlatRegion& reg(dirtyRegion[buffer]);
+    reg.count = 1;
+    reg.rects[0] = uint16_t(bounds.left);
+    reg.rects[1] = uint16_t(bounds.top);
+    reg.rects[2] = uint16_t(bounds.right);
+    reg.rects[3] = uint16_t(bounds.bottom);
+    return NO_ERROR;
+}
+
+Region SharedBufferStack::getDirtyRegion(int buffer) const
+{
+    Region res;
+    if (uint32_t(buffer) >= NUM_BUFFER_MAX)
+        return res;
+
+    const FlatRegion& reg(dirtyRegion[buffer]);
+    res.set(Rect(reg.rects[0], reg.rects[1], reg.rects[2], reg.rects[3]));
+    return res;
+}
+
+// ----------------------------------------------------------------------------
+
+SharedBufferBase::SharedBufferBase(SharedClient* sharedClient,
+        int surface, int num, int32_t identity)
+    : mSharedClient(sharedClient), 
+      mSharedStack(sharedClient->surfaces + surface),
+      mNumBuffers(num), mIdentity(identity)
+{
+}
+
+SharedBufferBase::~SharedBufferBase()
+{
+}
+
+uint32_t SharedBufferBase::getIdentity()
+{
+    SharedBufferStack& stack( *mSharedStack );
+    return stack.identity;
+}
+
+status_t SharedBufferBase::getStatus() const
+{
+    SharedBufferStack& stack( *mSharedStack );
+    return stack.status;
+}
+
+size_t SharedBufferBase::getFrontBuffer() const
+{
+    SharedBufferStack& stack( *mSharedStack );
+    return size_t( stack.head );
+}
+
+String8 SharedBufferBase::dump(char const* prefix) const
+{
+    const size_t SIZE = 1024;
+    char buffer[SIZE];
+    String8 result;
+    SharedBufferStack& stack( *mSharedStack );
+    snprintf(buffer, SIZE, 
+            "%s[ head=%2d, available=%2d, queued=%2d ] "
+            "reallocMask=%08x, inUse=%2d, identity=%d, status=%d\n",
+            prefix, stack.head, stack.available, stack.queued, 
+            stack.reallocMask, stack.inUse, stack.identity, stack.status);
+    result.append(buffer);
+    return result;
+}
+
+// ============================================================================
+// conditions and updates
+// ============================================================================
+
+SharedBufferClient::DequeueCondition::DequeueCondition(
+        SharedBufferClient* sbc) : ConditionBase(sbc)  { 
+}
+bool SharedBufferClient::DequeueCondition::operator()() {
+    return stack.available > 0;
+}
+
+SharedBufferClient::LockCondition::LockCondition(
+        SharedBufferClient* sbc, int buf) : ConditionBase(sbc), buf(buf) { 
+}
+bool SharedBufferClient::LockCondition::operator()() {
+    return (buf != stack.head || 
+            (stack.queued > 0 && stack.inUse != buf));
+}
+
+SharedBufferServer::ReallocateCondition::ReallocateCondition(
+        SharedBufferBase* sbb, int buf) : ConditionBase(sbb), buf(buf) { 
+}
+bool SharedBufferServer::ReallocateCondition::operator()() {
+    // TODO: we should also check that buf has been dequeued
+    return (buf != stack.head);
+}
+
+// ----------------------------------------------------------------------------
+
+SharedBufferClient::QueueUpdate::QueueUpdate(SharedBufferBase* sbb)
+    : UpdateBase(sbb) {    
+}
+ssize_t SharedBufferClient::QueueUpdate::operator()() {
+    android_atomic_inc(&stack.queued);
+    return NO_ERROR;
+}
+
+SharedBufferClient::UndoDequeueUpdate::UndoDequeueUpdate(SharedBufferBase* sbb)
+    : UpdateBase(sbb) {    
+}
+ssize_t SharedBufferClient::UndoDequeueUpdate::operator()() {
+    android_atomic_inc(&stack.available);
+    return NO_ERROR;
+}
+
+SharedBufferServer::UnlockUpdate::UnlockUpdate(
+        SharedBufferBase* sbb, int lockedBuffer)
+    : UpdateBase(sbb), lockedBuffer(lockedBuffer) {
+}
+ssize_t SharedBufferServer::UnlockUpdate::operator()() {
+    if (stack.inUse != lockedBuffer) {
+        LOGE("unlocking %d, but currently locked buffer is %d",
+                lockedBuffer, stack.inUse);
+        return BAD_VALUE;
+    }
+    android_atomic_write(-1, &stack.inUse);
+    return NO_ERROR;
+}
+
+SharedBufferServer::RetireUpdate::RetireUpdate(
+        SharedBufferBase* sbb, int numBuffers)
+    : UpdateBase(sbb), numBuffers(numBuffers) {
+}
+ssize_t SharedBufferServer::RetireUpdate::operator()() {
+    // head is only written in this function, which is single-thread.
+    int32_t head = stack.head;
+
+    // Preventively lock the current buffer before updating queued.
+    android_atomic_write(head, &stack.inUse);
+
+    // Decrement the number of queued buffers 
+    int32_t queued;
+    do {
+        queued = stack.queued;
+        if (queued == 0) {
+            return NOT_ENOUGH_DATA;
+        }
+    } while (android_atomic_cmpxchg(queued, queued-1, &stack.queued));
+    
+    // update the head pointer
+    head = ((head+1 >= numBuffers) ? 0 : head+1);
+
+    // lock the buffer before advancing head, which automatically unlocks
+    // the buffer we preventively locked upon entering this function
+    android_atomic_write(head, &stack.inUse);
+
+    // advance head
+    android_atomic_write(head, &stack.head);
+    
+    // now that head has moved, we can increment the number of available buffers
+    android_atomic_inc(&stack.available);
+    return head;
+}
+
+SharedBufferServer::StatusUpdate::StatusUpdate(
+        SharedBufferBase* sbb, status_t status)
+    : UpdateBase(sbb), status(status) {
+}
+
+ssize_t SharedBufferServer::StatusUpdate::operator()() {
+    android_atomic_write(status, &stack.status);
+    return NO_ERROR;
+}
+
+// ============================================================================
+
+SharedBufferClient::SharedBufferClient(SharedClient* sharedClient,
+        int surface, int num, int32_t identity)
+    : SharedBufferBase(sharedClient, surface, num, identity), tail(0)
+{
+    tail = computeTail();
+}
+
+int32_t SharedBufferClient::computeTail() const
+{
+    SharedBufferStack& stack( *mSharedStack );
+    // we need to make sure we read available and head coherently,
+    // w.r.t RetireUpdate.
+    int32_t newTail;
+    int32_t avail;
+    int32_t head;
+    do {
+        avail = stack.available;
+        head = stack.head;
+    } while (stack.available != avail);
+    newTail = head - avail + 1;
+    if (newTail < 0) {
+        newTail += mNumBuffers;
+    }
+    return newTail;
+}
+
+ssize_t SharedBufferClient::dequeue()
+{
+    SharedBufferStack& stack( *mSharedStack );
+
+    if (stack.head == tail && stack.available == 2) {
+        LOGW("dequeue: tail=%d, head=%d, avail=%d, queued=%d",
+                tail, stack.head, stack.available, stack.queued);
+    }
+        
+    const nsecs_t dequeueTime = systemTime(SYSTEM_TIME_THREAD);
+
+    //LOGD("[%d] about to dequeue a buffer",
+    //        mSharedStack->identity);
+    DequeueCondition condition(this);
+    status_t err = waitForCondition(condition);
+    if (err != NO_ERROR)
+        return ssize_t(err);
+
+    // NOTE: 'stack.available' is part of the conditions, however
+    // decrementing it, never changes any conditions, so we don't need
+    // to do this as part of an update.
+    if (android_atomic_dec(&stack.available) == 0) {
+        LOGW("dequeue probably called from multiple threads!");
+    }
+
+    int dequeued = tail;
+    tail = ((tail+1 >= mNumBuffers) ? 0 : tail+1);
+    LOGD_IF(DEBUG_ATOMICS, "dequeued=%d, tail=%d, %s",
+            dequeued, tail, dump("").string());
+
+    mDequeueTime[dequeued] = dequeueTime; 
+
+    return dequeued;
+}
+
+status_t SharedBufferClient::undoDequeue(int buf)
+{
+    UndoDequeueUpdate update(this);
+    status_t err = updateCondition( update );
+    if (err == NO_ERROR) {
+        tail = computeTail();
+    }
+    return err;
+}
+
+status_t SharedBufferClient::lock(int buf)
+{
+    LockCondition condition(this, buf);
+    status_t err = waitForCondition(condition);
+    return err;
+}
+
+status_t SharedBufferClient::queue(int buf)
+{
+    QueueUpdate update(this);
+    status_t err = updateCondition( update );
+    LOGD_IF(DEBUG_ATOMICS, "queued=%d, %s", buf, dump("").string());
+    SharedBufferStack& stack( *mSharedStack );
+    const nsecs_t now = systemTime(SYSTEM_TIME_THREAD);
+    stack.stats.totalTime = ns2us(now - mDequeueTime[buf]);
+    return err;
+}
+
+bool SharedBufferClient::needNewBuffer(int buffer) const
+{
+    SharedBufferStack& stack( *mSharedStack );
+    const uint32_t mask = 1<<buffer;
+    return (android_atomic_and(~mask, &stack.reallocMask) & mask) != 0;
+}
+
+status_t SharedBufferClient::setDirtyRegion(int buffer, const Region& reg)
+{
+    SharedBufferStack& stack( *mSharedStack );
+    return stack.setDirtyRegion(buffer, reg);
+}
+
+// ----------------------------------------------------------------------------
+
+SharedBufferServer::SharedBufferServer(SharedClient* sharedClient,
+        int surface, int num, int32_t identity)
+    : SharedBufferBase(sharedClient, surface, num, identity)
+{
+    mSharedStack->init(identity);
+    mSharedStack->head = num-1;
+    mSharedStack->available = num;
+    mSharedStack->queued = 0;
+    mSharedStack->reallocMask = 0;
+    memset(mSharedStack->dirtyRegion, 0, sizeof(mSharedStack->dirtyRegion));
+}
+
+ssize_t SharedBufferServer::retireAndLock()
+{
+    RetireUpdate update(this, mNumBuffers);
+    ssize_t buf = updateCondition( update );
+    LOGD_IF(DEBUG_ATOMICS && buf>=0, "retire=%d, %s", int(buf), dump("").string());
+    return buf;
+}
+
+status_t SharedBufferServer::unlock(int buffer)
+{
+    UnlockUpdate update(this, buffer);
+    status_t err = updateCondition( update );
+    return err;
+}
+
+void SharedBufferServer::setStatus(status_t status)
+{
+    if (status < NO_ERROR) {
+        StatusUpdate update(this, status);
+        updateCondition( update );
+    }
+}
+
+status_t SharedBufferServer::reallocate()
+{
+    SharedBufferStack& stack( *mSharedStack );
+    uint32_t mask = (1<<mNumBuffers)-1;
+    android_atomic_or(mask, &stack.reallocMask); 
+    return NO_ERROR;
+}
+
+int32_t SharedBufferServer::getQueuedCount() const
+{
+    SharedBufferStack& stack( *mSharedStack );
+    return stack.queued;
+}
+
+status_t SharedBufferServer::assertReallocate(int buffer)
+{
+    ReallocateCondition condition(this, buffer);
+    status_t err = waitForCondition(condition);
+    return err;
+}
+
+Region SharedBufferServer::getDirtyRegion(int buffer) const
+{
+    SharedBufferStack& stack( *mSharedStack );
+    return stack.getDirtyRegion(buffer);
+}
+
+SharedBufferStack::Statistics SharedBufferServer::getStats() const
+{
+    SharedBufferStack& stack( *mSharedStack );
+    return stack.stats;
+}
+
+
+// ---------------------------------------------------------------------------
+}; // namespace android
diff --git a/libs/ui/Surface.cpp b/libs/ui/Surface.cpp
index 4ea9ae2..f51ca7a 100644
--- a/libs/ui/Surface.cpp
+++ b/libs/ui/Surface.cpp
@@ -23,233 +23,734 @@
 #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/CallStack.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IMemory.h>
 #include <utils/Log.h>
 
+#include <ui/DisplayInfo.h>
+#include <ui/GraphicBuffer.h>
+#include <ui/GraphicBufferMapper.h>
 #include <ui/ISurface.h>
 #include <ui/Surface.h>
 #include <ui/SurfaceComposerClient.h>
 #include <ui/Rect.h>
 
-#include <private/ui/SharedState.h>
+#include <pixelflinger/pixelflinger.h>
+
+#include <private/ui/SharedBufferStack.h>
 #include <private/ui/LayerState.h>
 
 namespace android {
 
-// ---------------------------------------------------------------------------
+// ----------------------------------------------------------------------
 
-Surface::Surface(const sp<SurfaceComposerClient>& client, 
+static status_t copyBlt(
+        const sp<GraphicBuffer>& dst, 
+        const sp<GraphicBuffer>& src, 
+        const Region& reg)
+{
+    status_t err;
+    uint8_t const * src_bits = NULL;
+    err = src->lock(GRALLOC_USAGE_SW_READ_OFTEN, reg.bounds(), (void**)&src_bits);
+    LOGE_IF(err, "error locking src buffer %s", strerror(-err));
+
+    uint8_t* dst_bits = NULL;
+    err = dst->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, reg.bounds(), (void**)&dst_bits);
+    LOGE_IF(err, "error locking dst buffer %s", strerror(-err));
+
+    Region::const_iterator head(reg.begin());
+    Region::const_iterator tail(reg.end());
+    if (head != tail && src_bits && dst_bits) {
+        // NOTE: dst and src must be the same format
+        const size_t bpp = bytesPerPixel(src->format);
+        const size_t dbpr = dst->stride * bpp;
+        const size_t sbpr = src->stride * bpp;
+
+        while (head != tail) {
+            const Rect& r(*head++);
+            ssize_t h = r.height();
+            if (h <= 0) continue;
+            size_t size = r.width() * bpp;
+            uint8_t const * s = src_bits + (r.left + src->stride * r.top) * bpp;
+            uint8_t       * d = dst_bits + (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);
+        }
+    }
+    
+    if (src_bits)
+        src->unlock();
+    
+    if (dst_bits)
+        dst->unlock();
+    
+    return err;
+}
+
+// ============================================================================
+//  SurfaceControl
+// ============================================================================
+
+SurfaceControl::SurfaceControl(
+        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)
+        uint32_t w, uint32_t h, PixelFormat format, uint32_t flags)
     : mClient(client), mSurface(surface),
       mToken(data.token), mIdentity(data.identity),
-      mFormat(format), mFlags(flags), mOwner(owner)
+      mWidth(data.width), mHeight(data.height), mFormat(data.format),
+      mFlags(flags)
 {
-    mSwapRectangle.makeInvalid();
-    mSurfaceHeapBase[0] = 0;
-    mSurfaceHeapBase[1] = 0;
-    mHeap[0] = data.heap[0]; 
-    mHeap[1] = data.heap[1];
+}
+        
+SurfaceControl::~SurfaceControl()
+{
+    destroy();
 }
 
-Surface::Surface(Surface const* rhs)
-    : mOwner(false)
+void SurfaceControl::destroy()
 {
-    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) {
+    if (isValid()) {
         mClient->destroySurface(mToken);
     }
+
+    // clear all references and trigger an IPC now, to make sure things
+    // happen without delay, since these resources are quite heavy.
     mClient.clear();
     mSurface.clear();
-    mHeap[0].clear();
-    mHeap[1].clear();
     IPCThreadState::self()->flushCommands();
 }
 
-sp<Surface> Surface::dup() const
+void SurfaceControl::clear() 
 {
-    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);
+    // here, the window manager tells us explicitly that we should destroy
+    // the surface's resource. Soon after this call, it will also release
+    // its last reference (which will call the dtor); however, it is possible
+    // that a client living in the same process still holds references which
+    // would delay the call to the dtor -- that is why we need this explicit
+    // "clear()" call.
+    destroy();
 }
 
-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) 
+bool SurfaceControl::isSameSurface(
+        const sp<SurfaceControl>& lhs, const sp<SurfaceControl>& rhs) 
 {
     if (lhs == 0 || rhs == 0)
         return false;
     return lhs->mSurface->asBinder() == rhs->mSurface->asBinder();
 }
 
-void* Surface::heapBase(int i) const 
+status_t SurfaceControl::setLayer(int32_t layer) {
+    const sp<SurfaceComposerClient>& client(mClient);
+    if (client == 0) return NO_INIT;
+    status_t err = validate(client->mControl);
+    if (err < 0) return err;
+    return client->setLayer(mToken, layer);
+}
+status_t SurfaceControl::setPosition(int32_t x, int32_t y) {
+    const sp<SurfaceComposerClient>& client(mClient);
+    if (client == 0) return NO_INIT;
+    status_t err = validate(client->mControl);
+    if (err < 0) return err;
+    return client->setPosition(mToken, x, y);
+}
+status_t SurfaceControl::setSize(uint32_t w, uint32_t h) {
+    const sp<SurfaceComposerClient>& client(mClient);
+    if (client == 0) return NO_INIT;
+    status_t err = validate(client->mControl);
+    if (err < 0) return err;
+    return client->setSize(mToken, w, h);
+}
+status_t SurfaceControl::hide() {
+    const sp<SurfaceComposerClient>& client(mClient);
+    if (client == 0) return NO_INIT;
+    status_t err = validate(client->mControl);
+    if (err < 0) return err;
+    return client->hide(mToken);
+}
+status_t SurfaceControl::show(int32_t layer) {
+    const sp<SurfaceComposerClient>& client(mClient);
+    if (client == 0) return NO_INIT;
+    status_t err = validate(client->mControl);
+    if (err < 0) return err;
+    return client->show(mToken, layer);
+}
+status_t SurfaceControl::freeze() {
+    const sp<SurfaceComposerClient>& client(mClient);
+    if (client == 0) return NO_INIT;
+    status_t err = validate(client->mControl);
+    if (err < 0) return err;
+    return client->freeze(mToken);
+}
+status_t SurfaceControl::unfreeze() {
+    const sp<SurfaceComposerClient>& client(mClient);
+    if (client == 0) return NO_INIT;
+    status_t err = validate(client->mControl);
+    if (err < 0) return err;
+    return client->unfreeze(mToken);
+}
+status_t SurfaceControl::setFlags(uint32_t flags, uint32_t mask) {
+    const sp<SurfaceComposerClient>& client(mClient);
+    if (client == 0) return NO_INIT;
+    status_t err = validate(client->mControl);
+    if (err < 0) return err;
+    return client->setFlags(mToken, flags, mask);
+}
+status_t SurfaceControl::setTransparentRegionHint(const Region& transparent) {
+    const sp<SurfaceComposerClient>& client(mClient);
+    if (client == 0) return NO_INIT;
+    status_t err = validate(client->mControl);
+    if (err < 0) return err;
+    return client->setTransparentRegionHint(mToken, transparent);
+}
+status_t SurfaceControl::setAlpha(float alpha) {
+    const sp<SurfaceComposerClient>& client(mClient);
+    if (client == 0) return NO_INIT;
+    status_t err = validate(client->mControl);
+    if (err < 0) return err;
+    return client->setAlpha(mToken, alpha);
+}
+status_t SurfaceControl::setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
+    const sp<SurfaceComposerClient>& client(mClient);
+    if (client == 0) return NO_INIT;
+    status_t err = validate(client->mControl);
+    if (err < 0) return err;
+    return client->setMatrix(mToken, dsdx, dtdx, dsdy, dtdy);
+}
+status_t SurfaceControl::setFreezeTint(uint32_t tint) {
+    const sp<SurfaceComposerClient>& client(mClient);
+    if (client == 0) return NO_INIT;
+    status_t err = validate(client->mControl);
+    if (err < 0) return err;
+    return client->setFreezeTint(mToken, tint);
+}
+
+status_t SurfaceControl::validate(SharedClient const* cblk) 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;
+    if (mToken<0 || mClient==0) {
+        LOGE("invalid token (%d, identity=%u) or client (%p)", 
+                mToken, mIdentity, mClient.get());
+        return NO_INIT;
+    }
+    if (cblk == 0) {
+        LOGE("cblk is null (surface id=%d, identity=%u)", mToken, mIdentity);
+        return NO_INIT;
+    }
+    status_t err = cblk->validate(mToken);
+    if (err != NO_ERROR) {
+        LOGE("surface (id=%d, identity=%u) is invalid, err=%d (%s)",
+                mToken, mIdentity, err, strerror(-err));
+        return err;
+    }
+    uint32_t identity = cblk->getIdentity(mToken);
+    if (mIdentity != identity) {
+        LOGE("using an invalid surface id=%d, identity=%u should be %d",
+                mToken, mIdentity, identity);
+        return NO_INIT;
+    }
+    return NO_ERROR;
+}
+
+status_t SurfaceControl::writeSurfaceToParcel(
+        const sp<SurfaceControl>& control, Parcel* parcel)
+{
+    uint32_t flags = 0;
+    uint32_t format = 0;
+    SurfaceID token = -1;
+    uint32_t identity = 0;
+    uint32_t width = 0;
+    uint32_t height = 0;
+    sp<SurfaceComposerClient> client;
+    sp<ISurface> sur;
+    if (SurfaceControl::isValid(control)) {
+        token    = control->mToken;
+        identity = control->mIdentity;
+        client   = control->mClient;
+        sur      = control->mSurface;
+        width    = control->mWidth;
+        height   = control->mHeight;
+        format   = control->mFormat;
+        flags    = control->mFlags;
+    }
+    parcel->writeStrongBinder(client!=0  ? client->connection() : NULL);
+    parcel->writeStrongBinder(sur!=0     ? sur->asBinder()      : NULL);
+    parcel->writeInt32(token);
+    parcel->writeInt32(identity);
+    parcel->writeInt32(width);
+    parcel->writeInt32(height);
+    parcel->writeInt32(format);
+    parcel->writeInt32(flags);
+    return NO_ERROR;
+}
+
+sp<Surface> SurfaceControl::getSurface() const
+{
+    Mutex::Autolock _l(mLock);
+    if (mSurfaceData == 0) {
+        mSurfaceData = new Surface(const_cast<SurfaceControl*>(this));
+    }
+    return mSurfaceData;
+}
+
+// ============================================================================
+//  Surface
+// ============================================================================
+
+Surface::Surface(const sp<SurfaceControl>& surface)
+    : mClient(surface->mClient), mSurface(surface->mSurface),
+      mToken(surface->mToken), mIdentity(surface->mIdentity),
+      mFormat(surface->mFormat), mFlags(surface->mFlags),
+      mBufferMapper(GraphicBufferMapper::get()), mSharedBufferClient(NULL),
+      mWidth(surface->mWidth), mHeight(surface->mHeight)
+{
+    mSharedBufferClient = new SharedBufferClient(
+            mClient->mControl, mToken, 2, mIdentity);
+
+    init();
+}
+
+Surface::Surface(const Parcel& parcel)
+    :  mBufferMapper(GraphicBufferMapper::get()), mSharedBufferClient(NULL)
+{
+    sp<IBinder> clientBinder = parcel.readStrongBinder();
+    mSurface    = interface_cast<ISurface>(parcel.readStrongBinder());
+    mToken      = parcel.readInt32();
+    mIdentity   = parcel.readInt32();
+    mWidth      = parcel.readInt32();
+    mHeight     = parcel.readInt32();
+    mFormat     = parcel.readInt32();
+    mFlags      = parcel.readInt32();
+
+    // FIXME: what does that mean if clientBinder is NULL here?
+    if (clientBinder != NULL) {
+        mClient = SurfaceComposerClient::clientForConnection(clientBinder);
+
+        mSharedBufferClient = new SharedBufferClient(
+                mClient->mControl, mToken, 2, mIdentity);
+    }
+
+    init();
+}
+
+void Surface::init()
+{
+    android_native_window_t::setSwapInterval  = setSwapInterval;
+    android_native_window_t::dequeueBuffer    = dequeueBuffer;
+    android_native_window_t::lockBuffer       = lockBuffer;
+    android_native_window_t::queueBuffer      = queueBuffer;
+    android_native_window_t::query            = query;
+    android_native_window_t::perform          = perform;
+    mSwapRectangle.makeInvalid();
+    DisplayInfo dinfo;
+    SurfaceComposerClient::getDisplayInfo(0, &dinfo);
+    const_cast<float&>(android_native_window_t::xdpi) = dinfo.xdpi;
+    const_cast<float&>(android_native_window_t::ydpi) = dinfo.ydpi;
+    // FIXME: set real values here
+    const_cast<int&>(android_native_window_t::minSwapInterval) = 1;
+    const_cast<int&>(android_native_window_t::maxSwapInterval) = 1;
+    const_cast<uint32_t&>(android_native_window_t::flags) = 0;
+    // be default we request a hardware surface
+    mUsage = GRALLOC_USAGE_HW_RENDER;
+    mNeedFullUpdate = false;
+}
+
+Surface::~Surface()
+{
+    // this is a client-side operation, the surface is destroyed, unmap
+    // its buffers in this process.
+    for (int i=0 ; i<2 ; i++) {
+        if (mBuffers[i] != 0 && mBuffers[i]->handle != 0) {
+            getBufferMapper().unregisterBuffer(mBuffers[i]->handle);
         }
     }
-    return heapBase;
+
+    // clear all references and trigger an IPC now, to make sure things
+    // happen without delay, since these resources are quite heavy.
+    mClient.clear();
+    mSurface.clear();
+    delete mSharedBufferClient;
+    IPCThreadState::self()->flushCommands();
+}
+
+sp<SurfaceComposerClient> Surface::getClient() const {
+    return mClient;
+}
+
+sp<ISurface> Surface::getISurface() const {
+    return mSurface;
+}
+
+bool Surface::isValid() {
+    return mToken>=0 && mClient!=0;
+}
+
+status_t Surface::validate(SharedClient const* cblk) const
+{
+    sp<SurfaceComposerClient> client(getClient());
+    if (mToken<0 || mClient==0) {
+        LOGE("invalid token (%d, identity=%u) or client (%p)", 
+                mToken, mIdentity, client.get());
+        return NO_INIT;
+    }
+    if (cblk == 0) {
+        LOGE("cblk is null (surface id=%d, identity=%u)", mToken, mIdentity);
+        return NO_INIT;
+    }
+    status_t err = cblk->validate(mToken);
+    if (err != NO_ERROR) {
+        LOGE("surface (id=%d, identity=%u) is invalid, err=%d (%s)",
+                mToken, mIdentity, err, strerror(-err));
+        return err;
+    }
+    uint32_t identity = cblk->getIdentity(mToken);
+    if (mIdentity != identity) {
+        LOGE("using an invalid surface id=%d, identity=%u should be %d",
+                mToken, mIdentity, identity);
+        return NO_INIT;
+    }
+    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();
+}
+
+// ----------------------------------------------------------------------------
+
+int Surface::setSwapInterval(android_native_window_t* window, int interval) {
+    return 0;
+}
+
+int Surface::dequeueBuffer(android_native_window_t* window, 
+        android_native_buffer_t** buffer) {
+    Surface* self = getSelf(window);
+    return self->dequeueBuffer(buffer);
+}
+
+int Surface::lockBuffer(android_native_window_t* window, 
+        android_native_buffer_t* buffer) {
+    Surface* self = getSelf(window);
+    return self->lockBuffer(buffer);
+}
+
+int Surface::queueBuffer(android_native_window_t* window, 
+        android_native_buffer_t* buffer) {
+    Surface* self = getSelf(window);
+    return self->queueBuffer(buffer);
+}
+
+int Surface::query(android_native_window_t* window, 
+        int what, int* value) {
+    Surface* self = getSelf(window);
+    return self->query(what, value);
+}
+
+int Surface::perform(android_native_window_t* window, 
+        int operation, ...) {
+    va_list args;
+    va_start(args, operation);
+    Surface* self = getSelf(window);
+    int res = self->perform(operation, args);
+    va_end(args);
+    return res;
+}
+
+// ----------------------------------------------------------------------------
+
+status_t Surface::dequeueBuffer(sp<GraphicBuffer>* buffer) {
+    android_native_buffer_t* out;
+    status_t err = dequeueBuffer(&out);
+    if (err == NO_ERROR) {
+        *buffer = GraphicBuffer::getSelf(out);
+    }
+    return err;
+}
+
+// ----------------------------------------------------------------------------
+
+
+int Surface::dequeueBuffer(android_native_buffer_t** buffer)
+{
+    sp<SurfaceComposerClient> client(getClient());
+    status_t err = validate(client->mControl);
+    if (err != NO_ERROR)
+        return err;
+
+    ssize_t bufIdx = mSharedBufferClient->dequeue();
+    if (bufIdx < 0) {
+        LOGE("error dequeuing a buffer (%s)", strerror(bufIdx));
+        return bufIdx;
+    }
+
+    // below we make sure we AT LEAST have the usage flags we want
+    const uint32_t usage(getUsage());
+    const sp<GraphicBuffer>& backBuffer(mBuffers[bufIdx]);
+    if (backBuffer == 0 || 
+        ((uint32_t(backBuffer->usage) & usage) != usage) ||
+        mSharedBufferClient->needNewBuffer(bufIdx)) 
+    {
+        err = getBufferLocked(bufIdx, usage);
+        LOGE_IF(err, "getBufferLocked(%ld, %08x) failed (%s)",
+                bufIdx, usage, strerror(-err));
+        if (err == NO_ERROR) {
+            // reset the width/height with the what we get from the buffer
+            mWidth  = uint32_t(backBuffer->width);
+            mHeight = uint32_t(backBuffer->height);
+        }
+    }
+
+    // if we still don't have a buffer here, we probably ran out of memory
+    if (!err && backBuffer==0) {
+        err = NO_MEMORY;
+    }
+
+    if (err == NO_ERROR) {
+        mDirtyRegion.set(backBuffer->width, backBuffer->height);
+        *buffer = backBuffer.get();
+    } else {
+        mSharedBufferClient->undoDequeue(bufIdx);
+    }
+
+    return err;
+}
+
+int Surface::lockBuffer(android_native_buffer_t* buffer)
+{
+    sp<SurfaceComposerClient> client(getClient());
+    status_t err = validate(client->mControl);
+    if (err != NO_ERROR)
+        return err;
+
+    int32_t bufIdx = GraphicBuffer::getSelf(buffer)->getIndex();
+    err = mSharedBufferClient->lock(bufIdx);
+    LOGE_IF(err, "error locking buffer %d (%s)", bufIdx, strerror(-err));
+    return err;
+}
+
+int Surface::queueBuffer(android_native_buffer_t* buffer)
+{   
+    sp<SurfaceComposerClient> client(getClient());
+    status_t err = validate(client->mControl);
+    if (err != NO_ERROR)
+        return err;
+
+    if (mSwapRectangle.isValid()) {
+        mDirtyRegion.set(mSwapRectangle);
+    }
+    
+    int32_t bufIdx = GraphicBuffer::getSelf(buffer)->getIndex();
+    mSharedBufferClient->setDirtyRegion(bufIdx, mDirtyRegion);
+    err = mSharedBufferClient->queue(bufIdx);
+    LOGE_IF(err, "error queuing buffer %d (%s)", bufIdx, strerror(-err));
+
+    if (err == NO_ERROR) {
+        // FIXME: can we avoid this IPC if we know there is one pending?
+        client->signalServer();
+    }
+    return err;
+}
+
+int Surface::query(int what, int* value)
+{
+    switch (what) {
+    case NATIVE_WINDOW_WIDTH:
+        *value = int(mWidth);
+        return NO_ERROR;
+    case NATIVE_WINDOW_HEIGHT:
+        *value = int(mHeight);
+        return NO_ERROR;
+    case NATIVE_WINDOW_FORMAT:
+        *value = int(mFormat);
+        return NO_ERROR;
+    }
+    return BAD_VALUE;
+}
+
+int Surface::perform(int operation, va_list args)
+{
+    int res = NO_ERROR;
+    switch (operation) {
+        case NATIVE_WINDOW_SET_USAGE:
+            setUsage( va_arg(args, int) );
+            break;
+        default:
+            res = NAME_NOT_FOUND;
+            break;
+    }
+    return res;
+}
+
+void Surface::setUsage(uint32_t reqUsage)
+{
+    Mutex::Autolock _l(mSurfaceLock);
+    mUsage = reqUsage;
+}
+
+uint32_t Surface::getUsage() const
+{
+    Mutex::Autolock _l(mSurfaceLock);
+    return mUsage;
+}
+
+// ----------------------------------------------------------------------------
+
+status_t Surface::lock(SurfaceInfo* info, bool blocking) {
+    return Surface::lock(info, NULL, blocking);
+}
+
+status_t Surface::lock(SurfaceInfo* other, Region* dirtyIn, bool blocking) 
+{
+    if (mApiLock.tryLock() != NO_ERROR) {
+        LOGE("calling Surface::lock() from different threads!");
+        CallStack stack;
+        stack.update();
+        stack.dump("Surface::lock called from different threads");
+        return WOULD_BLOCK;
+    }
+    
+    // we're intending to do software rendering from this point
+    setUsage(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
+
+    sp<GraphicBuffer> backBuffer;
+    status_t err = dequeueBuffer(&backBuffer);
+    LOGE_IF(err, "dequeueBuffer failed (%s)", strerror(-err));
+    if (err == NO_ERROR) {
+        err = lockBuffer(backBuffer.get());
+        LOGE_IF(err, "lockBuffer (idx=%d) failed (%s)",
+                backBuffer->getIndex(), strerror(-err));
+        if (err == NO_ERROR) {
+            // we handle copy-back here...
+
+            const Rect bounds(backBuffer->width, backBuffer->height);
+            Region scratch(bounds);
+            Region& newDirtyRegion(dirtyIn ? *dirtyIn : scratch);
+
+            if (mNeedFullUpdate) {
+                // reset newDirtyRegion to bounds when a buffer is reallocated
+                // it would be better if this information was associated with
+                // the buffer and made available to outside of Surface.
+                // This will do for now though.
+                mNeedFullUpdate = false;
+                newDirtyRegion.set(bounds);
+            } else {
+                newDirtyRegion.andSelf(bounds);
+            }
+
+            const sp<GraphicBuffer>& frontBuffer(mPostedBuffer);
+            if (frontBuffer !=0 &&
+                backBuffer->width  == frontBuffer->width && 
+                backBuffer->height == frontBuffer->height &&
+                !(mFlags & ISurfaceComposer::eDestroyBackbuffer)) 
+            {
+                const Region copyback(mOldDirtyRegion.subtract(newDirtyRegion));
+                if (!copyback.isEmpty() && frontBuffer!=0) {
+                    // copy front to back
+                    copyBlt(backBuffer, frontBuffer, copyback);
+                }
+            }
+
+            mDirtyRegion = newDirtyRegion;
+            mOldDirtyRegion = newDirtyRegion;
+
+            void* vaddr;
+            status_t res = backBuffer->lock(
+                    GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
+                    newDirtyRegion.bounds(), &vaddr);
+            
+            LOGW_IF(res, "failed locking buffer (handle = %p)", 
+                    backBuffer->handle);
+
+            mLockedBuffer = backBuffer;
+            other->w      = backBuffer->width;
+            other->h      = backBuffer->height;
+            other->s      = backBuffer->stride;
+            other->usage  = backBuffer->usage;
+            other->format = backBuffer->format;
+            other->bits   = vaddr;
+        }
+    }
+    mApiLock.unlock();
+    return err;
+}
+    
+status_t Surface::unlockAndPost() 
+{
+    if (mLockedBuffer == 0) {
+        LOGE("unlockAndPost failed, no locked buffer");
+        return BAD_VALUE;
+    }
+
+    status_t err = mLockedBuffer->unlock();
+    LOGE_IF(err, "failed unlocking buffer (%p)", mLockedBuffer->handle);
+    
+    err = queueBuffer(mLockedBuffer.get());
+    LOGE_IF(err, "queueBuffer (idx=%d) failed (%s)",
+            mLockedBuffer->getIndex(), strerror(-err));
+
+    mPostedBuffer = mLockedBuffer;
+    mLockedBuffer = 0;
+    return err;
+}
+
+void Surface::setSwapRectangle(const Rect& r) {
+    Mutex::Autolock _l(mSurfaceLock);
+    mSwapRectangle = r;
+}
+
+status_t Surface::getBufferLocked(int index, int usage)
+{
+    sp<ISurface> s(mSurface);
+    if (s == 0) return NO_INIT;
+
+    status_t err = NO_MEMORY;
+
+    // free the current buffer
+    sp<GraphicBuffer>& currentBuffer(mBuffers[index]);
+    if (currentBuffer != 0) {
+        getBufferMapper().unregisterBuffer(currentBuffer->handle);
+        currentBuffer.clear();
+    }
+
+    sp<GraphicBuffer> buffer = s->requestBuffer(index, usage);
+    LOGE_IF(buffer==0,
+            "ISurface::getBuffer(%d, %08x) returned NULL",
+            index, usage);
+    if (buffer != 0) { // this should never happen by construction
+        LOGE_IF(buffer->handle == NULL, 
+                "Surface (identity=%d) requestBuffer(%d, %08x) returned"
+                "a buffer with a null handle", mIdentity, index, usage);
+        err = mSharedBufferClient->getStatus();
+        LOGE_IF(err,  "Surface (identity=%d) state = %d", mIdentity, err);
+        if (!err && buffer->handle != NULL) {
+            err = getBufferMapper().registerBuffer(buffer->handle);
+            LOGW_IF(err, "registerBuffer(...) failed %d (%s)",
+                    err, strerror(-err));
+            if (err == NO_ERROR) {
+                currentBuffer = buffer;
+                currentBuffer->setIndex(index);
+                mNeedFullUpdate = true;
+            }
+        } else {
+            err = err<0 ? err : NO_MEMORY;
+        }
+    }
+    return err; 
 }
 
 }; // namespace android
diff --git a/libs/ui/SurfaceComposerClient.cpp b/libs/ui/SurfaceComposerClient.cpp
index fe803ff..eda84ef 100644
--- a/libs/ui/SurfaceComposerClient.cpp
+++ b/libs/ui/SurfaceComposerClient.cpp
@@ -29,26 +29,19 @@
 #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 <binder/IServiceManager.h>
+#include <binder/IMemory.h>
 #include <utils/Log.h>
 
+#include <ui/DisplayInfo.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>
+#include <private/ui/SharedBufferStack.h>
 
 #define VERBOSE(...)	((void)0)
 //#define VERBOSE			LOGD
@@ -65,42 +58,50 @@
 static sp<ISurfaceComposer>                                 gSurfaceManager;
 static DefaultKeyedVector< sp<IBinder>, sp<SurfaceComposerClient> > gActiveConnections;
 static SortedVector<sp<SurfaceComposerClient> >             gOpenTransactions;
-static sp<IMemory>                                          gServerCblkMemory;
+static sp<IMemoryHeap>                                      gServerCblkMemory;
 static volatile surface_flinger_cblk_t*                     gServerCblk;
 
-const sp<ISurfaceComposer>& _get_surface_manager()
+static sp<ISurfaceComposer> getComposerService()
 {
-    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));
-
+    sp<ISurfaceComposer> sc;
     Mutex::Autolock _l(gLock);
-    if (gSurfaceManager == 0) {
-        gSurfaceManager = sc;
+    if (gSurfaceManager != 0) {
+        sc = gSurfaceManager;
+    } else {
+        // release the lock while we're waiting...
+        gLock.unlock();
+
+        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);
+
+        // grab the lock again for updating gSurfaceManager
+        gLock.lock();
+        if (gSurfaceManager == 0) {
+            sc = interface_cast<ISurfaceComposer>(binder);
+            gSurfaceManager = sc;
+        } else {
+            sc = gSurfaceManager;
+        }
     }
-    return gSurfaceManager;
+    return sc;
 }
 
 static volatile surface_flinger_cblk_t const * get_cblk()
 {
     if (gServerCblk == 0) {
-        const sp<ISurfaceComposer>& sm(_get_surface_manager());
+        sp<ISurfaceComposer> sm(getComposerService());
         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();
+            gServerCblk = (surface_flinger_cblk_t *)gServerCblkMemory->getBase();
             LOGE_IF(gServerCblk==0, "Can't get server control block address");
         }
     }
@@ -109,210 +110,6 @@
 
 // ---------------------------------------------------------------------------
 
-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;
@@ -322,7 +119,7 @@
 
 SurfaceComposerClient::SurfaceComposerClient()
 {
-    const sp<ISurfaceComposer>& sm(_get_surface_manager());
+    sp<ISurfaceComposer> sm(getComposerService());
     if (sm == 0) {
         _init(0, 0);
         return;
@@ -343,12 +140,20 @@
     _init(sm, interface_cast<ISurfaceFlingerClient>(conn));
 }
 
+
+status_t SurfaceComposerClient::linkToComposerDeath(
+        const sp<IBinder::DeathRecipient>& recipient,
+        void* cookie, uint32_t flags)
+{
+    sp<ISurfaceComposer> sm(getComposerService());
+    return sm->asBinder()->linkToDeath(recipient, cookie, flags);    
+}
+
 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;
@@ -360,9 +165,9 @@
         return;
     }
 
-    mClient->getControlBlocks(&mControlMemory);
-    mSignalServer = new SurfaceFlingerSynchro(sm);
-    mControl = static_cast<per_client_cblk_t *>(mControlMemory->pointer());
+    mControlMemory = mClient->getControlBlock();
+    mSignalServer = sm;
+    mControl = static_cast<SharedClient *>(mControlMemory->getBase());
 }
 
 SurfaceComposerClient::~SurfaceComposerClient()
@@ -376,32 +181,6 @@
     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;
@@ -419,7 +198,7 @@
 
     if (client == 0) {
         // Need to make a new client.
-        const sp<ISurfaceComposer>& sm(_get_surface_manager());
+        sp<ISurfaceComposer> sm(getComposerService());
         client = new SurfaceComposerClient(sm, conn);
         if (client != 0 && client->initCheck() == NO_ERROR) {
             Mutex::Autolock _l(gLock);
@@ -437,15 +216,13 @@
 {
     // this can be called more than once.
 
-    sp<IMemory>                 controlMemory;
+    sp<IMemoryHeap>             controlMemory;
     sp<ISurfaceFlingerClient>   client;
-    sp<IMemoryHeap>             surfaceHeap;
 
     {
         Mutex::Autolock _lg(gLock);
         Mutex::Autolock _lm(mLock);
 
-        delete mSignalServer;
         mSignalServer = 0;
 
         if (mClient != 0) {
@@ -462,9 +239,7 @@
         delete mPrebuiltLayerState;
         mPrebuiltLayerState = 0;
         controlMemory = mControlMemory;
-        surfaceHeap = mSurfaceHeap;
         mControlMemory.clear();
-        mSurfaceHeap.clear();
         mControl = 0;
         mStatus = NO_INIT;
     }
@@ -528,7 +303,13 @@
     return n;
 }
 
-sp<Surface> SurfaceComposerClient::createSurface(
+
+void SurfaceComposerClient::signalServer()
+{
+    mSignalServer->signal();
+}
+
+sp<SurfaceControl> SurfaceComposerClient::createSurface(
         int pid,
         DisplayID display,
         uint32_t w,
@@ -536,14 +317,14 @@
         PixelFormat format,
         uint32_t flags)
 {
-    sp<Surface> result;
+    sp<SurfaceControl> 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);
+                result = new SurfaceControl(this, surface, data, w, h, format, flags);
             }
         }
     }
@@ -568,186 +349,6 @@
     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);
@@ -789,34 +390,33 @@
 
     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();
+
+    sp<ISurfaceComposer> sm(getComposerService());
+    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());
+    sp<ISurfaceComposer> sm(getComposerService());
     return sm->freezeDisplay(dpy, flags);
 }
 
 status_t SurfaceComposerClient::unfreezeDisplay(DisplayID dpy, uint32_t flags)
 {
-    const sp<ISurfaceComposer>& sm(_get_surface_manager());
+    sp<ISurfaceComposer> sm(getComposerService());
     return sm->unfreezeDisplay(dpy, flags);
 }
 
 int SurfaceComposerClient::setOrientation(DisplayID dpy, 
         int orientation, uint32_t flags)
 {
-    const sp<ISurfaceComposer>& sm(_get_surface_manager());
+    sp<ISurfaceComposer> sm(getComposerService());
     return sm->setOrientation(dpy, orientation, flags);
 }
 
@@ -866,14 +466,8 @@
     return NO_ERROR;
 }
 
-layer_state_t* SurfaceComposerClient::_get_state_l(const sp<Surface>& surface)
+layer_state_t* SurfaceComposerClient::_get_state_l(SurfaceID index)
 {
-    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",
@@ -892,11 +486,11 @@
     return mStates.editArray() + i;
 }
 
-layer_state_t* SurfaceComposerClient::_lockLayerState(const sp<Surface>& surface)
+layer_state_t* SurfaceComposerClient::_lockLayerState(SurfaceID id)
 {
     layer_state_t* s;
     mLock.lock();
-    s = _get_state_l(surface);
+    s = _get_state_l(id);
     if (!s) mLock.unlock();
     return s;
 }
@@ -906,9 +500,9 @@
     mLock.unlock();
 }
 
-status_t SurfaceComposerClient::setPosition(Surface* surface, int32_t x, int32_t y)
+status_t SurfaceComposerClient::setPosition(SurfaceID id, int32_t x, int32_t y)
 {
-    layer_state_t* s = _lockLayerState(surface);
+    layer_state_t* s = _lockLayerState(id);
     if (!s) return BAD_INDEX;
     s->what |= ISurfaceComposer::ePositionChanged;
     s->x = x;
@@ -917,9 +511,9 @@
     return NO_ERROR;
 }
 
-status_t SurfaceComposerClient::setSize(Surface* surface, uint32_t w, uint32_t h)
+status_t SurfaceComposerClient::setSize(SurfaceID id, uint32_t w, uint32_t h)
 {
-    layer_state_t* s = _lockLayerState(surface);
+    layer_state_t* s = _lockLayerState(id);
     if (!s) return BAD_INDEX;
     s->what |= ISurfaceComposer::eSizeChanged;
     s->w = w;
@@ -928,9 +522,9 @@
     return NO_ERROR;
 }
 
-status_t SurfaceComposerClient::setLayer(Surface* surface, int32_t z)
+status_t SurfaceComposerClient::setLayer(SurfaceID id, int32_t z)
 {
-    layer_state_t* s = _lockLayerState(surface);
+    layer_state_t* s = _lockLayerState(id);
     if (!s) return BAD_INDEX;
     s->what |= ISurfaceComposer::eLayerChanged;
     s->z = z;
@@ -938,32 +532,32 @@
     return NO_ERROR;
 }
 
-status_t SurfaceComposerClient::hide(Surface* surface)
+status_t SurfaceComposerClient::hide(SurfaceID id)
 {
-    return setFlags(surface, ISurfaceComposer::eLayerHidden,
+    return setFlags(id, ISurfaceComposer::eLayerHidden,
             ISurfaceComposer::eLayerHidden);
 }
 
-status_t SurfaceComposerClient::show(Surface* surface, int32_t)
+status_t SurfaceComposerClient::show(SurfaceID id, int32_t)
 {
-    return setFlags(surface, 0, ISurfaceComposer::eLayerHidden);
+    return setFlags(id, 0, ISurfaceComposer::eLayerHidden);
 }
 
-status_t SurfaceComposerClient::freeze(Surface* surface)
+status_t SurfaceComposerClient::freeze(SurfaceID id)
 {
-    return setFlags(surface, ISurfaceComposer::eLayerFrozen,
+    return setFlags(id, ISurfaceComposer::eLayerFrozen,
             ISurfaceComposer::eLayerFrozen);
 }
 
-status_t SurfaceComposerClient::unfreeze(Surface* surface)
+status_t SurfaceComposerClient::unfreeze(SurfaceID id)
 {
-    return setFlags(surface, 0, ISurfaceComposer::eLayerFrozen);
+    return setFlags(id, 0, ISurfaceComposer::eLayerFrozen);
 }
 
-status_t SurfaceComposerClient::setFlags(Surface* surface,
+status_t SurfaceComposerClient::setFlags(SurfaceID id,
         uint32_t flags, uint32_t mask)
 {
-    layer_state_t* s = _lockLayerState(surface);
+    layer_state_t* s = _lockLayerState(id);
     if (!s) return BAD_INDEX;
     s->what |= ISurfaceComposer::eVisibilityChanged;
     s->flags &= ~mask;
@@ -973,11 +567,10 @@
     return NO_ERROR;
 }
 
-
 status_t SurfaceComposerClient::setTransparentRegionHint(
-        Surface* surface, const Region& transparentRegion)
+        SurfaceID id, const Region& transparentRegion)
 {
-    layer_state_t* s = _lockLayerState(surface);
+    layer_state_t* s = _lockLayerState(id);
     if (!s) return BAD_INDEX;
     s->what |= ISurfaceComposer::eTransparentRegionChanged;
     s->transparentRegion = transparentRegion;
@@ -985,9 +578,9 @@
     return NO_ERROR;
 }
 
-status_t SurfaceComposerClient::setAlpha(Surface* surface, float alpha)
+status_t SurfaceComposerClient::setAlpha(SurfaceID id, float alpha)
 {
-    layer_state_t* s = _lockLayerState(surface);
+    layer_state_t* s = _lockLayerState(id);
     if (!s) return BAD_INDEX;
     s->what |= ISurfaceComposer::eAlphaChanged;
     s->alpha = alpha;
@@ -996,11 +589,11 @@
 }
 
 status_t SurfaceComposerClient::setMatrix(
-        Surface* surface,
+        SurfaceID id,
         float dsdx, float dtdx,
         float dsdy, float dtdy )
 {
-    layer_state_t* s = _lockLayerState(surface);
+    layer_state_t* s = _lockLayerState(id);
     if (!s) return BAD_INDEX;
     s->what |= ISurfaceComposer::eMatrixChanged;
     layer_state_t::matrix22_t matrix;
@@ -1013,9 +606,9 @@
     return NO_ERROR;
 }
 
-status_t SurfaceComposerClient::setFreezeTint(Surface* surface, uint32_t tint)
+status_t SurfaceComposerClient::setFreezeTint(SurfaceID id, uint32_t tint)
 {
-    layer_state_t* s = _lockLayerState(surface);
+    layer_state_t* s = _lockLayerState(id);
     if (!s) return BAD_INDEX;
     s->what |= ISurfaceComposer::eFreezeTintChanged;
     s->tint = tint;
diff --git a/libs/ui/SurfaceFlingerSynchro.cpp b/libs/ui/SurfaceFlingerSynchro.cpp
deleted file mode 100644
index 5cd9755..0000000
--- a/libs/ui/SurfaceFlingerSynchro.cpp
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * 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/tests/Android.mk b/libs/ui/tests/Android.mk
new file mode 100644
index 0000000..6cc4a5a
--- /dev/null
+++ b/libs/ui/tests/Android.mk
@@ -0,0 +1,16 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+	region.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+	libcutils \
+	libutils \
+    libui
+
+LOCAL_MODULE:= test-region
+
+LOCAL_MODULE_TAGS := tests
+
+include $(BUILD_EXECUTABLE)
diff --git a/libs/ui/tests/region.cpp b/libs/ui/tests/region.cpp
new file mode 100644
index 0000000..ef15de9
--- /dev/null
+++ b/libs/ui/tests/region.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2009 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/Debug.h>
+#include <ui/Rect.h>
+#include <ui/Region.h>
+
+using namespace android;
+
+int main()
+{
+    Region empty;
+    Region reg0( Rect(  0, 0,  100, 100 ) );
+    Region reg1 = reg0;
+    Region reg2, reg3;
+
+    Region reg4 = empty | reg1;
+    Region reg5 = reg1 | empty;
+
+    reg4.dump("reg4");
+    reg5.dump("reg5");
+    
+    reg0.dump("reg0");
+    reg1.dump("reg1");
+
+    reg0 = reg0 | reg0.translate(150, 0);
+    reg0.dump("reg0");
+    reg1.dump("reg1");
+
+    reg0 = reg0 | reg0.translate(300, 0);
+    reg0.dump("reg0");
+    reg1.dump("reg1");
+
+    //reg2 = reg0 | reg0.translate(0, 100);
+    //reg0.dump("reg0");
+    //reg1.dump("reg1");
+    //reg2.dump("reg2");
+
+    //reg3 = reg0 | reg0.translate(0, 150);
+    //reg0.dump("reg0");
+    //reg1.dump("reg1");
+    //reg2.dump("reg2");
+    //reg3.dump("reg3");
+
+    LOGD("---");
+    reg2 = reg0 | reg0.translate(100, 0);
+    reg0.dump("reg0");
+    reg1.dump("reg1");
+    reg2.dump("reg2");
+    
+    return 0;
+}
+
diff --git a/libs/utils/Android.mk b/libs/utils/Android.mk
index 9bdd64a..59409a2 100644
--- a/libs/utils/Android.mk
+++ b/libs/utils/Android.mk
@@ -32,52 +32,24 @@
 	StopWatch.cpp \
 	String8.cpp \
 	String16.cpp \
+	StringArray.cpp \
 	SystemClock.cpp \
 	TextOutput.cpp \
 	Threads.cpp \
-	TimerProbe.cpp \
 	Timers.cpp \
 	VectorImpl.cpp \
     ZipFileCRO.cpp \
 	ZipFileRO.cpp \
 	ZipUtils.cpp \
-	misc.cpp \
-	ported.cpp \
-	LogSocket.cpp
+	misc.cpp
 
-#
-# The cpp files listed here do not belong in the device
-# build.  Consult with the swetland before even thinking about
-# putting them in commonSources.
-#
-# They're used by the simulator runtime and by host-side tools like
-# aapt and the simulator front-end.
-#
-hostSources:= \
-	InetAddress.cpp \
-	Pipe.cpp \
-	Socket.cpp \
-	ZipEntry.cpp \
-	ZipFile.cpp
 
 # For the host
 # =====================================================
 
 include $(CLEAR_VARS)
 
-LOCAL_SRC_FILES:= $(commonSources) $(hostSources)
-
-ifeq ($(HOST_OS),linux)
-# Use the futex based mutex and condition variable
-# implementation from android-arm because it's shared mem safe
-	LOCAL_SRC_FILES += \
-		futex_synchro.c \
-		executablepath_linux.cpp
-endif
-ifeq ($(HOST_OS),darwin)
-	LOCAL_SRC_FILES += \
-		executablepath_darwin.cpp
-endif
+LOCAL_SRC_FILES:= $(commonSources)
 
 LOCAL_MODULE:= libutils
 
@@ -103,37 +75,18 @@
 # we have the common sources, plus some device-specific stuff
 LOCAL_SRC_FILES:= \
 	$(commonSources) \
-	Binder.cpp \
-	BpBinder.cpp \
-	IInterface.cpp \
-	IMemory.cpp \
-	IPCThreadState.cpp \
-	MemoryDealer.cpp \
-    MemoryBase.cpp \
-    MemoryHeapBase.cpp \
-    MemoryHeapPmem.cpp \
-	Parcel.cpp \
-	ProcessState.cpp \
-	IPermissionController.cpp \
-	IServiceManager.cpp \
 	Unicode.cpp \
     BackupData.cpp \
 	BackupHelpers.cpp
 
-ifeq ($(TARGET_SIMULATOR),true)
-LOCAL_SRC_FILES += $(hostSources)
-endif
-
 ifeq ($(TARGET_OS),linux)
-# Use the futex based mutex and condition variable
-# implementation from android-arm because it's shared mem safe
-LOCAL_SRC_FILES += futex_synchro.c
 LOCAL_LDLIBS += -lrt -ldl
 endif
 
 LOCAL_C_INCLUDES += \
 		external/zlib \
 		external/icu4c/common
+
 LOCAL_LDLIBS += -lpthread
 
 LOCAL_SHARED_LIBRARIES := \
@@ -144,15 +97,10 @@
 ifneq ($(TARGET_SIMULATOR),true)
 ifeq ($(TARGET_OS)-$(TARGET_ARCH),linux-x86)
 # This is needed on x86 to bring in dl_iterate_phdr for CallStack.cpp
-LOCAL_SHARED_LIBRARIES += \
-	libdl
+LOCAL_SHARED_LIBRARIES += libdl
 endif # linux-x86
 endif # sim
 
 LOCAL_MODULE:= libutils
-
-#LOCAL_CFLAGS+=
-#LOCAL_LDFLAGS:=
-
 include $(BUILD_SHARED_LIBRARY)
 
diff --git a/libs/utils/BackupData.cpp b/libs/utils/BackupData.cpp
index cce754a..adb3174 100644
--- a/libs/utils/BackupData.cpp
+++ b/libs/utils/BackupData.cpp
@@ -107,7 +107,7 @@
     } else {
         k = key;
     }
-    if (true) {
+    if (false) {
         LOGD("Writing entity: prefix='%s' key='%s' dataSize=%d", m_keyPrefix.string(), key.string(),
                 dataSize);
     }
@@ -193,8 +193,11 @@
         if ((actual) != (expected)) { \
             if ((actual) == 0) { \
                 m_status = EIO; \
+                m_done = true; \
             } else { \
                 m_status = errno; \
+                LOGD("CHECK_SIZE(a=%ld e=%ld) failed at line %d m_status='%s'", \
+                    long(actual), long(expected), __LINE__, strerror(m_status)); \
             } \
             return m_status; \
         } \
@@ -203,6 +206,7 @@
     do { \
         status_t err = skip_padding(); \
         if (err != NO_ERROR) { \
+            LOGD("SKIP_PADDING FAILED at line %d", __LINE__); \
             m_status = err; \
             return err; \
         } \
@@ -218,10 +222,19 @@
 
     int amt;
 
-    // No error checking here, in case we're at the end of the stream.  Just let read() fail.
-    skip_padding();
+    amt = skip_padding();
+    if (amt == EIO) {
+        *done = m_done = true;
+        return NO_ERROR;
+    }
+    else if (amt != NO_ERROR) {
+        return amt;
+    }
     amt = read(m_fd, &m_header, sizeof(m_header));
     *done = m_done = (amt == 0);
+    if (*done) {
+        return NO_ERROR;
+    }
     CHECK_SIZE(amt, sizeof(m_header));
     m_pos += sizeof(m_header);
     if (type) {
@@ -298,10 +311,12 @@
     }
     if (m_header.entity.dataSize > 0) {
         int pos = lseek(m_fd, m_dataEndPos, SEEK_SET);
-        return pos == -1 ? (int)errno : (int)NO_ERROR;
-    } else {
-        return NO_ERROR;
+        if (pos == -1) {
+            return errno;
+        }
     }
+    SKIP_PADDING();
+    return NO_ERROR;
 }
 
 ssize_t
@@ -325,6 +340,10 @@
         m_status = errno;
         return -1;
     }
+    if (amt == 0) {
+        m_status = EIO;
+        m_done = true;
+    }
     m_pos += amt;
     return amt;
 }
diff --git a/libs/utils/CallStack.cpp b/libs/utils/CallStack.cpp
index 2fdaa71..55b6024 100644
--- a/libs/utils/CallStack.cpp
+++ b/libs/utils/CallStack.cpp
@@ -311,7 +311,8 @@
     } else { 
         void const* start = 0;
         name = MapInfo::mapAddressToName(ip, "<unknown>", &start);
-        snprintf(tmp, 256, "pc %08lx  %s", uintptr_t(ip)-uintptr_t(start), name);
+        snprintf(tmp, 256, "pc %08lx  %s", 
+                long(uintptr_t(ip)-uintptr_t(start)), name);
         res.append(tmp);
     }
     res.append("\n");
diff --git a/libs/utils/IDataConnection.cpp b/libs/utils/IDataConnection.cpp
deleted file mode 100644
index c6d49aa..0000000
--- a/libs/utils/IDataConnection.cpp
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2006 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/IDataConnection.h>
-
-namespace android {
-
-// ---------------------------------------------------------------------------
-
-enum
-{
-    CONNECT_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
-    DISCONNECT_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION + 1
-};
-
-class BpDataConnection : public BpInterface<IDataConnection>
-{
-public:
-    BpDataConnection::BpDataConnection(const sp<IBinder>& impl)
-        : BpInterface<IDataConnection>(impl)
-    {
-    }
-
-	virtual void connect()
-	{
-		Parcel data, reply;
-        data.writeInterfaceToken(IDataConnection::descriptor());
-		remote()->transact(CONNECT_TRANSACTION, data, &reply);
-	}
-	
-	virtual void disconnect()
-	{
-		Parcel data, reply;
-		remote()->transact(DISCONNECT_TRANSACTION, data, &reply);
-	}
-};
-
-IMPLEMENT_META_INTERFACE(DataConnection, "android.utils.IDataConnection");
-
-#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 BnDataConnection::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
-    switch(code)
-    {
-		case CONNECT_TRANSACTION:
-		{                   
-            CHECK_INTERFACE(IDataConnection, data, reply);
-			connect();
-			return NO_ERROR;
-		}    
-		
-		case DISCONNECT_TRANSACTION:
-		{                   
-            CHECK_INTERFACE(IDataConnection, data, reply);
-			disconnect();
-			return NO_ERROR;
-		}
-       
-		default:
-			return BBinder::onTransact(code, data, reply, flags);
-    }
-}
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
diff --git a/libs/utils/InetAddress.cpp b/libs/utils/InetAddress.cpp
deleted file mode 100644
index 39a0a68..0000000
--- a/libs/utils/InetAddress.cpp
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * Copyright (C) 2005 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.
- */
-
-//
-// Internet address class.
-//
-#ifdef HAVE_WINSOCK
-# include <winsock2.h>
-#else
-# include <sys/types.h>
-# include <sys/socket.h>
-# include <netinet/in.h>
-//# include <arpa/inet.h>
-# include <netdb.h>
-#endif
-
-#include <utils/inet_address.h>
-#include <utils/threads.h>
-#include <utils/Log.h>
-
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-
-using namespace android;
-
-
-/*
- * ===========================================================================
- *      InetAddress
- * ===========================================================================
- */
-
-// lock for the next couple of functions; could tuck into InetAddress
-static Mutex*   gGHBNLock;
-
-/*
- * Lock/unlock access to the hostent struct returned by gethostbyname().
- */
-static inline void lock_gethostbyname(void)
-{
-    if (gGHBNLock == NULL)
-        gGHBNLock = new Mutex;
-    gGHBNLock->lock();
-}
-static inline void unlock_gethostbyname(void)
-{
-    assert(gGHBNLock != NULL);
-    gGHBNLock->unlock();
-}
-
-
-/*
- * Constructor -- just init members.  This is private so that callers
- * are required to use getByName().
- */
-InetAddress::InetAddress(void)
-    : mAddress(NULL), mLength(-1), mName(NULL)
-{
-}
-
-/*
- * Destructor -- free address storage.
- */
-InetAddress::~InetAddress(void)
-{
-    delete[] (char*) mAddress;
-    delete[] mName;
-}
-
-/*
- * Copy constructor.
- */
-InetAddress::InetAddress(const InetAddress& orig)
-{
-    *this = orig;   // use assignment code
-}
-
-/*
- * Assignment operator.
- */
-InetAddress& InetAddress::operator=(const InetAddress& addr)
-{
-    // handle self-assignment
-    if (this == &addr)
-        return *this;
-    // copy mLength and mAddress
-    mLength = addr.mLength;
-    if (mLength > 0) {
-        mAddress = new char[mLength];
-        memcpy(mAddress, addr.mAddress, mLength);
-        LOG(LOG_DEBUG, "socket",
-            "HEY: copied %d bytes in assignment operator\n", mLength);
-    } else {
-        mAddress = NULL;
-    }
-    // copy mName
-    mName = new char[strlen(addr.mName)+1];
-    strcpy(mName, addr.mName);
-
-    return *this;
-}
-
-/*
- * Create a new object from a name or a dotted-number IP notation.
- *
- * Returns NULL on failure.
- */
-InetAddress*
-InetAddress::getByName(const char* host)
-{
-    InetAddress* newAddr = NULL;
-    struct sockaddr_in addr;
-    struct hostent* he;
-    DurationTimer hostTimer, lockTimer;
-
-    // gethostbyname() isn't reentrant, so we need to lock things until
-    // we can copy the data out.
-    lockTimer.start();
-    lock_gethostbyname();
-    hostTimer.start();
-
-    he = gethostbyname(host);
-    if (he == NULL) {
-        LOG(LOG_WARN, "socket", "WARNING: cannot resolve host %s\n", host);
-        unlock_gethostbyname();
-        return NULL;
-    }
-
-    memcpy(&addr.sin_addr, he->h_addr, he->h_length);
-    addr.sin_family = he->h_addrtype;
-    addr.sin_port = 0;
-
-    // got it, unlock us
-    hostTimer.stop();
-    he = NULL;
-    unlock_gethostbyname();
-
-    lockTimer.stop();
-    if ((long) lockTimer.durationUsecs() > 100000) {
-        long lockTime = (long) lockTimer.durationUsecs();
-        long hostTime = (long) hostTimer.durationUsecs();
-        LOG(LOG_DEBUG, "socket",
-            "Lookup of %s took %.3fs (gethostbyname=%.3fs lock=%.3fs)\n",
-            host, lockTime / 1000000.0, hostTime / 1000000.0,
-            (lockTime - hostTime) / 1000000.0);
-    }
-
-    // Alloc storage and copy it over.
-    newAddr = new InetAddress();
-    if (newAddr == NULL)
-        return NULL;
-
-    newAddr->mLength = sizeof(struct sockaddr_in);
-    newAddr->mAddress = new char[sizeof(struct sockaddr_in)];
-    if (newAddr->mAddress == NULL) {
-        delete newAddr;
-        return NULL;
-    }
-    memcpy(newAddr->mAddress, &addr, newAddr->mLength);
-
-    // Keep this for debug messages.
-    newAddr->mName = new char[strlen(host)+1];
-    if (newAddr->mName == NULL) {
-        delete newAddr;
-        return NULL;
-    }
-    strcpy(newAddr->mName, host);
-
-    return newAddr;
-}
-
-
-/*
- * ===========================================================================
- *      InetSocketAddress
- * ===========================================================================
- */
-
-/*
- * Create an address with the host wildcard (INADDR_ANY).
- */
-bool InetSocketAddress::create(int port)
-{
-    assert(mAddress == NULL);
-
-    mAddress = InetAddress::getByName("0.0.0.0");
-    if (mAddress == NULL)
-        return false;
-    mPort = port;
-    return true;
-}
-
-/*
- * Create address with host and port specified.
- */
-bool InetSocketAddress::create(const InetAddress* addr, int port)
-{
-    assert(mAddress == NULL);
-
-    mAddress = new InetAddress(*addr);  // make a copy
-    if (mAddress == NULL)
-        return false;
-    mPort = port;
-    return true;
-}
-
-/*
- * Create address with host and port specified.
- */
-bool InetSocketAddress::create(const char* host, int port)
-{
-    assert(mAddress == NULL);
-
-    mAddress = InetAddress::getByName(host);
-    if (mAddress == NULL)
-        return false;
-    mPort = port;
-    return true;
-}
-
diff --git a/libs/utils/LogSocket.cpp b/libs/utils/LogSocket.cpp
deleted file mode 100644
index 55c1b99..0000000
--- a/libs/utils/LogSocket.cpp
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * 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.
- */
-
-
-#ifndef HAVE_WINSOCK
-//#define SOCKETLOG
-#endif
-
-#ifdef SOCKETLOG
-
-#define LOG_TAG "SOCKETLOG"
-
-#include <string.h>
-#include <cutils/log.h>
-#include "utils/LogSocket.h"
-#include "utils/logger.h"
-#include "cutils/hashmap.h"
-
-// defined in //device/data/etc/event-log-tags
-#define SOCKET_CLOSE_LOG 51000
-
-static Hashmap* statsMap = NULL;
-
-#define LOG_LIST_NUMBER 5
-
-typedef struct SocketStats {
-    int fd;
-    unsigned int send;
-    unsigned int recv;
-    unsigned int ip;
-    unsigned short port;
-    short reason;
-}SocketStats;
-
-SocketStats *get_socket_stats(int fd) {
-    if (statsMap == NULL) {
-        statsMap = hashmapCreate(8, &hashmapIntHash, &hashmapIntEquals);
-    }
-
-    SocketStats *s = (SocketStats*) hashmapGet(statsMap, &fd);
-    if (s == NULL) {
-        // LOGD("create SocketStats for fd %d", fd);
-        s = (SocketStats*) malloc(sizeof(SocketStats));
-        memset(s, 0, sizeof(SocketStats));
-        s->fd = fd;
-        hashmapPut(statsMap, &s->fd, s);
-    }
-    return s;
-}
-
-void log_socket_connect(int fd, unsigned int ip, unsigned short port) {
-    // LOGD("log_socket_connect for fd %d ip %d port%d", fd, ip, port);
-    SocketStats *s = get_socket_stats(fd);
-    s->ip = ip;
-    s->port = port;
-}
-
-void add_send_stats(int fd, int send) {
-    if (send <=0) {
-        LOGE("add_send_stats send %d", send);
-        return;
-    }
-    SocketStats *s = get_socket_stats(fd);
-    s->send += send;
-    // LOGD("add_send_stats for fd %d ip %d port%d", fd, s->ip, s->port);
-}
-
-void add_recv_stats(int fd, int recv) {
-    if (recv <=0) {
-        LOGE("add_recv_stats recv %d", recv);
-        return;
-    }
-    SocketStats *s = get_socket_stats(fd);
-    s->recv += recv;
-    // LOGD("add_recv_stats for fd %d ip %d port%d", fd, s->ip, s->port);
-}
-
-char* put_int(char* buf, int value) {
-    *buf = EVENT_TYPE_INT;
-    buf++;
-    memcpy(buf, &value, sizeof(int));
-    return buf + sizeof(int);
-}
-
-void log_socket_close(int fd, short reason) {
-    if (statsMap) {
-        SocketStats *s = (SocketStats*) hashmapGet(statsMap, &fd);
-        if (s != NULL) {
-            if (s->send != 0 || s->recv != 0) {
-                s->reason = reason;
-                // 5 int + list type need 2 bytes
-                char buf[LOG_LIST_NUMBER * 5 + 2];
-                buf[0] = EVENT_TYPE_LIST;
-                buf[1] = LOG_LIST_NUMBER;
-                char* writePos = buf + 2;
-                writePos = put_int(writePos, s->send);
-                writePos = put_int(writePos, s->recv);
-                writePos = put_int(writePos, s->ip);
-                writePos = put_int(writePos, s->port);
-                writePos = put_int(writePos, s->reason);
-                
-                android_bWriteLog(SOCKET_CLOSE_LOG, buf, sizeof(buf));
-                // LOGD("send %d recv %d reason %d", s->send, s->recv, s->reason);
-            }
-            hashmapRemove(statsMap, &s->fd);
-            free(s);
-        }
-    }
-}
-
-#else
-void add_send_stats(int fd, int send) {} 
-void add_recv_stats(int fd, int recv) {}
-void log_socket_close(int fd, short reason) {}
-void log_socket_connect(int fd, unsigned int ip, unsigned short port) {}
-#endif
diff --git a/libs/utils/Pipe.cpp b/libs/utils/Pipe.cpp
deleted file mode 100644
index 613906b..0000000
--- a/libs/utils/Pipe.cpp
+++ /dev/null
@@ -1,465 +0,0 @@
-/*
- * Copyright (C) 2005 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.
- */
-
-//
-// Unidirectional pipe.
-//
-
-#include <utils/Pipe.h>
-#include <utils/Log.h>
-
-#if defined(HAVE_WIN32_IPC)
-# include <windows.h>
-#else
-# include <fcntl.h>
-# include <unistd.h>
-# include <errno.h>
-#endif
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <assert.h>
-#include <string.h>
-
-using namespace android;
-
-const unsigned long kInvalidHandle = (unsigned long) -1;
-
-
-/*
- * Constructor.  Do little.
- */
-Pipe::Pipe(void)
-    : mReadNonBlocking(false), mReadHandle(kInvalidHandle),
-      mWriteHandle(kInvalidHandle)
-{
-}
-
-/*
- * Destructor.  Use the system-appropriate close call.
- */
-Pipe::~Pipe(void)
-{
-#if defined(HAVE_WIN32_IPC)
-    if (mReadHandle != kInvalidHandle) {
-        if (!CloseHandle((HANDLE)mReadHandle))
-            LOG(LOG_WARN, "pipe", "failed closing read handle (%ld)\n",
-                mReadHandle);
-    }
-    if (mWriteHandle != kInvalidHandle) {
-        FlushFileBuffers((HANDLE)mWriteHandle);
-        if (!CloseHandle((HANDLE)mWriteHandle))
-            LOG(LOG_WARN, "pipe", "failed closing write handle (%ld)\n",
-                mWriteHandle);
-    }
-#else
-    if (mReadHandle != kInvalidHandle) {
-        if (close((int) mReadHandle) != 0)
-            LOG(LOG_WARN, "pipe", "failed closing read fd (%d)\n",
-                (int) mReadHandle);
-    }
-    if (mWriteHandle != kInvalidHandle) {
-        if (close((int) mWriteHandle) != 0)
-            LOG(LOG_WARN, "pipe", "failed closing write fd (%d)\n",
-                (int) mWriteHandle);
-    }
-#endif
-}
-
-/*
- * Create the pipe.
- *
- * Use the POSIX stuff for everything but Windows.
- */
-bool Pipe::create(void)
-{
-    assert(mReadHandle == kInvalidHandle);
-    assert(mWriteHandle == kInvalidHandle);
-
-#if defined(HAVE_WIN32_IPC)
-    /* we use this across processes, so they need to be inheritable */
-    HANDLE handles[2];
-    SECURITY_ATTRIBUTES saAttr;
-
-    saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
-    saAttr.bInheritHandle = TRUE;
-    saAttr.lpSecurityDescriptor = NULL;
-
-    if (!CreatePipe(&handles[0], &handles[1], &saAttr, 0)) {
-        LOG(LOG_ERROR, "pipe", "unable to create pipe\n");
-        return false;
-    }
-    mReadHandle = (unsigned long) handles[0];
-    mWriteHandle = (unsigned long) handles[1];
-    return true;
-#else
-    int fds[2];
-
-    if (pipe(fds) != 0) {
-        LOG(LOG_ERROR, "pipe", "unable to create pipe\n");
-        return false;
-    }
-    mReadHandle = fds[0];
-    mWriteHandle = fds[1];
-    return true;
-#endif
-}
-
-/*
- * Create a "half pipe".  Please, no Segway riding.
- */
-bool Pipe::createReader(unsigned long handle)
-{
-    mReadHandle = handle;
-    assert(mWriteHandle == kInvalidHandle);
-    return true;
-}
-
-/*
- * Create a "half pipe" for writing.
- */
-bool Pipe::createWriter(unsigned long handle)
-{
-    mWriteHandle = handle;
-    assert(mReadHandle == kInvalidHandle);
-    return true;
-}
-
-/*
- * Return "true" if create() has been called successfully.
- */
-bool Pipe::isCreated(void)
-{
-    // one or the other should be open
-    return (mReadHandle != kInvalidHandle || mWriteHandle != kInvalidHandle);
-}
-
-
-/*
- * Read data from the pipe.
- *
- * For Linux and Darwin, just call read().  For Windows, implement
- * non-blocking reads by calling PeekNamedPipe first.
- */
-int Pipe::read(void* buf, int count)
-{
-    assert(mReadHandle != kInvalidHandle);
-
-#if defined(HAVE_WIN32_IPC)
-    DWORD totalBytesAvail = count;
-    DWORD bytesRead;
-
-    if (mReadNonBlocking) {
-        // use PeekNamedPipe to adjust read count expectations
-        if (!PeekNamedPipe((HANDLE) mReadHandle, NULL, 0, NULL,
-                &totalBytesAvail, NULL))
-        {
-            LOG(LOG_ERROR, "pipe", "PeekNamedPipe failed\n");
-            return -1;
-        }
-
-        if (totalBytesAvail == 0)
-            return 0;
-    }
-
-    if (!ReadFile((HANDLE) mReadHandle, buf, totalBytesAvail, &bytesRead,
-            NULL))
-    {
-        DWORD err = GetLastError();
-        if (err == ERROR_HANDLE_EOF || err == ERROR_BROKEN_PIPE)
-            return 0;
-        LOG(LOG_ERROR, "pipe", "ReadFile failed (err=%ld)\n", err);
-        return -1;
-    }
-
-    return (int) bytesRead;
-#else
-    int cc;
-    cc = ::read(mReadHandle, buf, count);
-    if (cc < 0 && errno == EAGAIN)
-        return 0;
-    return cc;
-#endif
-}
-
-/*
- * Write data to the pipe.
- *
- * POSIX systems are trivial, Windows uses a different call and doesn't
- * handle non-blocking writes.
- *
- * If we add non-blocking support here, we probably want to make it an
- * all-or-nothing write.
- *
- * DO NOT use LOG() here, we could be writing a log message.
- */
-int Pipe::write(const void* buf, int count)
-{
-    assert(mWriteHandle != kInvalidHandle);
-
-#if defined(HAVE_WIN32_IPC)
-    DWORD bytesWritten;
-
-    if (mWriteNonBlocking) {
-        // BUG: can't use PeekNamedPipe() to get the amount of space
-        // left.  Looks like we need to use "overlapped I/O" functions.
-        // I just don't care that much.
-    }
-
-    if (!WriteFile((HANDLE) mWriteHandle, buf, count, &bytesWritten, NULL)) {
-        // can't LOG, use stderr
-        fprintf(stderr, "WriteFile failed (err=%ld)\n", GetLastError());
-        return -1;
-    }
-
-    return (int) bytesWritten;
-#else
-    int cc;
-    cc = ::write(mWriteHandle, buf, count);
-    if (cc < 0 && errno == EAGAIN)
-        return 0;
-    return cc;
-#endif
-}
-
-/*
- * Figure out if there is data available on the read fd.
- *
- * We return "true" on error because we want the caller to try to read
- * from the pipe.  They'll notice the read failure and do something
- * appropriate.
- */
-bool Pipe::readReady(void)
-{
-    assert(mReadHandle != kInvalidHandle);
-
-#if defined(HAVE_WIN32_IPC)
-    DWORD totalBytesAvail;
-
-    if (!PeekNamedPipe((HANDLE) mReadHandle, NULL, 0, NULL,
-            &totalBytesAvail, NULL))
-    {
-        LOG(LOG_ERROR, "pipe", "PeekNamedPipe failed\n");
-        return true;
-    }
-
-    return (totalBytesAvail != 0);
-#else
-    errno = 0;
-    fd_set readfds;
-    struct timeval tv = { 0, 0 };
-    int cc;
-
-    FD_ZERO(&readfds);
-    FD_SET(mReadHandle, &readfds);
-
-    cc = select(mReadHandle+1, &readfds, NULL, NULL, &tv);
-    if (cc < 0) {
-        LOG(LOG_ERROR, "pipe", "select() failed\n");
-        return true;
-    } else if (cc == 0) {
-        /* timed out, nothing available */
-        return false;
-    } else if (cc == 1) {
-        /* our fd is ready */
-        return true;
-    } else {
-        LOG(LOG_ERROR, "pipe", "HUH? select() returned > 1\n");
-        return true;
-    }
-#endif
-}
-
-/*
- * Enable or disable non-blocking mode for the read descriptor.
- *
- * NOTE: the calls succeed under Mac OS X, but the pipe doesn't appear to
- * actually be in non-blocking mode.  If this matters -- i.e. you're not
- * using a select() call -- put a call to readReady() in front of the
- * ::read() call, with a PIPE_NONBLOCK_BROKEN #ifdef in the Makefile for
- * Darwin.
- */
-bool Pipe::setReadNonBlocking(bool val)
-{
-    assert(mReadHandle != kInvalidHandle);
-
-#if defined(HAVE_WIN32_IPC)
-    // nothing to do
-#else
-    int flags;
-
-    if (fcntl(mReadHandle, F_GETFL, &flags) == -1) {
-        LOG(LOG_ERROR, "pipe", "couldn't get flags for pipe read fd\n");
-        return false;
-    }
-    if (val)
-        flags |= O_NONBLOCK;
-    else
-        flags &= ~(O_NONBLOCK);
-    if (fcntl(mReadHandle, F_SETFL, &flags) == -1) {
-        LOG(LOG_ERROR, "pipe", "couldn't set flags for pipe read fd\n");
-        return false;
-    }
-#endif
-
-    mReadNonBlocking = val;
-    return true;
-}
-
-/*
- * Enable or disable non-blocking mode for the write descriptor.
- *
- * As with setReadNonBlocking(), this does not work on the Mac.
- */
-bool Pipe::setWriteNonBlocking(bool val)
-{
-    assert(mWriteHandle != kInvalidHandle);
-
-#if defined(HAVE_WIN32_IPC)
-    // nothing to do
-#else
-    int flags;
-
-    if (fcntl(mWriteHandle, F_GETFL, &flags) == -1) {
-        LOG(LOG_WARN, "pipe",
-            "Warning: couldn't get flags for pipe write fd (errno=%d)\n",
-            errno);
-        return false;
-    }
-    if (val)
-        flags |= O_NONBLOCK;
-    else
-        flags &= ~(O_NONBLOCK);
-    if (fcntl(mWriteHandle, F_SETFL, &flags) == -1) {
-        LOG(LOG_WARN, "pipe",
-            "Warning: couldn't set flags for pipe write fd (errno=%d)\n",
-            errno);
-        return false;
-    }
-#endif
-
-    mWriteNonBlocking = val;
-    return true;
-}
-
-/*
- * Specify whether a file descriptor can be inherited by a child process.
- * Under Linux this means setting the close-on-exec flag, under Windows
- * this is SetHandleInformation(HANDLE_FLAG_INHERIT).
- */
-bool Pipe::disallowReadInherit(void)
-{
-    if (mReadHandle == kInvalidHandle)
-        return false;
-
-#if defined(HAVE_WIN32_IPC)
-    if (SetHandleInformation((HANDLE) mReadHandle, HANDLE_FLAG_INHERIT, 0) == 0)
-        return false;
-#else
-    if (fcntl((int) mReadHandle, F_SETFD, FD_CLOEXEC) != 0)
-        return false;
-#endif
-    return true;
-}
-bool Pipe::disallowWriteInherit(void)
-{
-    if (mWriteHandle == kInvalidHandle)
-        return false;
-
-#if defined(HAVE_WIN32_IPC)
-    if (SetHandleInformation((HANDLE) mWriteHandle, HANDLE_FLAG_INHERIT, 0) == 0)
-        return false;
-#else
-    if (fcntl((int) mWriteHandle, F_SETFD, FD_CLOEXEC) != 0)
-        return false;
-#endif
-    return true;
-}
-
-/*
- * Close read descriptor.
- */
-bool Pipe::closeRead(void)
-{
-    if (mReadHandle == kInvalidHandle)
-        return false;
-
-#if defined(HAVE_WIN32_IPC)
-    if (mReadHandle != kInvalidHandle) {
-        if (!CloseHandle((HANDLE)mReadHandle)) {
-            LOG(LOG_WARN, "pipe", "failed closing read handle\n");
-            return false;
-        }
-    }
-#else
-    if (mReadHandle != kInvalidHandle) {
-        if (close((int) mReadHandle) != 0) {
-            LOG(LOG_WARN, "pipe", "failed closing read fd\n");
-            return false;
-        }
-    }
-#endif
-    mReadHandle = kInvalidHandle;
-    return true;
-}
-
-/*
- * Close write descriptor.
- */
-bool Pipe::closeWrite(void)
-{
-    if (mWriteHandle == kInvalidHandle)
-        return false;
-
-#if defined(HAVE_WIN32_IPC)
-    if (mWriteHandle != kInvalidHandle) {
-        if (!CloseHandle((HANDLE)mWriteHandle)) {
-            LOG(LOG_WARN, "pipe", "failed closing write handle\n");
-            return false;
-        }
-    }
-#else
-    if (mWriteHandle != kInvalidHandle) {
-        if (close((int) mWriteHandle) != 0) {
-            LOG(LOG_WARN, "pipe", "failed closing write fd\n");
-            return false;
-        }
-    }
-#endif
-    mWriteHandle = kInvalidHandle;
-    return true;
-}
-
-/*
- * Get the read handle.
- */
-unsigned long Pipe::getReadHandle(void)
-{
-    assert(mReadHandle != kInvalidHandle);
-
-    return mReadHandle;
-}
-
-/*
- * Get the write handle.
- */
-unsigned long Pipe::getWriteHandle(void)
-{
-    assert(mWriteHandle != kInvalidHandle);
-
-    return mWriteHandle;
-}
-
diff --git a/libs/utils/ResourceTypes.cpp b/libs/utils/ResourceTypes.cpp
index 0831f4a..872b2bc 100644
--- a/libs/utils/ResourceTypes.cpp
+++ b/libs/utils/ResourceTypes.cpp
@@ -1740,7 +1740,11 @@
     const int e = Res_GETENTRY(resID);
 
     if (p < 0) {
-        LOGW("No package identifier when getting name for resource number 0x%08x", resID);
+        if (Res_GETPACKAGE(resID)+1 == 0) {
+            LOGW("No package identifier when getting name for resource number 0x%08x", resID);
+        } else {
+            LOGW("Resources don't contain package for resource number 0x%08x", resID);
+        }
         return false;
     }
     if (t < 0) {
@@ -1786,7 +1790,11 @@
     const int e = Res_GETENTRY(resID);
 
     if (p < 0) {
-        LOGW("No package identifier when getting value for resource number 0x%08x", resID);
+        if (Res_GETPACKAGE(resID)+1 == 0) {
+            LOGW("No package identifier when getting name for resource number 0x%08x", resID);
+        } else {
+            LOGW("Resources don't contain package for resource number 0x%08x", resID);
+        }
         return BAD_INDEX;
     }
     if (t < 0) {
@@ -3284,7 +3292,16 @@
                     break;
                 }
                 if (c == '\'' && (quoted == 0 || quoted == '\'')) {
-                    break;
+                    /*
+                     * In practice, when people write ' instead of \'
+                     * in a string, they are doing it by accident
+                     * instead of really meaning to use ' as a quoting
+                     * character.  Warn them so they don't lose it.
+                     */
+                    if (outErrorMsg) {
+                        *outErrorMsg = "Apostrophe not preceded by \\";
+                    }
+                    return false;
                 }
             }
             p++;
diff --git a/libs/utils/Socket.cpp b/libs/utils/Socket.cpp
deleted file mode 100644
index 51509a3..0000000
--- a/libs/utils/Socket.cpp
+++ /dev/null
@@ -1,388 +0,0 @@
-/*
- * Copyright (C) 2005 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.
- */
-
-//
-// Internet address class.
-//
-
-#ifdef HAVE_WINSOCK
-// This needs to come first, or Cygwin gets concerned about a potential
-// clash between WinSock and <sys/types.h>.
-# include <winsock2.h>
-#endif
-
-#include <utils/Socket.h>
-#include <utils/inet_address.h>
-#include <utils/Log.h>
-#include <utils/Timers.h>
-
-#ifndef HAVE_WINSOCK
-# include <sys/types.h>
-# include <sys/socket.h>
-# include <netinet/in.h>
-# include <arpa/inet.h>
-#endif
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <assert.h>
-
-using namespace android;
-
-
-/*
- * ===========================================================================
- *      Socket
- * ===========================================================================
- */
-
-#ifndef INVALID_SOCKET
-# define INVALID_SOCKET (-1)
-#endif
-#define UNDEF_SOCKET   ((unsigned long) INVALID_SOCKET)
-
-/*static*/ bool Socket::mBootInitialized = false;
-
-/*
- * Extract system-dependent error code.
- */
-static inline int getSocketError(void) {
-#ifdef HAVE_WINSOCK
-    return WSAGetLastError();
-#else
-    return errno;
-#endif
-}
-
-/*
- * One-time initialization for socket code.
- */
-/*static*/ bool Socket::bootInit(void)
-{
-#ifdef HAVE_WINSOCK
-    WSADATA wsaData;
-    int err;
-
-    err = WSAStartup(MAKEWORD(2, 0), &wsaData);
-    if (err != 0) {
-        LOG(LOG_ERROR, "socket", "Unable to start WinSock\n");
-        return false;
-    }
-
-    LOG(LOG_INFO, "socket", "Using WinSock v%d.%d\n",
-        LOBYTE(wsaData.wVersion), HIBYTE(wsaData.wVersion));
-#endif
-
-    mBootInitialized = true;
-    return true;
-}
-
-/*
- * One-time shutdown for socket code.
- */
-/*static*/ void Socket::finalShutdown(void)
-{
-#ifdef HAVE_WINSOCK
-    WSACleanup();
-#endif
-    mBootInitialized = false;
-}
-
-
-/*
- * Simple constructor.  Allow the application to create us and then make
- * bind/connect calls.
- */
-Socket::Socket(void)
-    : mSock(UNDEF_SOCKET)
-{
-    if (!mBootInitialized)
-        LOG(LOG_WARN, "socket", "WARNING: sockets not initialized\n");
-}
-
-/*
- * Destructor.  Closes the socket and resets our storage.
- */
-Socket::~Socket(void)
-{
-    close();
-}
-
-
-/*
- * Create a socket and connect to the specified host and port.
- */
-int Socket::connect(const char* host, int port)
-{
-    if (mSock != UNDEF_SOCKET) {
-        LOG(LOG_WARN, "socket", "Socket already connected\n");
-        return -1;
-    }
-
-    InetSocketAddress sockAddr;
-    if (!sockAddr.create(host, port))
-        return -1;
-
-    //return doConnect(sockAddr);
-    int foo;
-    foo = doConnect(sockAddr);
-    return foo;
-}
-
-/*
- * Create a socket and connect to the specified host and port.
- */
-int Socket::connect(const InetAddress* addr, int port)
-{
-    if (mSock != UNDEF_SOCKET) {
-        LOG(LOG_WARN, "socket", "Socket already connected\n");
-        return -1;
-    }
-
-    InetSocketAddress sockAddr;
-    if (!sockAddr.create(addr, port))
-        return -1;
-
-    return doConnect(sockAddr);
-}
-
-/*
- * Finish creating a socket by connecting to the remote host.
- *
- * Returns 0 on success.
- */
-int Socket::doConnect(const InetSocketAddress& sockAddr)
-{
-#ifdef HAVE_WINSOCK
-    SOCKET sock;
-#else
-    int sock;
-#endif
-    const InetAddress* addr = sockAddr.getAddress();
-    int port = sockAddr.getPort();
-    struct sockaddr_in inaddr;
-    DurationTimer connectTimer;
-
-    assert(sizeof(struct sockaddr_in) == addr->getAddressLength());
-    memcpy(&inaddr, addr->getAddress(), addr->getAddressLength());
-    inaddr.sin_port = htons(port);
-
-    //fprintf(stderr, "--- connecting to %s:%d\n",
-    //    sockAddr.getHostName(), port);
-
-    sock = ::socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
-    if (sock == INVALID_SOCKET) {
-        int err = getSocketError();
-        LOG(LOG_ERROR, "socket", "Unable to create socket (err=%d)\n", err);
-        return (err != 0) ? err : -1;
-    }
-
-    connectTimer.start();
-
-    if (::connect(sock, (struct sockaddr*) &inaddr, sizeof(inaddr)) != 0) {
-        int err = getSocketError();
-        LOG(LOG_WARN, "socket", "Connect to %s:%d failed: %d\n",
-            sockAddr.getHostName(), port, err);
-        return (err != 0) ? err : -1;
-    }
-
-    connectTimer.stop();
-    if ((long) connectTimer.durationUsecs() > 100000) {
-        LOG(LOG_INFO, "socket",
-            "Connect to %s:%d took %.3fs\n", sockAddr.getHostName(),
-            port, ((long) connectTimer.durationUsecs()) / 1000000.0);
-    }
-
-    mSock = (unsigned long) sock;
-    LOG(LOG_VERBOSE, "socket",
-        "--- connected to %s:%d\n", sockAddr.getHostName(), port);
-    return 0;
-}
-
-
-/*
- * Close the socket if it needs closing.
- */
-bool Socket::close(void)
-{
-    if (mSock != UNDEF_SOCKET) {
-        //fprintf(stderr, "--- closing socket %lu\n", mSock);
-#ifdef HAVE_WINSOCK
-        if (::closesocket((SOCKET) mSock) != 0)
-            return false;
-#else
-        if (::close((int) mSock) != 0)
-            return false;
-#endif
-    }
-
-    mSock = UNDEF_SOCKET;
-
-    return true;
-}
-
-/*
- * Read data from socket.
- *
- * Standard semantics: read up to "len" bytes into "buf".  Returns the
- * number of bytes read, or less than zero on error.
- */
-int Socket::read(void* buf, ssize_t len) const
-{
-    if (mSock == UNDEF_SOCKET) {
-        LOG(LOG_ERROR, "socket", "ERROR: read on invalid socket\n");
-        return -500;
-    }
-
-#ifdef HAVE_WINSOCK
-    SOCKET sock = (SOCKET) mSock;
-#else
-    int sock = (int) mSock;
-#endif
-    int cc;
-
-    cc = recv(sock, (char*)buf, len, 0);
-    if (cc < 0) {
-        int err = getSocketError();
-        return (err > 0) ? -err : -1;
-    }
-
-    return cc;
-}
-
-/*
- * Write data to a socket.
- *
- * Standard semantics: write up to "len" bytes into "buf".  Returns the
- * number of bytes written, or less than zero on error.
- */
-int Socket::write(const void* buf, ssize_t len) const
-{
-    if (mSock == UNDEF_SOCKET) {
-        LOG(LOG_ERROR, "socket", "ERROR: write on invalid socket\n");
-        return -500;
-    }
-
-#ifdef HAVE_WINSOCK
-    SOCKET sock = (SOCKET) mSock;
-#else
-    int sock = (int) mSock;
-#endif
-    int cc;
-
-    cc = send(sock, (const char*)buf, len, 0);
-    if (cc < 0) {
-        int err = getSocketError();
-        return (err > 0) ? -err : -1;
-    }
-
-    return cc;
-}
-
-
-/*
- * ===========================================================================
- *      Socket tests
- * ===========================================================================
- */
-
-/*
- * Read all data from the socket.  The data is read into a buffer that
- * expands as needed.
- *
- * On exit, the buffer is returned, and the length of the data is stored
- * in "*sz".  A null byte is added to the end, but is not included in
- * the length.
- */
-static char* socketReadAll(const Socket& s, int *sz)
-{
-    int max, r;
-    char *data, *ptr, *tmp;
-
-    data = (char*) malloc(max = 32768);
-    if (data == NULL)
-        return NULL;
-
-    ptr = data;
-    
-    for (;;) {
-        if ((ptr - data) == max) {
-            tmp = (char*) realloc(data, max *= 2);
-            if(tmp == 0) {
-                free(data);
-                return 0;
-            }
-        }
-        r = s.read(ptr, max - (ptr - data));
-        if (r == 0)
-            break;
-        if (r < 0) {
-            LOG(LOG_WARN, "socket", "WARNING: socket read failed (res=%d)\n",r);
-            break;
-        }
-        ptr += r;
-    }
-
-    if ((ptr - data) == max) {
-        tmp = (char*) realloc(data, max + 1);
-        if (tmp == NULL) {
-            free(data);
-            return NULL;
-        }
-    }
-    *ptr = '\0';
-    *sz = (ptr - data);
-    return data;
-}
-
-/*
- * Exercise the Socket class.
- */
-void android::TestSockets(void)
-{
-    printf("----- SOCKET TEST ------\n");
-    Socket::bootInit();
-
-    char* buf = NULL;
-    int len, cc;
-    const char* kTestStr =
-        "GET / HTTP/1.0\n"
-        "Connection: close\n"
-        "\n";
-
-    Socket sock;
-    if (sock.connect("www.google.com", 80) != 0) {
-        fprintf(stderr, "socket connected failed\n");
-        goto bail;
-    }
-
-    cc = sock.write(kTestStr, strlen(kTestStr));
-    if (cc != (int) strlen(kTestStr)) {
-        fprintf(stderr, "write failed, res=%d\n", cc);
-        goto bail;
-    }
-    buf = socketReadAll(sock, &len);
-
-    printf("GOT '%s'\n", buf);
-
-bail:
-    sock.close();
-    free(buf);
-}
-
diff --git a/libs/utils/Static.cpp b/libs/utils/Static.cpp
index 93f7e4f..4dfa578 100644
--- a/libs/utils/Static.cpp
+++ b/libs/utils/Static.cpp
@@ -20,7 +20,6 @@
 #include <private/utils/Static.h>
 
 #include <utils/BufferedTextOutput.h>
-#include <utils/IPCThreadState.h>
 #include <utils/Log.h>
 
 namespace android {
@@ -87,34 +86,4 @@
 TextOutput& aout(gStdoutTextOutput);
 TextOutput& aerr(gStderrTextOutput);
 
-#ifndef LIBUTILS_NATIVE
-
-// ------------ ProcessState.cpp
-
-Mutex gProcessMutex;
-sp<ProcessState> gProcess;
-
-class LibUtilsIPCtStatics
-{
-public:
-    LibUtilsIPCtStatics()
-    {
-    }
-    
-    ~LibUtilsIPCtStatics()
-    {
-        IPCThreadState::shutdown();
-    }
-};
-
-static LibUtilsIPCtStatics gIPCStatics;
-
-// ------------ ServiceManager.cpp
-
-Mutex gDefaultServiceManagerLock;
-sp<IServiceManager> gDefaultServiceManager;
-sp<IPermissionController> gPermissionController;
-
-#endif
-
 }   // namespace android
diff --git a/libs/utils/StringArray.cpp b/libs/utils/StringArray.cpp
new file mode 100644
index 0000000..aa42d68
--- /dev/null
+++ b/libs/utils/StringArray.cpp
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+//
+// Sortable array of strings.  STL-ish, but STL-free.
+//  
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <utils/StringArray.h>
+
+namespace android {
+
+//
+// An expanding array of strings.  Add, get, sort, delete.
+//
+StringArray::StringArray()
+    : mMax(0), mCurrent(0), mArray(NULL)
+{
+}
+
+StringArray:: ~StringArray() {
+    for (int i = 0; i < mCurrent; i++)
+        delete[] mArray[i];
+    delete[] mArray;
+}
+
+//
+// Add a string.  A copy of the string is made.
+//
+bool StringArray::push_back(const char* str) {
+    if (mCurrent >= mMax) {
+        char** tmp;
+
+        if (mMax == 0)
+            mMax = 16;      // initial storage
+        else
+            mMax *= 2;
+
+        tmp = new char*[mMax];
+        if (tmp == NULL)
+            return false;
+
+        memcpy(tmp, mArray, mCurrent * sizeof(char*));
+        delete[] mArray;
+        mArray = tmp;
+    }
+
+    int len = strlen(str);
+    mArray[mCurrent] = new char[len+1];
+    memcpy(mArray[mCurrent], str, len+1);
+    mCurrent++;
+
+    return true;
+}
+
+//
+// Delete an entry.
+//
+void StringArray::erase(int idx) {
+    if (idx < 0 || idx >= mCurrent)
+        return;
+    delete[] mArray[idx];
+    if (idx < mCurrent-1) {
+        memmove(&mArray[idx], &mArray[idx+1],
+                (mCurrent-1 - idx) * sizeof(char*));
+    }
+    mCurrent--;
+}
+
+//
+// Sort the array.
+//
+void StringArray::sort(int (*compare)(const void*, const void*)) {
+    qsort(mArray, mCurrent, sizeof(char*), compare);
+}
+
+//
+// Pass this to the sort routine to do an ascending alphabetical sort.
+//
+int StringArray::cmpAscendingAlpha(const void* pstr1, const void* pstr2) {
+    return strcmp(*(const char**)pstr1, *(const char**)pstr2);
+}
+
+//
+// Set entry N to specified string.
+// [should use operator[] here]
+//
+void StringArray::setEntry(int idx, const char* str) {
+    if (idx < 0 || idx >= mCurrent)
+        return;
+    delete[] mArray[idx];
+    int len = strlen(str);
+    mArray[idx] = new char[len+1];
+    memcpy(mArray[idx], str, len+1);
+}
+
+
+}; // namespace android
diff --git a/libs/utils/TextOutput.cpp b/libs/utils/TextOutput.cpp
index cebee99..e04823d 100644
--- a/libs/utils/TextOutput.cpp
+++ b/libs/utils/TextOutput.cpp
@@ -22,9 +22,17 @@
 #include <stdlib.h>
 #include <string.h>
 
+namespace android {
+
 // ---------------------------------------------------------------------------
 
-namespace android {
+TextOutput::TextOutput() { 
+}
+
+TextOutput::~TextOutput() { 
+}
+
+// ---------------------------------------------------------------------------
 
 TextOutput& operator<<(TextOutput& to, bool val)
 {
diff --git a/libs/utils/Threads.cpp b/libs/utils/Threads.cpp
index 9287c0b..ec3db09 100644
--- a/libs/utils/Threads.cpp
+++ b/libs/utils/Threads.cpp
@@ -38,10 +38,6 @@
 # define HAVE_CREATETHREAD  // Cygwin, vs. HAVE__BEGINTHREADEX for MinGW
 #endif
 
-#if defined(HAVE_FUTEX)
-#include <private/utils/futex_synchro.h>
-#endif
-
 #if defined(HAVE_PRCTL)
 #include <sys/prctl.h>
 #endif
@@ -56,10 +52,6 @@
 
 // ----------------------------------------------------------------------------
 #if defined(HAVE_PTHREADS)
-#if 0
-#pragma mark -
-#pragma mark PTHREAD
-#endif
 // ----------------------------------------------------------------------------
 
 /*
@@ -163,10 +155,6 @@
 
 // ----------------------------------------------------------------------------
 #elif defined(HAVE_WIN32_THREADS)
-#if 0
-#pragma mark -
-#pragma mark WIN32_THREADS
-#endif
 // ----------------------------------------------------------------------------
 
 /*
@@ -252,11 +240,6 @@
 
 // ----------------------------------------------------------------------------
 
-#if 0
-#pragma mark -
-#pragma mark Common Thread functions
-#endif
-
 int androidCreateThread(android_thread_func_t fn, void* arg)
 {
     return createThreadEtc(fn, arg);
@@ -294,109 +277,9 @@
  * ===========================================================================
  */
 
-#if 0
-#pragma mark -
-#pragma mark Mutex
-#endif
-
-#if defined(HAVE_PTHREADS) && !defined(HAVE_FUTEX)
-/*
- * Simple pthread wrapper.
- */
-
-Mutex::Mutex()
-{
-    _init();
-}
-
-Mutex::Mutex(const char* name)
-{
-    // XXX: name not used for now
-    _init();
-}
-
-void Mutex::_init()
-{
-    pthread_mutex_t* pMutex = new pthread_mutex_t;
-    pthread_mutex_init(pMutex, NULL);
-    mState = pMutex;
-}
-
-Mutex::~Mutex()
-{
-    delete (pthread_mutex_t*) mState;
-}
-
-status_t Mutex::lock()
-{
-    int res;
-    while ((res=pthread_mutex_lock((pthread_mutex_t*) mState)) == EINTR) ;
-    return -res;
-}
-
-void Mutex::unlock()
-{
-    pthread_mutex_unlock((pthread_mutex_t*) mState);
-}
-
-status_t Mutex::tryLock()
-{
-    int res;
-    while ((res=pthread_mutex_trylock((pthread_mutex_t*) mState)) == EINTR) ;
-    return -res;
-}
-
-#elif defined(HAVE_FUTEX)
-#if 0
-#pragma mark -
-#endif
-
-#define STATE ((futex_mutex_t*) (&mState))
-
-Mutex::Mutex()
-{
-    _init();
-}
-
-Mutex::Mutex(const char* name)
-{
-    _init();
-}
-
-void
-Mutex::_init()
-{
-    futex_mutex_init(STATE);
-}
-
-Mutex::~Mutex()
-{
-}
-
-status_t Mutex::lock()
-{
-    int res;
-    while ((res=futex_mutex_lock(STATE, FUTEX_WAIT_INFINITE)) == EINTR) ;
-    return -res;
-}
-
-void Mutex::unlock()
-{
-    futex_mutex_unlock(STATE);
-}
-
-status_t Mutex::tryLock()
-{
-    int res;
-    while ((res=futex_mutex_trylock(STATE)) == EINTR) ;
-    return -res;
-}
-#undef STATE
-
+#if defined(HAVE_PTHREADS)
+// implemented as inlines in threads.h
 #elif defined(HAVE_WIN32_THREADS)
-#if 0
-#pragma mark -
-#endif
 
 Mutex::Mutex()
 {
@@ -413,6 +296,19 @@
     // XXX: name not used for now
     HANDLE hMutex;
 
+    assert(sizeof(hMutex) == sizeof(mState));
+
+    hMutex = CreateMutex(NULL, FALSE, NULL);
+    mState = (void*) hMutex;
+}
+
+Mutex::Mutex(int type, const char* name)
+{
+    // XXX: type and name not used for now
+    HANDLE hMutex;
+
+    assert(sizeof(hMutex) == sizeof(mState));
+
     hMutex = CreateMutex(NULL, FALSE, NULL);
     mState = (void*) hMutex;
 }
@@ -456,161 +352,9 @@
  * ===========================================================================
  */
 
-#if 0
-#pragma mark -
-#pragma mark Condition
-#endif
-
-#if defined(HAVE_PTHREADS) && !defined(HAVE_FUTEX)
-
-/*
- * Constructor.  This is a simple pthread wrapper.
- */
-Condition::Condition()
-{
-    pthread_cond_t* pCond = new pthread_cond_t;
-
-    pthread_cond_init(pCond, NULL);
-    mState = pCond;
-}
-
-/*
- * Destructor.
- */
-Condition::~Condition()
-{
-    pthread_cond_destroy((pthread_cond_t*) mState);
-    delete (pthread_cond_t*) mState;
-}
-
-/*
- * Wait on a condition variable.  Lock the mutex before calling.
- */
-
-status_t Condition::wait(Mutex& mutex)
-{
-    assert(mutex.mState != NULL);
-
-    int cc;
-    while ((cc = pthread_cond_wait((pthread_cond_t*)mState,
-                (pthread_mutex_t*) mutex.mState)) == EINTR) ;
-    return -cc;
-}
-
-status_t Condition::wait(Mutex& mutex, nsecs_t abstime)
-{
-    assert(mutex.mState != NULL);
-
-    struct timespec ts;
-    ts.tv_sec = abstime/1000000000;
-    ts.tv_nsec = abstime-(ts.tv_sec*1000000000);
-    
-    int cc;
-    while ((cc = pthread_cond_timedwait((pthread_cond_t*)mState,
-            (pthread_mutex_t*) mutex.mState, &ts)) == EINTR) ;
-    return -cc;
-}
-
-status_t Condition::waitRelative(Mutex& mutex, nsecs_t reltime)
-{
-    return wait(mutex, systemTime()+reltime);
-}
-
-/*
- * Signal the condition variable, allowing one thread to continue.
- */
-void Condition::signal()
-{
-    pthread_cond_signal((pthread_cond_t*) mState);
-}
-
-/*
- * Signal the condition variable, allowing all threads to continue.
- */
-void Condition::broadcast()
-{
-    pthread_cond_broadcast((pthread_cond_t*) mState);
-}
-
-#elif defined(HAVE_FUTEX)
-#if 0
-#pragma mark -
-#endif
-
-#define STATE ((futex_cond_t*) (&mState))
-
-/*
- * Constructor.  This is a simple pthread wrapper.
- */
-Condition::Condition()
-{
-    futex_cond_init(STATE);
-}
-
-/*
- * Destructor.
- */
-Condition::~Condition()
-{
-}
-
-/*
- * Wait on a condition variable.  Lock the mutex before calling.
- */
-
-status_t Condition::wait(Mutex& mutex)
-{
-    assert(mutex.mState != NULL);
-
-    int res;
-    while ((res = futex_cond_wait(STATE,
-        (futex_mutex_t*)(&mutex.mState), FUTEX_WAIT_INFINITE)) == -EINTR) ;
-
-    return -res;
-}
-
-status_t Condition::wait(Mutex& mutex, nsecs_t abstime)
-{
-    nsecs_t reltime = abstime - systemTime();
-    if (reltime <= 0) return true;
-    return waitRelative(mutex, reltime);
-}
-
-status_t Condition::waitRelative(Mutex& mutex, nsecs_t reltime)
-{
-    assert(mutex.mState != NULL);
-    int res;
-    unsigned msec = ns2ms(reltime);
-    if(msec == 0)
-        return true;
-    // This code will not time out at the correct time if interrupted by signals
-    while ((res = futex_cond_wait(STATE,
-        (futex_mutex_t*)(&mutex.mState), msec)) == -EINTR) ;
-    return res;
-}
-
-/*
- * Signal the condition variable, allowing one thread to continue.
- */
-void Condition::signal()
-{
-    futex_cond_signal(STATE);
-}
-
-/*
- * Signal the condition variable, allowing all threads to continue.
- */
-void Condition::broadcast()
-{
-    futex_cond_broadcast(STATE);
-}
-
-#undef STATE
-
+#if defined(HAVE_PTHREADS)
+// implemented as inlines in threads.h
 #elif defined(HAVE_WIN32_THREADS)
-#if 0
-#pragma mark -
-#endif
 
 /*
  * Windows doesn't have a condition variable solution.  It's possible
@@ -753,17 +497,13 @@
     return ((WinCondition*)mState)->wait(condState, hMutex, NULL);
 }
 
-status_t Condition::wait(Mutex& mutex, nsecs_t abstime)
+status_t Condition::waitRelative(Mutex& mutex, nsecs_t reltime)
 {
     WinCondition* condState = (WinCondition*) mState;
     HANDLE hMutex = (HANDLE) mutex.mState;
+    nsecs_t absTime = systemTime()+reltime;
 
-    return ((WinCondition*)mState)->wait(condState, hMutex, &abstime);
-}
-
-status_t Condition::waitRelative(Mutex& mutex, nsecs_t reltime)
-{
-    return wait(mutex, systemTime()+reltime);
+    return ((WinCondition*)mState)->wait(condState, hMutex, &absTime);
 }
 
 /*
@@ -841,11 +581,6 @@
 
 // ----------------------------------------------------------------------------
 
-#if 0
-#pragma mark -
-#pragma mark Thread::Thread
-#endif
-
 /*
  * This is our thread object!
  */
@@ -920,6 +655,11 @@
     wp<Thread> weak(strong);
     self->mHoldSelf.clear();
 
+#if HAVE_ANDROID_OS
+    // this is very useful for debugging with gdb
+    self->mTid = gettid();
+#endif
+
     bool first = true;
 
     do {
@@ -950,7 +690,7 @@
             self->mExitPending = true;
             self->mLock.lock();
             self->mRunning = false;
-            self->mThreadExitedCondition.signal();
+            self->mThreadExitedCondition.broadcast();
             self->mLock.unlock();
             break;
         }
@@ -958,7 +698,7 @@
         // Release our strong reference, to let a chance to the thread
         // to die a peaceful death.
         strong.clear();
-        // And immediately, reacquire a strong reference for the next loop
+        // And immediately, re-acquire a strong reference for the next loop
         strong = weak.promote();
     } while(strong != 0);
     
diff --git a/libs/utils/TimerProbe.cpp b/libs/utils/TimerProbe.cpp
deleted file mode 100644
index 835480d..0000000
--- a/libs/utils/TimerProbe.cpp
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * 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/TimerProbe.h>
- 
-#if ENABLE_TIMER_PROBE
-
-#ifdef LOG_TAG
-#undef LOG_TAG
-#endif
-#define LOG_TAG "time"
-
-namespace android {
-
-Vector<TimerProbe::Bucket> TimerProbe::gBuckets;
-TimerProbe* TimerProbe::gExecuteChain;
-int TimerProbe::gIndent;
-timespec TimerProbe::gRealBase;
-
-TimerProbe::TimerProbe(const char tag[], int* slot) : mTag(tag)
-{
-    mNext = gExecuteChain;
-    gExecuteChain = this;
-    mIndent = gIndent;
-    gIndent += 1;
-    if (mIndent > 0) {
-        if (*slot == 0) {
-            int count = gBuckets.add();
-            *slot = count;
-            Bucket& bucket = gBuckets.editItemAt(count);
-            memset(&bucket, 0, sizeof(Bucket));
-            bucket.mTag = tag;
-            bucket.mSlotPtr = slot;
-            bucket.mIndent = mIndent;
-        }
-        mBucket = *slot;
-    }
-    clock_gettime(CLOCK_REALTIME, &mRealStart);
-    if (gRealBase.tv_sec == 0)
-        gRealBase = mRealStart;
-    clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &mPStart);
-    clock_gettime(CLOCK_THREAD_CPUTIME_ID, &mTStart);
-}
-
-void TimerProbe::end()
-{
-    timespec realEnd, pEnd, tEnd;
-    clock_gettime(CLOCK_REALTIME, &realEnd);
-    clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &pEnd);
-    clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tEnd);
-    print(realEnd, pEnd, tEnd);
-    mTag = NULL;
-}
-
-TimerProbe::~TimerProbe()
-{
-    if (mTag != NULL)
-        end();
-    gExecuteChain = mNext;
-    gIndent--;
-}
-
-
-uint32_t TimerProbe::ElapsedTime(const timespec& start, const timespec& end)
-{
-    int sec = end.tv_sec - start.tv_sec;
-    int nsec = end.tv_nsec - start.tv_nsec;
-    if (nsec < 0) {
-        sec--;
-        nsec += 1000000000;
-    }
-    return sec * 1000000 + nsec / 1000;
-}
-
-void TimerProbe::print(const timespec& r, const timespec& p,
-        const timespec& t) const
-{
-    uint32_t es = ElapsedTime(gRealBase, mRealStart);
-    uint32_t er = ElapsedTime(mRealStart, r);
-    uint32_t ep = ElapsedTime(mPStart, p);
-    uint32_t et = ElapsedTime(mTStart, t);
-    if (mIndent > 0) {
-        Bucket& bucket = gBuckets.editItemAt(mBucket);
-        if (bucket.mStart == 0)
-            bucket.mStart = es;
-        bucket.mReal += er;
-        bucket.mProcess += ep;
-        bucket.mThread += et;
-        bucket.mCount++;
-        return;
-    }
-    int index = 0;
-    int buckets = gBuckets.size();
-    int count = 1;
-    const char* tag = mTag;
-    int indent = mIndent;
-    do {
-        LOGD("%-30.30s: (%3d) %-5.*s time=%-10.3f real=%7dus process=%7dus (%3d%%) thread=%7dus (%3d%%)\n", 
-            tag, count, indent > 5 ? 5 : indent, "+++++", es / 1000000.0,
-            er, ep, ep * 100 / er, et, et * 100 / er);
-        if (index >= buckets)
-            break;
-        Bucket& bucket = gBuckets.editItemAt(index);
-        count = bucket.mCount;
-        es = bucket.mStart;
-        er = bucket.mReal;
-        ep = bucket.mProcess;
-        et = bucket.mThread;
-        tag = bucket.mTag;
-        indent = bucket.mIndent;
-        *bucket.mSlotPtr = 0;
-    } while (++index); // always true
-    gBuckets.clear();
-}
-
-}; // namespace android
-
-#endif
diff --git a/libs/utils/Timers.cpp b/libs/utils/Timers.cpp
index 2abc811..784f035 100644
--- a/libs/utils/Timers.cpp
+++ b/libs/utils/Timers.cpp
@@ -18,7 +18,6 @@
 // Timer functions.
 //
 #include <utils/Timers.h>
-#include <utils/ported.h>     // may need usleep
 #include <utils/Log.h>
 
 #include <stdlib.h>
@@ -54,130 +53,6 @@
 #endif
 }
 
-//#define MONITOR_USLEEP
-
-/*
- * Sleep long enough that we'll wake up "interval" milliseconds after
- * the previous snooze.
- *
- * The "nextTick" argument is updated on each call, and should be passed
- * in every time.  Set its fields to zero on the first call.
- *
- * Returns the #of intervals we have overslept, which will be zero if we're
- * on time.  [Currently just returns 0 or 1.]
- */
-int sleepForInterval(long interval, struct timeval* pNextTick)
-{
-    struct timeval now;
-    long long timeBeforeNext;
-    long sleepTime = 0;
-    bool overSlept = false;
-    //int usleepBias = 0;
-
-#ifdef USLEEP_BIAS
-    /*
-     * Linux likes to add 9000ms or so.
-     * [not using this for now]
-     */
-    //usleepBias = USLEEP_BIAS;
-#endif
-
-    gettimeofday(&now, NULL);
-
-    if (pNextTick->tv_sec == 0) {
-        /* special-case for first time through */
-        *pNextTick = now;
-        sleepTime = interval;
-        android::DurationTimer::addToTimeval(pNextTick, interval);
-    } else {
-        /*
-         * Compute how much time there is before the next tick.  If this
-         * value is negative, we've run over.  If we've run over a little
-         * bit we can shorten the next frame to keep the pace steady, but
-         * if we've dramatically overshot we need to re-sync.
-         */
-        timeBeforeNext = android::DurationTimer::subtractTimevals(pNextTick, &now);
-        //printf("TOP: now=%ld.%ld next=%ld.%ld diff=%ld\n",
-        //    now.tv_sec, now.tv_usec, pNextTick->tv_sec, pNextTick->tv_usec,
-        //    (long) timeBeforeNext);
-        if (timeBeforeNext < -interval) {
-            /* way over */
-            overSlept = true;
-            sleepTime = 0;
-            *pNextTick = now;
-        } else if (timeBeforeNext <= 0) {
-            /* slightly over, keep the pace steady */
-            overSlept = true;
-            sleepTime = 0;
-        } else if (timeBeforeNext <= interval) {
-            /* right on schedule */
-            sleepTime = timeBeforeNext;
-        } else if (timeBeforeNext > interval && timeBeforeNext <= 2*interval) {
-            /* sleep call returned early; do a longer sleep this time */
-            sleepTime = timeBeforeNext;
-        } else if (timeBeforeNext > interval) {
-            /* we went back in time -- somebody updated system clock? */
-            /* (could also be a *seriously* broken usleep()) */
-            LOG(LOG_DEBUG, "",
-                " Impossible: timeBeforeNext = %ld\n", (long)timeBeforeNext);
-            sleepTime = 0;
-            *pNextTick = now;
-        }
-        android::DurationTimer::addToTimeval(pNextTick, interval);
-    }
-    //printf(" Before sleep: now=%ld.%ld next=%ld.%ld sleepTime=%ld\n",
-    //    now.tv_sec, now.tv_usec, pNextTick->tv_sec, pNextTick->tv_usec,
-    //    sleepTime);
-
-    /*
-     * Sleep for the designated period of time.
-     *
-     * Linux tends to sleep for longer than requested, often by 17-18ms.
-     * MinGW tends to sleep for less than requested, by as much as 14ms,
-     * but occasionally oversleeps for 40+ms (looks like some external
-     * factors plus round-off on a 64Hz clock).  Cygwin is pretty steady.
-     *
-     * If you start the MinGW version, and then launch the Cygwin version,
-     * the MinGW clock becomes more erratic.  Not entirely sure why.
-     *
-     * (There's a lot of stuff here; it's really just a usleep() call with
-     * a bunch of instrumentation.)
-     */
-    if (sleepTime > 0) {
-#if defined(MONITOR_USLEEP)
-        struct timeval before, after;
-        long long actual;
-
-        gettimeofday(&before, NULL);
-        usleep((long) sleepTime);
-        gettimeofday(&after, NULL);
-
-        /* check usleep() accuracy; default Linux threads are pretty sloppy */
-        actual = android::DurationTimer::subtractTimevals(&after, &before);
-        if ((long) actual < sleepTime - 14000 /*(sleepTime/10)*/ ||
-            (long) actual > sleepTime + 20000 /*(sleepTime/10)*/)
-        {
-            LOG(LOG_DEBUG, "", " Odd usleep: req=%ld, actual=%ld\n", sleepTime,
-                (long) actual);
-        }
-#else
-#ifdef HAVE_WIN32_THREADS
-        Sleep( sleepTime/1000 );
-#else        
-        usleep((long) sleepTime);
-#endif        
-#endif
-    }
-
-    //printf("slept %d\n", sleepTime);
-
-    if (overSlept)
-        return 1;       // close enough
-    else
-        return 0;
-}
-
-
 /*
  * ===========================================================================
  *      DurationTimer
diff --git a/libs/utils/ZipEntry.cpp b/libs/utils/ZipEntry.cpp
deleted file mode 100644
index 96f9fc4..0000000
--- a/libs/utils/ZipEntry.cpp
+++ /dev/null
@@ -1,696 +0,0 @@
-/*
- * Copyright (C) 2006 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.
- */
-
-//
-// Access to entries in a Zip archive.
-//
-
-#define LOG_TAG "zip"
-
-#include <utils/ZipEntry.h>
-#include <utils/Log.h>
-
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
-
-using namespace android;
-
-/*
- * Initialize a new ZipEntry structure from a FILE* positioned at a
- * CentralDirectoryEntry.
- *
- * On exit, the file pointer will be at the start of the next CDE or
- * at the EOCD.
- */
-status_t ZipEntry::initFromCDE(FILE* fp)
-{
-    status_t result;
-    long posn;
-    bool hasDD;
-
-    //LOGV("initFromCDE ---\n");
-
-    /* read the CDE */
-    result = mCDE.read(fp);
-    if (result != NO_ERROR) {
-        LOGD("mCDE.read failed\n");
-        return result;
-    }
-
-    //mCDE.dump();
-
-    /* using the info in the CDE, go load up the LFH */
-    posn = ftell(fp);
-    if (fseek(fp, mCDE.mLocalHeaderRelOffset, SEEK_SET) != 0) {
-        LOGD("local header seek failed (%ld)\n",
-            mCDE.mLocalHeaderRelOffset);
-        return UNKNOWN_ERROR;
-    }
-
-    result = mLFH.read(fp);
-    if (result != NO_ERROR) {
-        LOGD("mLFH.read failed\n");
-        return result;
-    }
-
-    if (fseek(fp, posn, SEEK_SET) != 0)
-        return UNKNOWN_ERROR;
-
-    //mLFH.dump();
-
-    /*
-     * We *might* need to read the Data Descriptor at this point and
-     * integrate it into the LFH.  If this bit is set, the CRC-32,
-     * compressed size, and uncompressed size will be zero.  In practice
-     * these seem to be rare.
-     */
-    hasDD = (mLFH.mGPBitFlag & kUsesDataDescr) != 0;
-    if (hasDD) {
-        // do something clever
-        //LOGD("+++ has data descriptor\n");
-    }
-
-    /*
-     * Sanity-check the LFH.  Note that this will fail if the "kUsesDataDescr"
-     * flag is set, because the LFH is incomplete.  (Not a problem, since we
-     * prefer the CDE values.)
-     */
-    if (!hasDD && !compareHeaders()) {
-        LOGW("WARNING: header mismatch\n");
-        // keep going?
-    }
-
-    /*
-     * If the mVersionToExtract is greater than 20, we may have an
-     * issue unpacking the record -- could be encrypted, compressed
-     * with something we don't support, or use Zip64 extensions.  We
-     * can defer worrying about that to when we're extracting data.
-     */
-
-    return NO_ERROR;
-}
-
-/*
- * Initialize a new entry.  Pass in the file name and an optional comment.
- *
- * Initializes the CDE and the LFH.
- */
-void ZipEntry::initNew(const char* fileName, const char* comment)
-{
-    assert(fileName != NULL && *fileName != '\0');  // name required
-
-    /* most fields are properly initialized by constructor */
-    mCDE.mVersionMadeBy = kDefaultMadeBy;
-    mCDE.mVersionToExtract = kDefaultVersion;
-    mCDE.mCompressionMethod = kCompressStored;
-    mCDE.mFileNameLength = strlen(fileName);
-    if (comment != NULL)
-        mCDE.mFileCommentLength = strlen(comment);
-    mCDE.mExternalAttrs = 0x81b60020;   // matches what WinZip does
-
-    if (mCDE.mFileNameLength > 0) {
-        mCDE.mFileName = new unsigned char[mCDE.mFileNameLength+1];
-        strcpy((char*) mCDE.mFileName, fileName);
-    }
-    if (mCDE.mFileCommentLength > 0) {
-        /* TODO: stop assuming null-terminated ASCII here? */
-        mCDE.mFileComment = new unsigned char[mCDE.mFileCommentLength+1];
-        strcpy((char*) mCDE.mFileComment, comment);
-    }
-
-    copyCDEtoLFH();
-}
-
-/*
- * Initialize a new entry, starting with the ZipEntry from a different
- * archive.
- *
- * Initializes the CDE and the LFH.
- */
-status_t ZipEntry::initFromExternal(const ZipFile* pZipFile,
-    const ZipEntry* pEntry)
-{
-    /*
-     * Copy everything in the CDE over, then fix up the hairy bits.
-     */
-    memcpy(&mCDE, &pEntry->mCDE, sizeof(mCDE));
-
-    if (mCDE.mFileNameLength > 0) {
-        mCDE.mFileName = new unsigned char[mCDE.mFileNameLength+1];
-        if (mCDE.mFileName == NULL)
-            return NO_MEMORY;
-        strcpy((char*) mCDE.mFileName, (char*)pEntry->mCDE.mFileName);
-    }
-    if (mCDE.mFileCommentLength > 0) {
-        mCDE.mFileComment = new unsigned char[mCDE.mFileCommentLength+1];
-        if (mCDE.mFileComment == NULL)
-            return NO_MEMORY;
-        strcpy((char*) mCDE.mFileComment, (char*)pEntry->mCDE.mFileComment);
-    }
-    if (mCDE.mExtraFieldLength > 0) {
-        /* we null-terminate this, though it may not be a string */
-        mCDE.mExtraField = new unsigned char[mCDE.mExtraFieldLength+1];
-        if (mCDE.mExtraField == NULL)
-            return NO_MEMORY;
-        memcpy(mCDE.mExtraField, pEntry->mCDE.mExtraField,
-            mCDE.mExtraFieldLength+1);
-    }
-
-    /* construct the LFH from the CDE */
-    copyCDEtoLFH();
-
-    /*
-     * The LFH "extra" field is independent of the CDE "extra", so we
-     * handle it here.
-     */
-    assert(mLFH.mExtraField == NULL);
-    mLFH.mExtraFieldLength = pEntry->mLFH.mExtraFieldLength;
-    if (mLFH.mExtraFieldLength > 0) {
-        mLFH.mExtraField = new unsigned char[mLFH.mExtraFieldLength+1];
-        if (mLFH.mExtraField == NULL)
-            return NO_MEMORY;
-        memcpy(mLFH.mExtraField, pEntry->mLFH.mExtraField,
-            mLFH.mExtraFieldLength+1);
-    }
-
-    return NO_ERROR;
-}
-
-/*
- * Insert pad bytes in the LFH by tweaking the "extra" field.  This will
- * potentially confuse something that put "extra" data in here earlier,
- * but I can't find an actual problem.
- */
-status_t ZipEntry::addPadding(int padding)
-{
-    if (padding <= 0)
-        return INVALID_OPERATION;
-
-    //LOGI("HEY: adding %d pad bytes to existing %d in %s\n",
-    //    padding, mLFH.mExtraFieldLength, mCDE.mFileName);
-
-    if (mLFH.mExtraFieldLength > 0) {
-        /* extend existing field */
-        unsigned char* newExtra;
-
-        newExtra = new unsigned char[mLFH.mExtraFieldLength + padding];
-        if (newExtra == NULL)
-            return NO_MEMORY;
-        memset(newExtra + mLFH.mExtraFieldLength, 0, padding);
-        memcpy(newExtra, mLFH.mExtraField, mLFH.mExtraFieldLength);
-
-        delete[] mLFH.mExtraField;
-        mLFH.mExtraField = newExtra;
-        mLFH.mExtraFieldLength += padding;
-    } else {
-        /* create new field */
-        mLFH.mExtraField = new unsigned char[padding];
-        memset(mLFH.mExtraField, 0, padding);
-        mLFH.mExtraFieldLength = padding;
-    }
-
-    return NO_ERROR;
-}
-
-/*
- * Set the fields in the LFH equal to the corresponding fields in the CDE.
- *
- * This does not touch the LFH "extra" field.
- */
-void ZipEntry::copyCDEtoLFH(void)
-{
-    mLFH.mVersionToExtract  = mCDE.mVersionToExtract;
-    mLFH.mGPBitFlag         = mCDE.mGPBitFlag;
-    mLFH.mCompressionMethod = mCDE.mCompressionMethod;
-    mLFH.mLastModFileTime   = mCDE.mLastModFileTime;
-    mLFH.mLastModFileDate   = mCDE.mLastModFileDate;
-    mLFH.mCRC32             = mCDE.mCRC32;
-    mLFH.mCompressedSize    = mCDE.mCompressedSize;
-    mLFH.mUncompressedSize  = mCDE.mUncompressedSize;
-    mLFH.mFileNameLength    = mCDE.mFileNameLength;
-    // the "extra field" is independent
-
-    delete[] mLFH.mFileName;
-    if (mLFH.mFileNameLength > 0) {
-        mLFH.mFileName = new unsigned char[mLFH.mFileNameLength+1];
-        strcpy((char*) mLFH.mFileName, (const char*) mCDE.mFileName);
-    } else {
-        mLFH.mFileName = NULL;
-    }
-}
-
-/*
- * Set some information about a file after we add it.
- */
-void ZipEntry::setDataInfo(long uncompLen, long compLen, unsigned long crc32,
-    int compressionMethod)
-{
-    mCDE.mCompressionMethod = compressionMethod;
-    mCDE.mCRC32 = crc32;
-    mCDE.mCompressedSize = compLen;
-    mCDE.mUncompressedSize = uncompLen;
-    mCDE.mCompressionMethod = compressionMethod;
-    if (compressionMethod == kCompressDeflated) {
-        mCDE.mGPBitFlag |= 0x0002;      // indicates maximum compression used
-    }
-    copyCDEtoLFH();
-}
-
-/*
- * See if the data in mCDE and mLFH match up.  This is mostly useful for
- * debugging these classes, but it can be used to identify damaged
- * archives.
- *
- * Returns "false" if they differ.
- */
-bool ZipEntry::compareHeaders(void) const
-{
-    if (mCDE.mVersionToExtract != mLFH.mVersionToExtract) {
-        LOGV("cmp: VersionToExtract\n");
-        return false;
-    }
-    if (mCDE.mGPBitFlag != mLFH.mGPBitFlag) {
-        LOGV("cmp: GPBitFlag\n");
-        return false;
-    }
-    if (mCDE.mCompressionMethod != mLFH.mCompressionMethod) {
-        LOGV("cmp: CompressionMethod\n");
-        return false;
-    }
-    if (mCDE.mLastModFileTime != mLFH.mLastModFileTime) {
-        LOGV("cmp: LastModFileTime\n");
-        return false;
-    }
-    if (mCDE.mLastModFileDate != mLFH.mLastModFileDate) {
-        LOGV("cmp: LastModFileDate\n");
-        return false;
-    }
-    if (mCDE.mCRC32 != mLFH.mCRC32) {
-        LOGV("cmp: CRC32\n");
-        return false;
-    }
-    if (mCDE.mCompressedSize != mLFH.mCompressedSize) {
-        LOGV("cmp: CompressedSize\n");
-        return false;
-    }
-    if (mCDE.mUncompressedSize != mLFH.mUncompressedSize) {
-        LOGV("cmp: UncompressedSize\n");
-        return false;
-    }
-    if (mCDE.mFileNameLength != mLFH.mFileNameLength) {
-        LOGV("cmp: FileNameLength\n");
-        return false;
-    }
-#if 0       // this seems to be used for padding, not real data
-    if (mCDE.mExtraFieldLength != mLFH.mExtraFieldLength) {
-        LOGV("cmp: ExtraFieldLength\n");
-        return false;
-    }
-#endif
-    if (mCDE.mFileName != NULL) {
-        if (strcmp((char*) mCDE.mFileName, (char*) mLFH.mFileName) != 0) {
-            LOGV("cmp: FileName\n");
-            return false;
-        }
-    }
-
-    return true;
-}
-
-
-/*
- * Convert the DOS date/time stamp into a UNIX time stamp.
- */
-time_t ZipEntry::getModWhen(void) const
-{
-    struct tm parts;
-
-    parts.tm_sec = (mCDE.mLastModFileTime & 0x001f) << 1;
-    parts.tm_min = (mCDE.mLastModFileTime & 0x07e0) >> 5;
-    parts.tm_hour = (mCDE.mLastModFileTime & 0xf800) >> 11;
-    parts.tm_mday = (mCDE.mLastModFileDate & 0x001f);
-    parts.tm_mon = ((mCDE.mLastModFileDate & 0x01e0) >> 5) -1;
-    parts.tm_year = ((mCDE.mLastModFileDate & 0xfe00) >> 9) + 80;
-    parts.tm_wday = parts.tm_yday = 0;
-    parts.tm_isdst = -1;        // DST info "not available"
-
-    return mktime(&parts);
-}
-
-/*
- * Set the CDE/LFH timestamp from UNIX time.
- */
-void ZipEntry::setModWhen(time_t when)
-{
-#ifdef HAVE_LOCALTIME_R
-    struct tm tmResult;
-#endif
-    time_t even;
-    unsigned short zdate, ztime;
-
-    struct tm* ptm;
-
-    /* round up to an even number of seconds */
-    even = (time_t)(((unsigned long)(when) + 1) & (~1));
-
-    /* expand */
-#ifdef HAVE_LOCALTIME_R
-    ptm = localtime_r(&even, &tmResult);
-#else
-    ptm = localtime(&even);
-#endif
-
-    int year;
-    year = ptm->tm_year;
-    if (year < 80)
-        year = 80;
-
-    zdate = (year - 80) << 9 | (ptm->tm_mon+1) << 5 | ptm->tm_mday;
-    ztime = ptm->tm_hour << 11 | ptm->tm_min << 5 | ptm->tm_sec >> 1;
-
-    mCDE.mLastModFileTime = mLFH.mLastModFileTime = ztime;
-    mCDE.mLastModFileDate = mLFH.mLastModFileDate = zdate;
-}
-
-
-/*
- * ===========================================================================
- *      ZipEntry::LocalFileHeader
- * ===========================================================================
- */
-
-/*
- * Read a local file header.
- *
- * On entry, "fp" points to the signature at the start of the header.
- * On exit, "fp" points to the start of data.
- */
-status_t ZipEntry::LocalFileHeader::read(FILE* fp)
-{
-    status_t result = NO_ERROR;
-    unsigned char buf[kLFHLen];
-
-    assert(mFileName == NULL);
-    assert(mExtraField == NULL);
-
-    if (fread(buf, 1, kLFHLen, fp) != kLFHLen) {
-        result = UNKNOWN_ERROR;
-        goto bail;
-    }
-
-    if (ZipEntry::getLongLE(&buf[0x00]) != kSignature) {
-        LOGD("whoops: didn't find expected signature\n");
-        result = UNKNOWN_ERROR;
-        goto bail;
-    }
-
-    mVersionToExtract = ZipEntry::getShortLE(&buf[0x04]);
-    mGPBitFlag = ZipEntry::getShortLE(&buf[0x06]);
-    mCompressionMethod = ZipEntry::getShortLE(&buf[0x08]);
-    mLastModFileTime = ZipEntry::getShortLE(&buf[0x0a]);
-    mLastModFileDate = ZipEntry::getShortLE(&buf[0x0c]);
-    mCRC32 = ZipEntry::getLongLE(&buf[0x0e]);
-    mCompressedSize = ZipEntry::getLongLE(&buf[0x12]);
-    mUncompressedSize = ZipEntry::getLongLE(&buf[0x16]);
-    mFileNameLength = ZipEntry::getShortLE(&buf[0x1a]);
-    mExtraFieldLength = ZipEntry::getShortLE(&buf[0x1c]);
-
-    // TODO: validate sizes
-
-    /* grab filename */
-    if (mFileNameLength != 0) {
-        mFileName = new unsigned char[mFileNameLength+1];
-        if (mFileName == NULL) {
-            result = NO_MEMORY;
-            goto bail;
-        }
-        if (fread(mFileName, 1, mFileNameLength, fp) != mFileNameLength) {
-            result = UNKNOWN_ERROR;
-            goto bail;
-        }
-        mFileName[mFileNameLength] = '\0';
-    }
-
-    /* grab extra field */
-    if (mExtraFieldLength != 0) {
-        mExtraField = new unsigned char[mExtraFieldLength+1];
-        if (mExtraField == NULL) {
-            result = NO_MEMORY;
-            goto bail;
-        }
-        if (fread(mExtraField, 1, mExtraFieldLength, fp) != mExtraFieldLength) {
-            result = UNKNOWN_ERROR;
-            goto bail;
-        }
-        mExtraField[mExtraFieldLength] = '\0';
-    }
-
-bail:
-    return result;
-}
-
-/*
- * Write a local file header.
- */
-status_t ZipEntry::LocalFileHeader::write(FILE* fp)
-{
-    unsigned char buf[kLFHLen];
-
-    ZipEntry::putLongLE(&buf[0x00], kSignature);
-    ZipEntry::putShortLE(&buf[0x04], mVersionToExtract);
-    ZipEntry::putShortLE(&buf[0x06], mGPBitFlag);
-    ZipEntry::putShortLE(&buf[0x08], mCompressionMethod);
-    ZipEntry::putShortLE(&buf[0x0a], mLastModFileTime);
-    ZipEntry::putShortLE(&buf[0x0c], mLastModFileDate);
-    ZipEntry::putLongLE(&buf[0x0e], mCRC32);
-    ZipEntry::putLongLE(&buf[0x12], mCompressedSize);
-    ZipEntry::putLongLE(&buf[0x16], mUncompressedSize);
-    ZipEntry::putShortLE(&buf[0x1a], mFileNameLength);
-    ZipEntry::putShortLE(&buf[0x1c], mExtraFieldLength);
-
-    if (fwrite(buf, 1, kLFHLen, fp) != kLFHLen)
-        return UNKNOWN_ERROR;
-
-    /* write filename */
-    if (mFileNameLength != 0) {
-        if (fwrite(mFileName, 1, mFileNameLength, fp) != mFileNameLength)
-            return UNKNOWN_ERROR;
-    }
-
-    /* write "extra field" */
-    if (mExtraFieldLength != 0) {
-        if (fwrite(mExtraField, 1, mExtraFieldLength, fp) != mExtraFieldLength)
-            return UNKNOWN_ERROR;
-    }
-
-    return NO_ERROR;
-}
-
-
-/*
- * Dump the contents of a LocalFileHeader object.
- */
-void ZipEntry::LocalFileHeader::dump(void) const
-{
-    LOGD(" LocalFileHeader contents:\n");
-    LOGD("  versToExt=%u gpBits=0x%04x compression=%u\n",
-        mVersionToExtract, mGPBitFlag, mCompressionMethod);
-    LOGD("  modTime=0x%04x modDate=0x%04x crc32=0x%08lx\n",
-        mLastModFileTime, mLastModFileDate, mCRC32);
-    LOGD("  compressedSize=%lu uncompressedSize=%lu\n",
-        mCompressedSize, mUncompressedSize);
-    LOGD("  filenameLen=%u extraLen=%u\n",
-        mFileNameLength, mExtraFieldLength);
-    if (mFileName != NULL)
-        LOGD("  filename: '%s'\n", mFileName);
-}
-
-
-/*
- * ===========================================================================
- *      ZipEntry::CentralDirEntry
- * ===========================================================================
- */
-
-/*
- * Read the central dir entry that appears next in the file.
- *
- * On entry, "fp" should be positioned on the signature bytes for the
- * entry.  On exit, "fp" will point at the signature word for the next
- * entry or for the EOCD.
- */
-status_t ZipEntry::CentralDirEntry::read(FILE* fp)
-{
-    status_t result = NO_ERROR;
-    unsigned char buf[kCDELen];
-
-    /* no re-use */
-    assert(mFileName == NULL);
-    assert(mExtraField == NULL);
-    assert(mFileComment == NULL);
-
-    if (fread(buf, 1, kCDELen, fp) != kCDELen) {
-        result = UNKNOWN_ERROR;
-        goto bail;
-    }
-
-    if (ZipEntry::getLongLE(&buf[0x00]) != kSignature) {
-        LOGD("Whoops: didn't find expected signature\n");
-        result = UNKNOWN_ERROR;
-        goto bail;
-    }
-
-    mVersionMadeBy = ZipEntry::getShortLE(&buf[0x04]);
-    mVersionToExtract = ZipEntry::getShortLE(&buf[0x06]);
-    mGPBitFlag = ZipEntry::getShortLE(&buf[0x08]);
-    mCompressionMethod = ZipEntry::getShortLE(&buf[0x0a]);
-    mLastModFileTime = ZipEntry::getShortLE(&buf[0x0c]);
-    mLastModFileDate = ZipEntry::getShortLE(&buf[0x0e]);
-    mCRC32 = ZipEntry::getLongLE(&buf[0x10]);
-    mCompressedSize = ZipEntry::getLongLE(&buf[0x14]);
-    mUncompressedSize = ZipEntry::getLongLE(&buf[0x18]);
-    mFileNameLength = ZipEntry::getShortLE(&buf[0x1c]);
-    mExtraFieldLength = ZipEntry::getShortLE(&buf[0x1e]);
-    mFileCommentLength = ZipEntry::getShortLE(&buf[0x20]);
-    mDiskNumberStart = ZipEntry::getShortLE(&buf[0x22]);
-    mInternalAttrs = ZipEntry::getShortLE(&buf[0x24]);
-    mExternalAttrs = ZipEntry::getLongLE(&buf[0x26]);
-    mLocalHeaderRelOffset = ZipEntry::getLongLE(&buf[0x2a]);
-
-    // TODO: validate sizes and offsets
-
-    /* grab filename */
-    if (mFileNameLength != 0) {
-        mFileName = new unsigned char[mFileNameLength+1];
-        if (mFileName == NULL) {
-            result = NO_MEMORY;
-            goto bail;
-        }
-        if (fread(mFileName, 1, mFileNameLength, fp) != mFileNameLength) {
-            result = UNKNOWN_ERROR;
-            goto bail;
-        }
-        mFileName[mFileNameLength] = '\0';
-    }
-
-    /* read "extra field" */
-    if (mExtraFieldLength != 0) {
-        mExtraField = new unsigned char[mExtraFieldLength+1];
-        if (mExtraField == NULL) {
-            result = NO_MEMORY;
-            goto bail;
-        }
-        if (fread(mExtraField, 1, mExtraFieldLength, fp) != mExtraFieldLength) {
-            result = UNKNOWN_ERROR;
-            goto bail;
-        }
-        mExtraField[mExtraFieldLength] = '\0';
-    }
-
-
-    /* grab comment, if any */
-    if (mFileCommentLength != 0) {
-        mFileComment = new unsigned char[mFileCommentLength+1];
-        if (mFileComment == NULL) {
-            result = NO_MEMORY;
-            goto bail;
-        }
-        if (fread(mFileComment, 1, mFileCommentLength, fp) != mFileCommentLength)
-        {
-            result = UNKNOWN_ERROR;
-            goto bail;
-        }
-        mFileComment[mFileCommentLength] = '\0';
-    }
-
-bail:
-    return result;
-}
-
-/*
- * Write a central dir entry.
- */
-status_t ZipEntry::CentralDirEntry::write(FILE* fp)
-{
-    unsigned char buf[kCDELen];
-
-    ZipEntry::putLongLE(&buf[0x00], kSignature);
-    ZipEntry::putShortLE(&buf[0x04], mVersionMadeBy);
-    ZipEntry::putShortLE(&buf[0x06], mVersionToExtract);
-    ZipEntry::putShortLE(&buf[0x08], mGPBitFlag);
-    ZipEntry::putShortLE(&buf[0x0a], mCompressionMethod);
-    ZipEntry::putShortLE(&buf[0x0c], mLastModFileTime);
-    ZipEntry::putShortLE(&buf[0x0e], mLastModFileDate);
-    ZipEntry::putLongLE(&buf[0x10], mCRC32);
-    ZipEntry::putLongLE(&buf[0x14], mCompressedSize);
-    ZipEntry::putLongLE(&buf[0x18], mUncompressedSize);
-    ZipEntry::putShortLE(&buf[0x1c], mFileNameLength);
-    ZipEntry::putShortLE(&buf[0x1e], mExtraFieldLength);
-    ZipEntry::putShortLE(&buf[0x20], mFileCommentLength);
-    ZipEntry::putShortLE(&buf[0x22], mDiskNumberStart);
-    ZipEntry::putShortLE(&buf[0x24], mInternalAttrs);
-    ZipEntry::putLongLE(&buf[0x26], mExternalAttrs);
-    ZipEntry::putLongLE(&buf[0x2a], mLocalHeaderRelOffset);
-
-    if (fwrite(buf, 1, kCDELen, fp) != kCDELen)
-        return UNKNOWN_ERROR;
-
-    /* write filename */
-    if (mFileNameLength != 0) {
-        if (fwrite(mFileName, 1, mFileNameLength, fp) != mFileNameLength)
-            return UNKNOWN_ERROR;
-    }
-
-    /* write "extra field" */
-    if (mExtraFieldLength != 0) {
-        if (fwrite(mExtraField, 1, mExtraFieldLength, fp) != mExtraFieldLength)
-            return UNKNOWN_ERROR;
-    }
-
-    /* write comment */
-    if (mFileCommentLength != 0) {
-        if (fwrite(mFileComment, 1, mFileCommentLength, fp) != mFileCommentLength)
-            return UNKNOWN_ERROR;
-    }
-
-    return NO_ERROR;
-}
-
-/*
- * Dump the contents of a CentralDirEntry object.
- */
-void ZipEntry::CentralDirEntry::dump(void) const
-{
-    LOGD(" CentralDirEntry contents:\n");
-    LOGD("  versMadeBy=%u versToExt=%u gpBits=0x%04x compression=%u\n",
-        mVersionMadeBy, mVersionToExtract, mGPBitFlag, mCompressionMethod);
-    LOGD("  modTime=0x%04x modDate=0x%04x crc32=0x%08lx\n",
-        mLastModFileTime, mLastModFileDate, mCRC32);
-    LOGD("  compressedSize=%lu uncompressedSize=%lu\n",
-        mCompressedSize, mUncompressedSize);
-    LOGD("  filenameLen=%u extraLen=%u commentLen=%u\n",
-        mFileNameLength, mExtraFieldLength, mFileCommentLength);
-    LOGD("  diskNumStart=%u intAttr=0x%04x extAttr=0x%08lx relOffset=%lu\n",
-        mDiskNumberStart, mInternalAttrs, mExternalAttrs,
-        mLocalHeaderRelOffset);
-
-    if (mFileName != NULL)
-        LOGD("  filename: '%s'\n", mFileName);
-    if (mFileComment != NULL)
-        LOGD("  comment: '%s'\n", mFileComment);
-}
-
diff --git a/libs/utils/ZipFile.cpp b/libs/utils/ZipFile.cpp
deleted file mode 100644
index 6f27d17..0000000
--- a/libs/utils/ZipFile.cpp
+++ /dev/null
@@ -1,1296 +0,0 @@
-/*
- * Copyright (C) 2006 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.
- */
-
-//
-// Access to Zip archives.
-//
-
-#define LOG_TAG "zip"
-
-#include <utils/ZipFile.h>
-#include <utils/ZipUtils.h>
-#include <utils/Log.h>
-
-#include <zlib.h>
-#define DEF_MEM_LEVEL 8                // normally in zutil.h?
-
-#include <memory.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <assert.h>
-
-using namespace android;
-
-/*
- * Some environments require the "b", some choke on it.
- */
-#define FILE_OPEN_RO        "rb"
-#define FILE_OPEN_RW        "r+b"
-#define FILE_OPEN_RW_CREATE "w+b"
-
-/* should live somewhere else? */
-static status_t errnoToStatus(int err)
-{
-    if (err == ENOENT)
-        return NAME_NOT_FOUND;
-    else if (err == EACCES)
-        return PERMISSION_DENIED;
-    else
-        return UNKNOWN_ERROR;
-}
-
-/*
- * Open a file and parse its guts.
- */
-status_t ZipFile::open(const char* zipFileName, int flags)
-{
-    bool newArchive = false;
-
-    assert(mZipFp == NULL);     // no reopen
-
-    if ((flags & kOpenTruncate))
-        flags |= kOpenCreate;           // trunc implies create
-
-    if ((flags & kOpenReadOnly) && (flags & kOpenReadWrite))
-        return INVALID_OPERATION;       // not both
-    if (!((flags & kOpenReadOnly) || (flags & kOpenReadWrite)))
-        return INVALID_OPERATION;       // not neither
-    if ((flags & kOpenCreate) && !(flags & kOpenReadWrite))
-        return INVALID_OPERATION;       // create requires write
-
-    if (flags & kOpenTruncate) {
-        newArchive = true;
-    } else {
-        newArchive = (access(zipFileName, F_OK) != 0);
-        if (!(flags & kOpenCreate) && newArchive) {
-            /* not creating, must already exist */
-            LOGD("File %s does not exist", zipFileName);
-            return NAME_NOT_FOUND;
-        }
-    }
-
-    /* open the file */
-    const char* openflags;
-    if (flags & kOpenReadWrite) {
-        if (newArchive)
-            openflags = FILE_OPEN_RW_CREATE;
-        else
-            openflags = FILE_OPEN_RW;
-    } else {
-        openflags = FILE_OPEN_RO;
-    }
-    mZipFp = fopen(zipFileName, openflags);
-    if (mZipFp == NULL) {
-		int err = errno;
-		LOGD("fopen failed: %d\n", err);
-        return errnoToStatus(err);
-	}
-
-    status_t result;
-    if (!newArchive) {
-        /*
-         * Load the central directory.  If that fails, then this probably
-         * isn't a Zip archive.
-         */
-        result = readCentralDir();
-    } else {
-        /*
-         * Newly-created.  The EndOfCentralDir constructor actually
-         * sets everything to be the way we want it (all zeroes).  We
-         * set mNeedCDRewrite so that we create *something* if the
-         * caller doesn't add any files.  (We could also just unlink
-         * the file if it's brand new and nothing was added, but that's
-         * probably doing more than we really should -- the user might
-         * have a need for empty zip files.)
-         */
-        mNeedCDRewrite = true;
-        result = NO_ERROR;
-    }
-
-    if (flags & kOpenReadOnly)
-        mReadOnly = true;
-    else
-        assert(!mReadOnly);
-
-    return result;
-}
-
-/*
- * Return the Nth entry in the archive.
- */
-ZipEntry* ZipFile::getEntryByIndex(int idx) const
-{
-    if (idx < 0 || idx >= (int) mEntries.size())
-        return NULL;
-
-    return mEntries[idx];
-}
-
-/*
- * Find an entry by name.
- */
-ZipEntry* ZipFile::getEntryByName(const char* fileName) const
-{
-    /*
-     * Do a stupid linear string-compare search.
-     *
-     * There are various ways to speed this up, especially since it's rare
-     * to intermingle changes to the archive with "get by name" calls.  We
-     * don't want to sort the mEntries vector itself, however, because
-     * it's used to recreate the Central Directory.
-     *
-     * (Hash table works, parallel list of pointers in sorted order is good.)
-     */
-    int idx;
-
-    for (idx = mEntries.size()-1; idx >= 0; idx--) {
-        ZipEntry* pEntry = mEntries[idx];
-        if (!pEntry->getDeleted() &&
-            strcmp(fileName, pEntry->getFileName()) == 0)
-        {
-            return pEntry;
-        }
-    }
-
-    return NULL;
-}
-
-/*
- * Empty the mEntries vector.
- */
-void ZipFile::discardEntries(void)
-{
-    int count = mEntries.size();
-
-    while (--count >= 0)
-        delete mEntries[count];
-
-    mEntries.clear();
-}
-
-
-/*
- * Find the central directory and read the contents.
- *
- * The fun thing about ZIP archives is that they may or may not be
- * readable from start to end.  In some cases, notably for archives
- * that were written to stdout, the only length information is in the
- * central directory at the end of the file.
- *
- * Of course, the central directory can be followed by a variable-length
- * comment field, so we have to scan through it backwards.  The comment
- * is at most 64K, plus we have 18 bytes for the end-of-central-dir stuff
- * itself, plus apparently sometimes people throw random junk on the end
- * just for the fun of it.
- *
- * This is all a little wobbly.  If the wrong value ends up in the EOCD
- * area, we're hosed.  This appears to be the way that everbody handles
- * it though, so we're in pretty good company if this fails.
- */
-status_t ZipFile::readCentralDir(void)
-{
-    status_t result = NO_ERROR;
-    unsigned char* buf = NULL;
-    off_t fileLength, seekStart;
-    long readAmount;
-    int i;
-
-    fseek(mZipFp, 0, SEEK_END);
-    fileLength = ftell(mZipFp);
-    rewind(mZipFp);
-
-    /* too small to be a ZIP archive? */
-    if (fileLength < EndOfCentralDir::kEOCDLen) {
-        LOGD("Length is %ld -- too small\n", (long)fileLength);
-        result = INVALID_OPERATION;
-        goto bail;
-    }
-
-    buf = new unsigned char[EndOfCentralDir::kMaxEOCDSearch];
-    if (buf == NULL) {
-		LOGD("Failure allocating %d bytes for EOCD search",
-			 EndOfCentralDir::kMaxEOCDSearch);
-        result = NO_MEMORY;
-        goto bail;
-    }
-
-    if (fileLength > EndOfCentralDir::kMaxEOCDSearch) {
-        seekStart = fileLength - EndOfCentralDir::kMaxEOCDSearch;
-        readAmount = EndOfCentralDir::kMaxEOCDSearch;
-    } else {
-        seekStart = 0;
-        readAmount = (long) fileLength;
-    }
-    if (fseek(mZipFp, seekStart, SEEK_SET) != 0) {
-		LOGD("Failure seeking to end of zip at %ld", (long) seekStart);
-        result = UNKNOWN_ERROR;
-        goto bail;
-    }
-
-    /* read the last part of the file into the buffer */
-    if (fread(buf, 1, readAmount, mZipFp) != (size_t) readAmount) {
-        LOGD("short file? wanted %ld\n", readAmount);
-        result = UNKNOWN_ERROR;
-        goto bail;
-    }
-
-    /* find the end-of-central-dir magic */
-    for (i = readAmount - 4; i >= 0; i--) {
-        if (buf[i] == 0x50 &&
-            ZipEntry::getLongLE(&buf[i]) == EndOfCentralDir::kSignature)
-        {
-            LOGV("+++ Found EOCD at buf+%d\n", i);
-            break;
-        }
-    }
-    if (i < 0) {
-        LOGD("EOCD not found, not Zip\n");
-        result = INVALID_OPERATION;
-        goto bail;
-    }
-
-    /* extract eocd values */
-    result = mEOCD.readBuf(buf + i, readAmount - i);
-    if (result != NO_ERROR) {
-		LOGD("Failure reading %ld bytes of EOCD values", readAmount - i);
-        goto bail;
-	}
-    //mEOCD.dump();
-
-    if (mEOCD.mDiskNumber != 0 || mEOCD.mDiskWithCentralDir != 0 ||
-        mEOCD.mNumEntries != mEOCD.mTotalNumEntries)
-    {
-        LOGD("Archive spanning not supported\n");
-        result = INVALID_OPERATION;
-        goto bail;
-    }
-
-    /*
-     * So far so good.  "mCentralDirSize" is the size in bytes of the
-     * central directory, so we can just seek back that far to find it.
-     * We can also seek forward mCentralDirOffset bytes from the
-     * start of the file.
-     *
-     * We're not guaranteed to have the rest of the central dir in the
-     * buffer, nor are we guaranteed that the central dir will have any
-     * sort of convenient size.  We need to skip to the start of it and
-     * read the header, then the other goodies.
-     *
-     * The only thing we really need right now is the file comment, which
-     * we're hoping to preserve.
-     */
-    if (fseek(mZipFp, mEOCD.mCentralDirOffset, SEEK_SET) != 0) {
-		LOGD("Failure seeking to central dir offset %ld\n",
-			 mEOCD.mCentralDirOffset);
-        result = UNKNOWN_ERROR;
-        goto bail;
-    }
-
-    /*
-     * Loop through and read the central dir entries.
-     */
-    LOGV("Scanning %d entries...\n", mEOCD.mTotalNumEntries);
-    int entry;
-    for (entry = 0; entry < mEOCD.mTotalNumEntries; entry++) {
-        ZipEntry* pEntry = new ZipEntry;
-
-        result = pEntry->initFromCDE(mZipFp);
-        if (result != NO_ERROR) {
-            LOGD("initFromCDE failed\n");
-            delete pEntry;
-            goto bail;
-        }
-
-        mEntries.add(pEntry);
-    }
-
-
-    /*
-     * If all went well, we should now be back at the EOCD.
-     */
-    {
-        unsigned char checkBuf[4];
-        if (fread(checkBuf, 1, 4, mZipFp) != 4) {
-            LOGD("EOCD check read failed\n");
-            result = INVALID_OPERATION;
-            goto bail;
-        }
-        if (ZipEntry::getLongLE(checkBuf) != EndOfCentralDir::kSignature) {
-            LOGD("EOCD read check failed\n");
-            result = UNKNOWN_ERROR;
-            goto bail;
-        }
-        LOGV("+++ EOCD read check passed\n");
-    }
-
-bail:
-    delete[] buf;
-    return result;
-}
-
-
-/*
- * Add a new file to the archive.
- *
- * This requires creating and populating a ZipEntry structure, and copying
- * the data into the file at the appropriate position.  The "appropriate
- * position" is the current location of the central directory, which we
- * casually overwrite (we can put it back later).
- *
- * If we were concerned about safety, we would want to make all changes
- * in a temp file and then overwrite the original after everything was
- * safely written.  Not really a concern for us.
- */
-status_t ZipFile::addCommon(const char* fileName, const void* data, size_t size,
-    const char* storageName, int sourceType, int compressionMethod,
-    ZipEntry** ppEntry)
-{
-    ZipEntry* pEntry = NULL;
-    status_t result = NO_ERROR;
-    long lfhPosn, startPosn, endPosn, uncompressedLen;
-    FILE* inputFp = NULL;
-    unsigned long crc;
-    time_t modWhen;
-
-    if (mReadOnly)
-        return INVALID_OPERATION;
-
-    assert(compressionMethod == ZipEntry::kCompressDeflated ||
-           compressionMethod == ZipEntry::kCompressStored);
-
-    /* make sure we're in a reasonable state */
-    assert(mZipFp != NULL);
-    assert(mEntries.size() == mEOCD.mTotalNumEntries);
-
-    /* make sure it doesn't already exist */
-    if (getEntryByName(storageName) != NULL)
-        return ALREADY_EXISTS;
-
-    if (!data) {
-        inputFp = fopen(fileName, FILE_OPEN_RO);
-        if (inputFp == NULL)
-            return errnoToStatus(errno);
-    }
-
-    if (fseek(mZipFp, mEOCD.mCentralDirOffset, SEEK_SET) != 0) {
-        result = UNKNOWN_ERROR;
-        goto bail;
-    }
-
-    pEntry = new ZipEntry;
-    pEntry->initNew(storageName, NULL);
-
-    /*
-     * From here on out, failures are more interesting.
-     */
-    mNeedCDRewrite = true;
-
-    /*
-     * Write the LFH, even though it's still mostly blank.  We need it
-     * as a place-holder.  In theory the LFH isn't necessary, but in
-     * practice some utilities demand it.
-     */
-    lfhPosn = ftell(mZipFp);
-    pEntry->mLFH.write(mZipFp);
-    startPosn = ftell(mZipFp);
-
-    /*
-     * Copy the data in, possibly compressing it as we go.
-     */
-    if (sourceType == ZipEntry::kCompressStored) {
-        if (compressionMethod == ZipEntry::kCompressDeflated) {
-            bool failed = false;
-            result = compressFpToFp(mZipFp, inputFp, data, size, &crc);
-            if (result != NO_ERROR) {
-                LOGD("compression failed, storing\n");
-                failed = true;
-            } else {
-                /*
-                 * Make sure it has compressed "enough".  This probably ought
-                 * to be set through an API call, but I don't expect our
-                 * criteria to change over time.
-                 */
-                long src = inputFp ? ftell(inputFp) : size;
-                long dst = ftell(mZipFp) - startPosn;
-                if (dst + (dst / 10) > src) {
-                    LOGD("insufficient compression (src=%ld dst=%ld), storing\n",
-                        src, dst);
-                    failed = true;
-                }
-            }
-
-            if (failed) {
-                compressionMethod = ZipEntry::kCompressStored;
-                if (inputFp) rewind(inputFp);
-                fseek(mZipFp, startPosn, SEEK_SET);
-                /* fall through to kCompressStored case */
-            }
-        }
-        /* handle "no compression" request, or failed compression from above */
-        if (compressionMethod == ZipEntry::kCompressStored) {
-            if (inputFp) {
-                result = copyFpToFp(mZipFp, inputFp, &crc);
-            } else {
-                result = copyDataToFp(mZipFp, data, size, &crc);
-            }
-            if (result != NO_ERROR) {
-                // don't need to truncate; happens in CDE rewrite
-                LOGD("failed copying data in\n");
-                goto bail;
-            }
-        }
-
-        // currently seeked to end of file
-        uncompressedLen = inputFp ? ftell(inputFp) : size;
-    } else if (sourceType == ZipEntry::kCompressDeflated) {
-        /* we should support uncompressed-from-compressed, but it's not
-         * important right now */
-        assert(compressionMethod == ZipEntry::kCompressDeflated);
-
-        bool scanResult;
-        int method;
-        long compressedLen;
-
-        scanResult = ZipUtils::examineGzip(inputFp, &method, &uncompressedLen,
-                        &compressedLen, &crc);
-        if (!scanResult || method != ZipEntry::kCompressDeflated) {
-            LOGD("this isn't a deflated gzip file?");
-            result = UNKNOWN_ERROR;
-            goto bail;
-        }
-
-        result = copyPartialFpToFp(mZipFp, inputFp, compressedLen, NULL);
-        if (result != NO_ERROR) {
-            LOGD("failed copying gzip data in\n");
-            goto bail;
-        }
-    } else {
-        assert(false);
-        result = UNKNOWN_ERROR;
-        goto bail;
-    }
-
-    /*
-     * We could write the "Data Descriptor", but there doesn't seem to
-     * be any point since we're going to go back and write the LFH.
-     *
-     * Update file offsets.
-     */
-    endPosn = ftell(mZipFp);            // seeked to end of compressed data
-
-    /*
-     * Success!  Fill out new values.
-     */
-    pEntry->setDataInfo(uncompressedLen, endPosn - startPosn, crc,
-        compressionMethod);
-    modWhen = getModTime(inputFp ? fileno(inputFp) : fileno(mZipFp));
-    pEntry->setModWhen(modWhen);
-    pEntry->setLFHOffset(lfhPosn);
-    mEOCD.mNumEntries++;
-    mEOCD.mTotalNumEntries++;
-    mEOCD.mCentralDirSize = 0;      // mark invalid; set by flush()
-    mEOCD.mCentralDirOffset = endPosn;
-
-    /*
-     * Go back and write the LFH.
-     */
-    if (fseek(mZipFp, lfhPosn, SEEK_SET) != 0) {
-        result = UNKNOWN_ERROR;
-        goto bail;
-    }
-    pEntry->mLFH.write(mZipFp);
-
-    /*
-     * Add pEntry to the list.
-     */
-    mEntries.add(pEntry);
-    if (ppEntry != NULL)
-        *ppEntry = pEntry;
-    pEntry = NULL;
-
-bail:
-    if (inputFp != NULL)
-        fclose(inputFp);
-    delete pEntry;
-    return result;
-}
-
-/*
- * Add an entry by copying it from another zip file.  If "padding" is
- * nonzero, the specified number of bytes will be added to the "extra"
- * field in the header.
- *
- * If "ppEntry" is non-NULL, a pointer to the new entry will be returned.
- */
-status_t ZipFile::add(const ZipFile* pSourceZip, const ZipEntry* pSourceEntry,
-    int padding, ZipEntry** ppEntry)
-{
-    ZipEntry* pEntry = NULL;
-    status_t result;
-    long lfhPosn, endPosn;
-
-    if (mReadOnly)
-        return INVALID_OPERATION;
-
-    /* make sure we're in a reasonable state */
-    assert(mZipFp != NULL);
-    assert(mEntries.size() == mEOCD.mTotalNumEntries);
-
-    if (fseek(mZipFp, mEOCD.mCentralDirOffset, SEEK_SET) != 0) {
-        result = UNKNOWN_ERROR;
-        goto bail;
-    }
-
-    pEntry = new ZipEntry;
-    if (pEntry == NULL) {
-        result = NO_MEMORY;
-        goto bail;
-    }
-
-    result = pEntry->initFromExternal(pSourceZip, pSourceEntry);
-    if (result != NO_ERROR)
-        goto bail;
-    if (padding != 0) {
-        result = pEntry->addPadding(padding);
-        if (result != NO_ERROR)
-            goto bail;
-    }
-
-    /*
-     * From here on out, failures are more interesting.
-     */
-    mNeedCDRewrite = true;
-
-    /*
-     * Write the LFH.  Since we're not recompressing the data, we already
-     * have all of the fields filled out.
-     */
-    lfhPosn = ftell(mZipFp);
-    pEntry->mLFH.write(mZipFp);
-
-    /*
-     * Copy the data over.
-     *
-     * If the "has data descriptor" flag is set, we want to copy the DD
-     * fields as well.  This is a fixed-size area immediately following
-     * the data.
-     */
-    if (fseek(pSourceZip->mZipFp, pSourceEntry->getFileOffset(), SEEK_SET) != 0)
-    {
-        result = UNKNOWN_ERROR;
-        goto bail;
-    }
-
-    off_t copyLen;
-    copyLen = pSourceEntry->getCompressedLen();
-    if ((pSourceEntry->mLFH.mGPBitFlag & ZipEntry::kUsesDataDescr) != 0)
-        copyLen += ZipEntry::kDataDescriptorLen;
-
-    if (copyPartialFpToFp(mZipFp, pSourceZip->mZipFp, copyLen, NULL)
-        != NO_ERROR)
-    {
-        LOGW("copy of '%s' failed\n", pEntry->mCDE.mFileName);
-        result = UNKNOWN_ERROR;
-        goto bail;
-    }
-
-    /*
-     * Update file offsets.
-     */
-    endPosn = ftell(mZipFp);
-
-    /*
-     * Success!  Fill out new values.
-     */
-    pEntry->setLFHOffset(lfhPosn);      // sets mCDE.mLocalHeaderRelOffset
-    mEOCD.mNumEntries++;
-    mEOCD.mTotalNumEntries++;
-    mEOCD.mCentralDirSize = 0;      // mark invalid; set by flush()
-    mEOCD.mCentralDirOffset = endPosn;
-
-    /*
-     * Add pEntry to the list.
-     */
-    mEntries.add(pEntry);
-    if (ppEntry != NULL)
-        *ppEntry = pEntry;
-    pEntry = NULL;
-
-    result = NO_ERROR;
-
-bail:
-    delete pEntry;
-    return result;
-}
-
-/*
- * Copy all of the bytes in "src" to "dst".
- *
- * On exit, "srcFp" will be seeked to the end of the file, and "dstFp"
- * will be seeked immediately past the data.
- */
-status_t ZipFile::copyFpToFp(FILE* dstFp, FILE* srcFp, unsigned long* pCRC32)
-{
-    unsigned char tmpBuf[32768];
-    size_t count;
-
-    *pCRC32 = crc32(0L, Z_NULL, 0);
-
-    while (1) {
-        count = fread(tmpBuf, 1, sizeof(tmpBuf), srcFp);
-        if (ferror(srcFp) || ferror(dstFp))
-            return errnoToStatus(errno);
-        if (count == 0)
-            break;
-
-        *pCRC32 = crc32(*pCRC32, tmpBuf, count);
-
-        if (fwrite(tmpBuf, 1, count, dstFp) != count) {
-            LOGD("fwrite %d bytes failed\n", (int) count);
-            return UNKNOWN_ERROR;
-        }
-    }
-
-    return NO_ERROR;
-}
-
-/*
- * Copy all of the bytes in "src" to "dst".
- *
- * On exit, "dstFp" will be seeked immediately past the data.
- */
-status_t ZipFile::copyDataToFp(FILE* dstFp,
-    const void* data, size_t size, unsigned long* pCRC32)
-{
-    size_t count;
-
-    *pCRC32 = crc32(0L, Z_NULL, 0);
-    if (size > 0) {
-        *pCRC32 = crc32(*pCRC32, (const unsigned char*)data, size);
-        if (fwrite(data, 1, size, dstFp) != size) {
-            LOGD("fwrite %d bytes failed\n", (int) size);
-            return UNKNOWN_ERROR;
-        }
-    }
-
-    return NO_ERROR;
-}
-
-/*
- * Copy some of the bytes in "src" to "dst".
- *
- * If "pCRC32" is NULL, the CRC will not be computed.
- *
- * On exit, "srcFp" will be seeked to the end of the file, and "dstFp"
- * will be seeked immediately past the data just written.
- */
-status_t ZipFile::copyPartialFpToFp(FILE* dstFp, FILE* srcFp, long length,
-    unsigned long* pCRC32)
-{
-    unsigned char tmpBuf[32768];
-    size_t count;
-
-    if (pCRC32 != NULL)
-        *pCRC32 = crc32(0L, Z_NULL, 0);
-
-    while (length) {
-        long readSize;
-        
-        readSize = sizeof(tmpBuf);
-        if (readSize > length)
-            readSize = length;
-
-        count = fread(tmpBuf, 1, readSize, srcFp);
-        if ((long) count != readSize) {     // error or unexpected EOF
-            LOGD("fread %d bytes failed\n", (int) readSize);
-            return UNKNOWN_ERROR;
-        }
-
-        if (pCRC32 != NULL)
-            *pCRC32 = crc32(*pCRC32, tmpBuf, count);
-
-        if (fwrite(tmpBuf, 1, count, dstFp) != count) {
-            LOGD("fwrite %d bytes failed\n", (int) count);
-            return UNKNOWN_ERROR;
-        }
-
-        length -= readSize;
-    }
-
-    return NO_ERROR;
-}
-
-/*
- * Compress all of the data in "srcFp" and write it to "dstFp".
- *
- * On exit, "srcFp" will be seeked to the end of the file, and "dstFp"
- * will be seeked immediately past the compressed data.
- */
-status_t ZipFile::compressFpToFp(FILE* dstFp, FILE* srcFp,
-    const void* data, size_t size, unsigned long* pCRC32)
-{
-    status_t result = NO_ERROR;
-	const size_t kBufSize = 32768;
-	unsigned char* inBuf = NULL;
-	unsigned char* outBuf = NULL;
-	z_stream zstream;
-    bool atEof = false;     // no feof() aviailable yet
-	unsigned long crc;
-	int zerr;
-
-	/*
-	 * Create an input buffer and an output buffer.
-	 */
-	inBuf = new unsigned char[kBufSize];
-	outBuf = new unsigned char[kBufSize];
-	if (inBuf == NULL || outBuf == NULL) {
-		result = NO_MEMORY;
-		goto bail;
-	}
-
-	/*
-	 * Initialize the zlib stream.
-	 */
-	memset(&zstream, 0, sizeof(zstream));
-	zstream.zalloc = Z_NULL;
-	zstream.zfree = Z_NULL;
-	zstream.opaque = Z_NULL;
-	zstream.next_in = NULL;
-	zstream.avail_in = 0;
-	zstream.next_out = outBuf;
-	zstream.avail_out = kBufSize;
-	zstream.data_type = Z_UNKNOWN;
-
-	zerr = deflateInit2(&zstream, Z_BEST_COMPRESSION,
-		Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY);
-	if (zerr != Z_OK) {
-		result = UNKNOWN_ERROR;
-		if (zerr == Z_VERSION_ERROR) {
-			LOGE("Installed zlib is not compatible with linked version (%s)\n",
-				ZLIB_VERSION);
-		} else {
-			LOGD("Call to deflateInit2 failed (zerr=%d)\n", zerr);
-		}
-		goto bail;
-	}
-
- 	crc = crc32(0L, Z_NULL, 0);
-
-	/*
-	 * Loop while we have data.
-	 */
-	do {
-		size_t getSize;
-		int flush;
-
-		/* only read if the input buffer is empty */
-		if (zstream.avail_in == 0 && !atEof) {
-            LOGV("+++ reading %d bytes\n", (int)kBufSize);
-            if (data) {
-                getSize = size > kBufSize ? kBufSize : size;
-                memcpy(inBuf, data, getSize);
-                data = ((const char*)data) + getSize;
-                size -= getSize;
-            } else {
-                getSize = fread(inBuf, 1, kBufSize, srcFp);
-                if (ferror(srcFp)) {
-                    LOGD("deflate read failed (errno=%d)\n", errno);
-                    goto z_bail;
-                }
-            }
-            if (getSize < kBufSize) {
-                LOGV("+++  got %d bytes, EOF reached\n",
-                    (int)getSize);
-                atEof = true;
-            }
-
-			crc = crc32(crc, inBuf, getSize);
-
-			zstream.next_in = inBuf;
-			zstream.avail_in = getSize;
-		}
-
-		if (atEof)
-			flush = Z_FINISH;       /* tell zlib that we're done */
-		else
-			flush = Z_NO_FLUSH;     /* more to come! */
-
-		zerr = deflate(&zstream, flush);
-		if (zerr != Z_OK && zerr != Z_STREAM_END) {
-			LOGD("zlib deflate call failed (zerr=%d)\n", zerr);
-			result = UNKNOWN_ERROR;
-			goto z_bail;
-		}
-
-		/* write when we're full or when we're done */
-		if (zstream.avail_out == 0 ||
-			(zerr == Z_STREAM_END && zstream.avail_out != (uInt) kBufSize))
-		{
-			LOGV("+++ writing %d bytes\n", (int) (zstream.next_out - outBuf));
-            if (fwrite(outBuf, 1, zstream.next_out - outBuf, dstFp) !=
-                (size_t)(zstream.next_out - outBuf))
-            {
-				LOGD("write %d failed in deflate\n",
-                    (int) (zstream.next_out - outBuf));
-				goto z_bail;
-			}
-
-			zstream.next_out = outBuf;
-			zstream.avail_out = kBufSize;
-		}
-	} while (zerr == Z_OK);
-
-	assert(zerr == Z_STREAM_END);       /* other errors should've been caught */
-
-	*pCRC32 = crc;
-
-z_bail:
-	deflateEnd(&zstream);        /* free up any allocated structures */
-
-bail:
-	delete[] inBuf;
-	delete[] outBuf;
-
-	return result;
-}
-
-/*
- * Mark an entry as deleted.
- *
- * We will eventually need to crunch the file down, but if several files
- * are being removed (perhaps as part of an "update" process) we can make
- * things considerably faster by deferring the removal to "flush" time.
- */
-status_t ZipFile::remove(ZipEntry* pEntry)
-{
-    /*
-     * Should verify that pEntry is actually part of this archive, and
-     * not some stray ZipEntry from a different file.
-     */
-
-    /* mark entry as deleted, and mark archive as dirty */
-    pEntry->setDeleted();
-    mNeedCDRewrite = true;
-    return NO_ERROR;
-}
-
-/*
- * Flush any pending writes.
- *
- * In particular, this will crunch out deleted entries, and write the
- * Central Directory and EOCD if we have stomped on them.
- */
-status_t ZipFile::flush(void)
-{
-    status_t result = NO_ERROR;
-    long eocdPosn;
-    int i, count;
-
-    if (mReadOnly)
-        return INVALID_OPERATION;
-    if (!mNeedCDRewrite)
-        return NO_ERROR;
-
-    assert(mZipFp != NULL);
-
-    result = crunchArchive();
-    if (result != NO_ERROR)
-        return result;
-
-    if (fseek(mZipFp, mEOCD.mCentralDirOffset, SEEK_SET) != 0)
-        return UNKNOWN_ERROR;
-
-    count = mEntries.size();
-    for (i = 0; i < count; i++) {
-        ZipEntry* pEntry = mEntries[i];
-        pEntry->mCDE.write(mZipFp);
-    }
-
-    eocdPosn = ftell(mZipFp);
-    mEOCD.mCentralDirSize = eocdPosn - mEOCD.mCentralDirOffset;
-
-    mEOCD.write(mZipFp);
-
-    /*
-     * If we had some stuff bloat up during compression and get replaced
-     * with plain files, or if we deleted some entries, there's a lot
-     * of wasted space at the end of the file.  Remove it now.
-     */
-    if (ftruncate(fileno(mZipFp), ftell(mZipFp)) != 0) {
-        LOGW("ftruncate failed %ld: %s\n", ftell(mZipFp), strerror(errno));
-        // not fatal
-    }
-
-    /* should we clear the "newly added" flag in all entries now? */
-
-    mNeedCDRewrite = false;
-    return NO_ERROR;
-}
-
-/*
- * Crunch deleted files out of an archive by shifting the later files down.
- *
- * Because we're not using a temp file, we do the operation inside the
- * current file.
- */
-status_t ZipFile::crunchArchive(void)
-{
-    status_t result = NO_ERROR;
-    int i, count;
-    long delCount, adjust;
-
-#if 0
-    printf("CONTENTS:\n");
-    for (i = 0; i < (int) mEntries.size(); i++) {
-        printf(" %d: lfhOff=%ld del=%d\n",
-            i, mEntries[i]->getLFHOffset(), mEntries[i]->getDeleted());
-    }
-    printf("  END is %ld\n", (long) mEOCD.mCentralDirOffset);
-#endif
-
-    /*
-     * Roll through the set of files, shifting them as appropriate.  We
-     * could probably get a slight performance improvement by sliding
-     * multiple files down at once (because we could use larger reads
-     * when operating on batches of small files), but it's not that useful.
-     */
-    count = mEntries.size();
-    delCount = adjust = 0;
-    for (i = 0; i < count; i++) {
-        ZipEntry* pEntry = mEntries[i];
-        long span;
-
-        if (pEntry->getLFHOffset() != 0) {
-            long nextOffset;
-
-            /* Get the length of this entry by finding the offset
-             * of the next entry.  Directory entries don't have
-             * file offsets, so we need to find the next non-directory
-             * entry.
-             */
-            nextOffset = 0;
-            for (int ii = i+1; nextOffset == 0 && ii < count; ii++)
-                nextOffset = mEntries[ii]->getLFHOffset();
-            if (nextOffset == 0)
-                nextOffset = mEOCD.mCentralDirOffset;
-            span = nextOffset - pEntry->getLFHOffset();
-
-            assert(span >= ZipEntry::LocalFileHeader::kLFHLen);
-        } else {
-            /* This is a directory entry.  It doesn't have
-             * any actual file contents, so there's no need to
-             * move anything.
-             */
-            span = 0;
-        }
-
-        //printf("+++ %d: off=%ld span=%ld del=%d [count=%d]\n",
-        //    i, pEntry->getLFHOffset(), span, pEntry->getDeleted(), count);
-
-        if (pEntry->getDeleted()) {
-            adjust += span;
-            delCount++;
-
-            delete pEntry;
-            mEntries.removeAt(i);
-
-            /* adjust loop control */
-            count--;
-            i--;
-        } else if (span != 0 && adjust > 0) {
-            /* shuffle this entry back */
-            //printf("+++ Shuffling '%s' back %ld\n",
-            //    pEntry->getFileName(), adjust);
-            result = filemove(mZipFp, pEntry->getLFHOffset() - adjust,
-                        pEntry->getLFHOffset(), span);
-            if (result != NO_ERROR) {
-                /* this is why you use a temp file */
-                LOGE("error during crunch - archive is toast\n");
-                return result;
-            }
-
-            pEntry->setLFHOffset(pEntry->getLFHOffset() - adjust);
-        }
-    }
-
-    /*
-     * Fix EOCD info.  We have to wait until the end to do some of this
-     * because we use mCentralDirOffset to determine "span" for the
-     * last entry.
-     */
-    mEOCD.mCentralDirOffset -= adjust;
-    mEOCD.mNumEntries -= delCount;
-    mEOCD.mTotalNumEntries -= delCount;
-    mEOCD.mCentralDirSize = 0;  // mark invalid; set by flush()
-
-    assert(mEOCD.mNumEntries == mEOCD.mTotalNumEntries);
-    assert(mEOCD.mNumEntries == count);
-
-    return result;
-}
-
-/*
- * Works like memmove(), but on pieces of a file.
- */
-status_t ZipFile::filemove(FILE* fp, off_t dst, off_t src, size_t n)
-{
-    if (dst == src || n <= 0)
-        return NO_ERROR;
-
-    unsigned char readBuf[32768];
-
-    if (dst < src) {
-        /* shift stuff toward start of file; must read from start */
-        while (n != 0) {
-            size_t getSize = sizeof(readBuf);
-            if (getSize > n)
-                getSize = n;
-
-            if (fseek(fp, (long) src, SEEK_SET) != 0) {
-                LOGD("filemove src seek %ld failed\n", (long) src);
-                return UNKNOWN_ERROR;
-            }
-
-            if (fread(readBuf, 1, getSize, fp) != getSize) {
-                LOGD("filemove read %ld off=%ld failed\n",
-                    (long) getSize, (long) src);
-                return UNKNOWN_ERROR;
-            }
-
-            if (fseek(fp, (long) dst, SEEK_SET) != 0) {
-                LOGD("filemove dst seek %ld failed\n", (long) dst);
-                return UNKNOWN_ERROR;
-            }
-
-            if (fwrite(readBuf, 1, getSize, fp) != getSize) {
-                LOGD("filemove write %ld off=%ld failed\n",
-                    (long) getSize, (long) dst);
-                return UNKNOWN_ERROR;
-            }
-
-            src += getSize;
-            dst += getSize;
-            n -= getSize;
-        }
-    } else {
-        /* shift stuff toward end of file; must read from end */
-        assert(false);      // write this someday, maybe
-        return UNKNOWN_ERROR;
-    }
-
-    return NO_ERROR;
-}
-
-
-/*
- * Get the modification time from a file descriptor.
- */
-time_t ZipFile::getModTime(int fd)
-{
-    struct stat sb;
-
-    if (fstat(fd, &sb) < 0) {
-        LOGD("HEY: fstat on fd %d failed\n", fd);
-        return (time_t) -1;
-    }
-
-    return sb.st_mtime;
-}
-
-
-#if 0       /* this is a bad idea */
-/*
- * Get a copy of the Zip file descriptor.
- *
- * We don't allow this if the file was opened read-write because we tend
- * to leave the file contents in an uncertain state between calls to
- * flush().  The duplicated file descriptor should only be valid for reads.
- */
-int ZipFile::getZipFd(void) const
-{
-    if (!mReadOnly)
-        return INVALID_OPERATION;
-    assert(mZipFp != NULL);
-
-    int fd;
-    fd = dup(fileno(mZipFp));
-    if (fd < 0) {
-        LOGD("didn't work, errno=%d\n", errno);
-    }
-
-    return fd;
-}
-#endif
-
-
-#if 0
-/*
- * Expand data.
- */
-bool ZipFile::uncompress(const ZipEntry* pEntry, void* buf) const
-{
-    return false;
-}
-#endif
-
-// free the memory when you're done
-void* ZipFile::uncompress(const ZipEntry* entry)
-{
-    size_t unlen = entry->getUncompressedLen();
-    size_t clen = entry->getCompressedLen();
-
-    void* buf = malloc(unlen);
-    if (buf == NULL) {
-        return NULL;
-    }
-
-    fseek(mZipFp, 0, SEEK_SET);
-
-    off_t offset = entry->getFileOffset();
-    if (fseek(mZipFp, offset, SEEK_SET) != 0) {
-        goto bail;
-    }
-
-    switch (entry->getCompressionMethod())
-    {
-        case ZipEntry::kCompressStored: {
-            ssize_t amt = fread(buf, 1, unlen, mZipFp);
-            if (amt != (ssize_t)unlen) {
-                goto bail;
-            }
-#if 0
-            printf("data...\n");
-            const unsigned char* p = (unsigned char*)buf;
-            const unsigned char* end = p+unlen;
-            for (int i=0; i<32 && p < end; i++) {
-                printf("0x%08x ", (int)(offset+(i*0x10)));
-                for (int j=0; j<0x10 && p < end; j++) {
-                    printf(" %02x", *p);
-                    p++;
-                }
-                printf("\n");
-            }
-#endif
-
-            }
-            break;
-        case ZipEntry::kCompressDeflated: {
-            if (!ZipUtils::inflateToBuffer(mZipFp, buf, unlen, clen)) {
-                goto bail;
-            }
-            }
-            break;
-        default:
-            goto bail;
-    }
-    return buf;
-
-bail:
-    free(buf);
-    return NULL;
-}
-
-
-/*
- * ===========================================================================
- *		ZipFile::EndOfCentralDir
- * ===========================================================================
- */
-
-/*
- * Read the end-of-central-dir fields.
- *
- * "buf" should be positioned at the EOCD signature, and should contain
- * the entire EOCD area including the comment.
- */
-status_t ZipFile::EndOfCentralDir::readBuf(const unsigned char* buf, int len)
-{
-    /* don't allow re-use */
-    assert(mComment == NULL);
-
-    if (len < kEOCDLen) {
-        /* looks like ZIP file got truncated */
-        LOGD(" Zip EOCD: expected >= %d bytes, found %d\n",
-            kEOCDLen, len);
-        return INVALID_OPERATION;
-    }
-
-    /* this should probably be an assert() */
-    if (ZipEntry::getLongLE(&buf[0x00]) != kSignature)
-        return UNKNOWN_ERROR;
-
-    mDiskNumber = ZipEntry::getShortLE(&buf[0x04]);
-    mDiskWithCentralDir = ZipEntry::getShortLE(&buf[0x06]);
-    mNumEntries = ZipEntry::getShortLE(&buf[0x08]);
-    mTotalNumEntries = ZipEntry::getShortLE(&buf[0x0a]);
-    mCentralDirSize = ZipEntry::getLongLE(&buf[0x0c]);
-    mCentralDirOffset = ZipEntry::getLongLE(&buf[0x10]);
-    mCommentLen = ZipEntry::getShortLE(&buf[0x14]);
-
-    // TODO: validate mCentralDirOffset
-
-    if (mCommentLen > 0) {
-        if (kEOCDLen + mCommentLen > len) {
-            LOGD("EOCD(%d) + comment(%d) exceeds len (%d)\n",
-                kEOCDLen, mCommentLen, len);
-            return UNKNOWN_ERROR;
-        }
-        mComment = new unsigned char[mCommentLen];
-        memcpy(mComment, buf + kEOCDLen, mCommentLen);
-    }
-
-    return NO_ERROR;
-}
-
-/*
- * Write an end-of-central-directory section.
- */
-status_t ZipFile::EndOfCentralDir::write(FILE* fp)
-{
-    unsigned char buf[kEOCDLen];
-
-    ZipEntry::putLongLE(&buf[0x00], kSignature);
-    ZipEntry::putShortLE(&buf[0x04], mDiskNumber);
-    ZipEntry::putShortLE(&buf[0x06], mDiskWithCentralDir);
-    ZipEntry::putShortLE(&buf[0x08], mNumEntries);
-    ZipEntry::putShortLE(&buf[0x0a], mTotalNumEntries);
-    ZipEntry::putLongLE(&buf[0x0c], mCentralDirSize);
-    ZipEntry::putLongLE(&buf[0x10], mCentralDirOffset);
-    ZipEntry::putShortLE(&buf[0x14], mCommentLen);
-
-    if (fwrite(buf, 1, kEOCDLen, fp) != kEOCDLen)
-        return UNKNOWN_ERROR;
-    if (mCommentLen > 0) {
-        assert(mComment != NULL);
-        if (fwrite(mComment, mCommentLen, 1, fp) != mCommentLen)
-            return UNKNOWN_ERROR;
-    }
-
-    return NO_ERROR;
-}
-
-/*
- * Dump the contents of an EndOfCentralDir object.
- */
-void ZipFile::EndOfCentralDir::dump(void) const
-{
-    LOGD(" EndOfCentralDir contents:\n");
-    LOGD("  diskNum=%u diskWCD=%u numEnt=%u totalNumEnt=%u\n",
-        mDiskNumber, mDiskWithCentralDir, mNumEntries, mTotalNumEntries);
-    LOGD("  centDirSize=%lu centDirOff=%lu commentLen=%u\n",
-        mCentralDirSize, mCentralDirOffset, mCommentLen);
-}
-
diff --git a/libs/utils/executablepath_darwin.cpp b/libs/utils/executablepath_darwin.cpp
deleted file mode 100644
index 2e3c3a0..0000000
--- a/libs/utils/executablepath_darwin.cpp
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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/executablepath.h>
-#import <Carbon/Carbon.h>
-#include <unistd.h>
-
-void executablepath(char s[PATH_MAX])
-{
-    ProcessSerialNumber psn;
-    GetCurrentProcess(&psn);
-    CFDictionaryRef dict;
-    dict = ProcessInformationCopyDictionary(&psn, 0xffffffff);
-    CFStringRef value = (CFStringRef)CFDictionaryGetValue(dict,
-                CFSTR("CFBundleExecutable"));
-    CFStringGetCString(value, s, PATH_MAX+1, kCFStringEncodingUTF8);
-}
-
diff --git a/libs/utils/executablepath_linux.cpp b/libs/utils/executablepath_linux.cpp
deleted file mode 100644
index b8d2a3d..0000000
--- a/libs/utils/executablepath_linux.cpp
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * 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/executablepath.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <limits.h>
-#include <stdio.h>
-
-void executablepath(char exe[PATH_MAX])
-{
-    char proc[100];
-    sprintf(proc, "/proc/%d/exe", getpid());
-    
-    int err = readlink(proc, exe, PATH_MAX);
-}
-
diff --git a/libs/utils/futex_synchro.c b/libs/utils/futex_synchro.c
deleted file mode 100644
index ab48c69..0000000
--- a/libs/utils/futex_synchro.c
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * 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 <stdio.h>
-#include <limits.h>
-
-#include <sys/time.h>
-#include <sched.h>
-
-#include <errno.h>
-
-#include <private/utils/futex_synchro.h>
-
-
-// This futex glue code is need on desktop linux, but is already part of bionic.
-#if !defined(HAVE_FUTEX_WRAPPERS)
-
-#include <unistd.h>
-#include <sys/syscall.h>
-typedef unsigned int u32;
-#define asmlinkage
-#define __user
-#include <linux/futex.h>
-#include <utils/Atomic.h>
-
-
-int futex (int *uaddr, int op, int val, const struct timespec *timeout, int *uaddr2, int val3)
-{
-    int err = syscall(SYS_futex, uaddr, op, val, timeout, uaddr2, val3);
-    return err == 0 ? 0 : -errno;
-}
-
-int __futex_wait(volatile void *ftx, int val, const struct timespec *timeout)
-{
-    return futex((int*)ftx, FUTEX_WAIT, val, timeout, NULL, 0);
-}
-
-int __futex_wake(volatile void *ftx, int count)
-{
-    return futex((int*)ftx, FUTEX_WAKE, count, NULL, NULL, 0);
-}
-
-int __atomic_cmpxchg(int old, int _new, volatile int *ptr)
-{
-    return android_atomic_cmpxchg(old, _new, ptr);
-}
-
-int __atomic_swap(int _new, volatile int *ptr)
-{
-    return android_atomic_swap(_new, ptr);
-}
-
-int __atomic_dec(volatile int *ptr)
-{
-    return android_atomic_dec(ptr);
-}
-
-#else // !defined(__arm__)
-
-int __futex_wait(volatile void *ftx, int val, const struct timespec *timeout);
-int __futex_wake(volatile void *ftx, int count);
-
-int __atomic_cmpxchg(int old, int _new, volatile int *ptr);
-int __atomic_swap(int _new, volatile int *ptr);
-int __atomic_dec(volatile int *ptr);
-
-#endif // !defined(HAVE_FUTEX_WRAPPERS)
-
-
-// lock states
-//
-// 0: unlocked
-// 1: locked, no waiters
-// 2: locked, maybe waiters
-
-void futex_mutex_init(futex_mutex_t *m)
-{
-    m->value = 0;
-}
-
-int futex_mutex_lock(futex_mutex_t *m, unsigned msec)
-{
-    if(__atomic_cmpxchg(0, 1, &m->value) == 0) {
-        return 0;
-    }
-    if(msec == FUTEX_WAIT_INFINITE) {
-        while(__atomic_swap(2, &m->value) != 0) {
-            __futex_wait(&m->value, 2, 0);
-        }
-    } else {
-        struct timespec ts;
-        ts.tv_sec = msec / 1000;
-        ts.tv_nsec = (msec % 1000) * 1000000;
-        while(__atomic_swap(2, &m->value) != 0) {
-            if(__futex_wait(&m->value, 2, &ts) == -ETIMEDOUT) {
-                return -1;
-            }
-        }
-    }
-    return 0;
-}
-
-int futex_mutex_trylock(futex_mutex_t *m)
-{
-    if(__atomic_cmpxchg(0, 1, &m->value) == 0) {
-        return 0;
-    }
-    return -1;
-}
-
-void futex_mutex_unlock(futex_mutex_t *m)
-{
-    if(__atomic_dec(&m->value) != 1) {
-        m->value = 0;
-        __futex_wake(&m->value, 1);
-    }
-}
-
-/* XXX *technically* there is a race condition that could allow
- * XXX a signal to be missed.  If thread A is preempted in _wait()
- * XXX after unlocking the mutex and before waiting, and if other
- * XXX threads call signal or broadcast UINT_MAX times (exactly),
- * XXX before thread A is scheduled again and calls futex_wait(),
- * XXX then the signal will be lost.
- */
-
-void futex_cond_init(futex_cond_t *c)
-{
-    c->value = 0;
-}
-
-int futex_cond_wait(futex_cond_t *c, futex_mutex_t *m, unsigned msec)
-{
-    if(msec == FUTEX_WAIT_INFINITE){
-        int oldvalue = c->value;
-        futex_mutex_unlock(m);
-        __futex_wait(&c->value, oldvalue, 0);
-        futex_mutex_lock(m, FUTEX_WAIT_INFINITE);
-        return 0;
-    } else {
-        int oldvalue = c->value;
-        struct timespec ts;        
-        ts.tv_sec = msec / 1000;
-        ts.tv_nsec = (msec % 1000) * 1000000;
-        futex_mutex_unlock(m);
-        const int err = __futex_wait(&c->value, oldvalue, &ts);
-        futex_mutex_lock(m, FUTEX_WAIT_INFINITE);
-        return err;
-    }
-}
-
-void futex_cond_signal(futex_cond_t *c)
-{
-    __atomic_dec(&c->value);
-    __futex_wake(&c->value, 1);
-}
-
-void futex_cond_broadcast(futex_cond_t *c)
-{
-    __atomic_dec(&c->value);
-    __futex_wake(&c->value, INT_MAX);
-}
-
diff --git a/libs/utils/ported.cpp b/libs/utils/ported.cpp
deleted file mode 100644
index 656e46f..0000000
--- a/libs/utils/ported.cpp
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2005 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.
- */
-
-//
-// Ports of standard functions that don't exist on a specific platform.
-//
-// Note these are NOT in the "android" namespace.
-//
-#include <utils/ported.h>
-
-#if defined(NEED_GETTIMEOFDAY) || defined(NEED_USLEEP)
-# include <sys/time.h>
-# include <windows.h>
-#endif
-
-
-#if defined(NEED_GETTIMEOFDAY)
-/*
- * Replacement gettimeofday() for Windows environments (primarily MinGW).
- *
- * Ignores "tz".
- */
-int gettimeofday(struct timeval* ptv, struct timezone* tz)
-{
-    long long nsTime;   // time in 100ns units since Jan 1 1601
-    FILETIME ft;
-
-    if (tz != NULL) {
-        // oh well
-    }
-
-    ::GetSystemTimeAsFileTime(&ft);
-    nsTime = (long long) ft.dwHighDateTime << 32 |
-             (long long) ft.dwLowDateTime;
-    // convert to time in usec since Jan 1 1970
-    ptv->tv_usec = (long) ((nsTime / 10LL) % 1000000LL);
-    ptv->tv_sec = (long) ((nsTime - 116444736000000000LL) / 10000000LL);
-
-    return 0;
-}
-#endif
-
-#if defined(NEED_USLEEP)
-//
-// Replacement usleep for Windows environments (primarily MinGW).
-//
-void usleep(unsigned long usec)
-{
-    // Win32 API function Sleep() takes milliseconds
-    ::Sleep((usec + 500) / 1000);
-}
-#endif
-
-#if 0 //defined(NEED_PIPE)
-//
-// Replacement pipe() command for MinGW
-//
-// The _O_NOINHERIT flag sets bInheritHandle to FALSE in the
-// SecurityAttributes argument to CreatePipe().  This means the handles
-// aren't inherited when a new process is created.  The examples I've seen
-// use it, possibly because there's a lot of junk going on behind the
-// scenes.  (I'm assuming "process" and "thread" are different here, so
-// we should be okay spinning up a thread.)  The recommended practice is
-// to dup() the descriptor you want the child to have.
-//
-// It appears that unnamed pipes can't do non-blocking ("overlapped") I/O.
-// You can't use select() either, since that only works on sockets.  The
-// Windows API calls that are useful here all operate on a HANDLE, not
-// an integer file descriptor, and I don't think you can get there from
-// here.  The "named pipe" stuff is insane.
-//
-int pipe(int filedes[2])
-{
-    return _pipe(filedes, 0, _O_BINARY | _O_NOINHERIT);
-}
-#endif
-
-#if defined(NEED_SETENV)
-/*
- * MinGW lacks these.  For now, just stub them out so the code compiles.
- */
-int setenv(const char* name, const char* value, int overwrite)
-{
-    return 0;
-}
-void unsetenv(const char* name)
-{
-}
-char* getenv(const char* name)
-{
-    return NULL;
-}
-#endif
diff --git a/opengl/include/EGL/eglext.h b/opengl/include/EGL/eglext.h
index 25cfcb8..545fd0e 100644
--- a/opengl/include/EGL/eglext.h
+++ b/opengl/include/EGL/eglext.h
@@ -131,6 +131,30 @@
 /* Interfaces defined by EGL_KHR_image above */
 #endif
 
+
+#ifndef EGL_ANDROID_image_native_buffer
+#define EGL_ANDROID_image_native_buffer 1
+struct android_native_buffer_t;
+#define EGL_NATIVE_BUFFER_ANDROID       0x3140  /* eglCreateImageKHR target */
+#endif
+
+#ifndef EGL_ANDROID_get_render_buffer
+#define EGL_ANDROID_get_render_buffer 1
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLClientBuffer EGLAPIENTRY eglGetRenderBufferANDROID(EGLDisplay dpy, EGLSurface draw);
+#endif
+typedef EGLClientBuffer (EGLAPIENTRYP PFNEGLGETRENDERBUFFERANDROIDPROC) (EGLDisplay dpy, EGLSurface draw);
+#endif
+
+#ifndef EGL_ANDROID_swap_rectangle
+#define EGL_ANDROID_swap_rectangle 1
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglSetSwapRectangleANDROID (EGLDisplay dpy, EGLSurface draw, EGLint left, EGLint top, EGLint width, EGLint height);
+#endif /* EGL_EGLEXT_PROTOTYPES */
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSETSWAPRECTANGLEANDROIDPROC) (EGLDisplay dpy, EGLSurface draw, EGLint left, EGLint top, EGLint width, EGLint height);
+#endif
+
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/opengl/include/EGL/eglnatives.h b/opengl/include/EGL/eglnatives.h
deleted file mode 100644
index 21622dc..0000000
--- a/opengl/include/EGL/eglnatives.h
+++ /dev/null
@@ -1,271 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_EGLNATIVES_H
-#define ANDROID_EGLNATIVES_H
-
-#include <sys/types.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*****************************************************************************/
-
-/* flags returned from swapBuffer */
-#define EGL_NATIVES_FLAG_SIZE_CHANGED       0x00000001
-
-/* surface flags */
-#define EGL_NATIVES_FLAG_DESTROY_BACKBUFFER 0x00000001
-
-enum native_pixel_format_t
-{
-    NATIVE_PIXEL_FORMAT_RGBA_8888   = 1,
-    NATIVE_PIXEL_FORMAT_RGB_565     = 4,
-    NATIVE_PIXEL_FORMAT_BGRA_8888   = 5,
-    NATIVE_PIXEL_FORMAT_RGBA_5551   = 6,
-    NATIVE_PIXEL_FORMAT_RGBA_4444   = 7,
-    NATIVE_PIXEL_FORMAT_YCbCr_422_SP= 0x10,
-    NATIVE_PIXEL_FORMAT_YCbCr_420_SP= 0x11,
-};
-
-enum native_memory_type_t
-{
-    NATIVE_MEMORY_TYPE_PMEM         = 0,
-    NATIVE_MEMORY_TYPE_GPU          = 1,
-    NATIVE_MEMORY_TYPE_FB           = 2,
-    NATIVE_MEMORY_TYPE_HEAP         = 128
-};
-
-
-struct egl_native_window_t
-{
-    /*
-     * magic must be set to 0x600913
-     */
-    uint32_t    magic;
-    
-    /*
-     * must be sizeof(egl_native_window_t)
-     */
-    uint32_t    version;
-
-    /*
-     * ident is reserved for the Android platform
-     */
-    uint32_t    ident;
-    
-    /*
-     * width, height and stride of the window in pixels
-     * Any of these value can be nul in which case GL commands are
-     * accepted and processed as usual, but not rendering occurs.
-     */
-    int         width;      // w=h=0 is legal
-    int         height;
-    int         stride;
-
-    /*
-     * format of the native window (see ui/PixelFormat.h)
-     */
-    int         format;
-    
-    /*
-     * Offset of the bits in the VRAM
-     */
-    intptr_t    offset;
-    
-    /*
-     * flags describing some attributes of this surface
-     * EGL_NATIVES_FLAG_DESTROY_BACKBUFFER: backbuffer not preserved after 
-     * eglSwapBuffers
-     */
-    uint32_t    flags;
-    
-    /*
-     * horizontal and vertical resolution in DPI
-     */
-    float       xdpi;
-    float       ydpi;
-    
-    /*
-     * refresh rate in frames per second (Hz)
-     */
-    float       fps;
-    
-    
-    /*
-     *  Base memory virtual address of the surface in the CPU side
-     */
-    intptr_t    base;
-    
-    /*
-     *  Heap the offset above is based from
-     */
-    int         fd;
-    
-    /*
-     *  Memory type the surface resides into
-     */
-    uint8_t     memory_type;
-    
-    /*
-     * Reserved for future use. MUST BE ZERO.
-     */
-    uint8_t     reserved_pad[3];
-    int         reserved[8];
-    
-    /*
-     * Vertical stride (only relevant with planar formats) 
-     */
-    
-    int         vstride;
-
-    /*
-     * Hook called by EGL to hold a reference on this structure
-     */
-    void        (*incRef)(struct egl_native_window_t* window);
-
-    /*
-     * Hook called by EGL to release a reference on this structure
-     */
-    void        (*decRef)(struct egl_native_window_t* window);
-
-    /*
-     * Hook called by EGL to perform a page flip. This function
-     * may update the size attributes above, in which case it returns
-     * the EGL_NATIVES_FLAG_SIZE_CHANGED bit set.
-     */
-    uint32_t    (*swapBuffers)(struct egl_native_window_t* window);
-    
-    /*
-     * Reserved for future use. MUST BE ZERO.
-     */
-    void        (*reserved_proc_0)(void);
-
-    /*
-     * Reserved for future use. MUST BE ZERO.
-     */
-    void        (*reserved_proc_1)(void);
-    
-    /*
-     * Reserved for future use. MUST BE ZERO.
-     */
-    void        (*reserved_proc_2)(void);
-
-    
-    /*
-     * Hook called by EGL when the native surface is associated to EGL
-     * (eglCreateWindowSurface). Can be NULL.
-     */
-    void        (*connect)(struct egl_native_window_t* window);
-
-    /*
-     * Hook called by EGL when eglDestroySurface is called.  Can be NULL.
-     */
-    void        (*disconnect)(struct egl_native_window_t* window);
-    
-    /*
-     * Reserved for future use. MUST BE ZERO.
-     */
-    void        (*reserved_proc[11])(void);
-    
-    /*
-     *  Some storage reserved for the oem driver.
-     */
-    intptr_t    oem[4];
-};
-
-
-struct egl_native_pixmap_t
-{
-    int32_t     version;    /* must be 32 */
-    int32_t     width;
-    int32_t     height;
-    int32_t     stride;
-    uint8_t*    data;
-    uint8_t     format;
-    uint8_t     rfu[3];
-    union {
-        uint32_t    compressedFormat;
-        int32_t     vstride;
-    };
-    int32_t     reserved;
-};
-
-/*****************************************************************************/
-
-/* 
- * This a convenience function to create a NativeWindowType surface
- * that maps to the whole screen
- * This function is actually implemented in libui.so
- */
-
-struct egl_native_window_t* android_createDisplaySurface();
-
-/*****************************************************************************/
-
-
-/*
- * OEM's egl's library (libhgl.so) must imlement these hooks to allocate
- * the GPU memory they need  
- */
-
-
-typedef struct
-{
-    // for internal use
-    void*   user;
-    // virtual address of this area
-    void*   base;
-    // size of this area in bytes
-    size_t  size;
-    // physical address of this area
-    void*   phys;
-    // offset in this area available to the GPU
-    size_t  offset;
-    // fd of this area
-    int     fd;
-} gpu_area_t;
-
-typedef struct
-{
-    // area where GPU registers are mapped
-    gpu_area_t regs;
-    // number of extra areas (currently limited to 2)
-    int32_t count;
-    // extra GPU areas (currently limited to 2)
-    gpu_area_t gpu[2];
-} request_gpu_t;
-
-
-typedef request_gpu_t* (*OEM_EGL_acquire_gpu_t)(void* user);
-typedef int (*OEM_EGL_release_gpu_t)(void* user, request_gpu_t* handle);
-typedef void (*register_gpu_t)
-        (void* user, OEM_EGL_acquire_gpu_t, OEM_EGL_release_gpu_t);
-
-void oem_register_gpu(
-        void* user,
-        OEM_EGL_acquire_gpu_t acquire,
-        OEM_EGL_release_gpu_t release);
-
-
-/*****************************************************************************/
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* ANDROID_EGLNATIVES_H */
diff --git a/opengl/include/EGL/eglplatform.h b/opengl/include/EGL/eglplatform.h
index ac00901..53e9e61 100644
--- a/opengl/include/EGL/eglplatform.h
+++ b/opengl/include/EGL/eglplatform.h
@@ -89,9 +89,10 @@
 
 #elif defined(ANDROID)
 
-#include <EGL/eglnatives.h>
+struct android_native_window_t;
+struct egl_native_pixmap_t;
 
-typedef struct egl_native_window_t*     EGLNativeWindowType;
+typedef struct android_native_window_t* EGLNativeWindowType;
 typedef struct egl_native_pixmap_t*     EGLNativePixmapType;
 typedef void*                           EGLNativeDisplayType;
 
diff --git a/opengl/include/GLES/glplatform.h b/opengl/include/GLES/glplatform.h
index 0924cae..198e679 100644
--- a/opengl/include/GLES/glplatform.h
+++ b/opengl/include/GLES/glplatform.h
@@ -28,12 +28,6 @@
 
 #define GL_APIENTRY KHRONOS_APIENTRY
 
-// XXX: this should probably not be here
-#define GL_DIRECT_TEXTURE_2D_QUALCOMM               0x7E80
-
-// XXX: not sure how this is intended to be used
-#define GL_GLEXT_PROTOTYPES
-
 #endif
 
 #endif /* __glplatform_h_ */
diff --git a/opengl/include/GLES2/gl2.h b/opengl/include/GLES2/gl2.h
new file mode 100644
index 0000000..0182a67
--- /dev/null
+++ b/opengl/include/GLES2/gl2.h
@@ -0,0 +1,620 @@
+#ifndef __gl2_h_
+#define __gl2_h_
+
+/* $Revision: 7173 $ on $Date:: 2009-01-09 11:18:21 -0800 #$ */
+
+#include <GLES2/gl2platform.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This document is licensed under the SGI Free Software B License Version
+ * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ .
+ */
+
+/*-------------------------------------------------------------------------
+ * Data type definitions
+ *-----------------------------------------------------------------------*/
+
+typedef void             GLvoid;
+typedef unsigned int     GLenum;
+typedef unsigned char    GLboolean;
+typedef unsigned int     GLbitfield;
+typedef khronos_int8_t   GLbyte;
+typedef short            GLshort;
+typedef int              GLint;
+typedef int              GLsizei;
+typedef khronos_uint8_t  GLubyte;
+typedef unsigned short   GLushort;
+typedef unsigned int     GLuint;
+typedef khronos_float_t  GLfloat;
+typedef khronos_float_t  GLclampf;
+typedef khronos_int32_t  GLfixed;
+
+/* GL types for handling large vertex buffer objects */
+typedef khronos_intptr_t GLintptr;
+typedef khronos_ssize_t  GLsizeiptr;
+
+/* OpenGL ES core versions */
+#define GL_ES_VERSION_2_0                 1
+
+/* ClearBufferMask */
+#define GL_DEPTH_BUFFER_BIT               0x00000100
+#define GL_STENCIL_BUFFER_BIT             0x00000400
+#define GL_COLOR_BUFFER_BIT               0x00004000
+
+/* Boolean */
+#define GL_FALSE                          0
+#define GL_TRUE                           1
+
+/* BeginMode */
+#define GL_POINTS                         0x0000
+#define GL_LINES                          0x0001
+#define GL_LINE_LOOP                      0x0002
+#define GL_LINE_STRIP                     0x0003
+#define GL_TRIANGLES                      0x0004
+#define GL_TRIANGLE_STRIP                 0x0005
+#define GL_TRIANGLE_FAN                   0x0006
+
+/* AlphaFunction (not supported in ES20) */
+/*      GL_NEVER */
+/*      GL_LESS */
+/*      GL_EQUAL */
+/*      GL_LEQUAL */
+/*      GL_GREATER */
+/*      GL_NOTEQUAL */
+/*      GL_GEQUAL */
+/*      GL_ALWAYS */
+
+/* BlendingFactorDest */
+#define GL_ZERO                           0
+#define GL_ONE                            1
+#define GL_SRC_COLOR                      0x0300
+#define GL_ONE_MINUS_SRC_COLOR            0x0301
+#define GL_SRC_ALPHA                      0x0302
+#define GL_ONE_MINUS_SRC_ALPHA            0x0303
+#define GL_DST_ALPHA                      0x0304
+#define GL_ONE_MINUS_DST_ALPHA            0x0305
+
+/* BlendingFactorSrc */
+/*      GL_ZERO */
+/*      GL_ONE */
+#define GL_DST_COLOR                      0x0306
+#define GL_ONE_MINUS_DST_COLOR            0x0307
+#define GL_SRC_ALPHA_SATURATE             0x0308
+/*      GL_SRC_ALPHA */
+/*      GL_ONE_MINUS_SRC_ALPHA */
+/*      GL_DST_ALPHA */
+/*      GL_ONE_MINUS_DST_ALPHA */
+
+/* BlendEquationSeparate */
+#define GL_FUNC_ADD                       0x8006
+#define GL_BLEND_EQUATION                 0x8009
+#define GL_BLEND_EQUATION_RGB             0x8009    /* same as BLEND_EQUATION */
+#define GL_BLEND_EQUATION_ALPHA           0x883D
+
+/* BlendSubtract */
+#define GL_FUNC_SUBTRACT                  0x800A
+#define GL_FUNC_REVERSE_SUBTRACT          0x800B
+
+/* Separate Blend Functions */
+#define GL_BLEND_DST_RGB                  0x80C8
+#define GL_BLEND_SRC_RGB                  0x80C9
+#define GL_BLEND_DST_ALPHA                0x80CA
+#define GL_BLEND_SRC_ALPHA                0x80CB
+#define GL_CONSTANT_COLOR                 0x8001
+#define GL_ONE_MINUS_CONSTANT_COLOR       0x8002
+#define GL_CONSTANT_ALPHA                 0x8003
+#define GL_ONE_MINUS_CONSTANT_ALPHA       0x8004
+#define GL_BLEND_COLOR                    0x8005
+
+/* Buffer Objects */
+#define GL_ARRAY_BUFFER                   0x8892
+#define GL_ELEMENT_ARRAY_BUFFER           0x8893
+#define GL_ARRAY_BUFFER_BINDING           0x8894
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING   0x8895
+
+#define GL_STREAM_DRAW                    0x88E0
+#define GL_STATIC_DRAW                    0x88E4
+#define GL_DYNAMIC_DRAW                   0x88E8
+
+#define GL_BUFFER_SIZE                    0x8764
+#define GL_BUFFER_USAGE                   0x8765
+
+#define GL_CURRENT_VERTEX_ATTRIB          0x8626
+
+/* CullFaceMode */
+#define GL_FRONT                          0x0404
+#define GL_BACK                           0x0405
+#define GL_FRONT_AND_BACK                 0x0408
+
+/* DepthFunction */
+/*      GL_NEVER */
+/*      GL_LESS */
+/*      GL_EQUAL */
+/*      GL_LEQUAL */
+/*      GL_GREATER */
+/*      GL_NOTEQUAL */
+/*      GL_GEQUAL */
+/*      GL_ALWAYS */
+
+/* EnableCap */
+#define GL_TEXTURE_2D                     0x0DE1
+#define GL_CULL_FACE                      0x0B44
+#define GL_BLEND                          0x0BE2
+#define GL_DITHER                         0x0BD0
+#define GL_STENCIL_TEST                   0x0B90
+#define GL_DEPTH_TEST                     0x0B71
+#define GL_SCISSOR_TEST                   0x0C11
+#define GL_POLYGON_OFFSET_FILL            0x8037
+#define GL_SAMPLE_ALPHA_TO_COVERAGE       0x809E
+#define GL_SAMPLE_COVERAGE                0x80A0
+
+/* ErrorCode */
+#define GL_NO_ERROR                       0
+#define GL_INVALID_ENUM                   0x0500
+#define GL_INVALID_VALUE                  0x0501
+#define GL_INVALID_OPERATION              0x0502
+#define GL_OUT_OF_MEMORY                  0x0505
+
+/* FrontFaceDirection */
+#define GL_CW                             0x0900
+#define GL_CCW                            0x0901
+
+/* GetPName */
+#define GL_LINE_WIDTH                     0x0B21
+#define GL_ALIASED_POINT_SIZE_RANGE       0x846D
+#define GL_ALIASED_LINE_WIDTH_RANGE       0x846E
+#define GL_CULL_FACE_MODE                 0x0B45
+#define GL_FRONT_FACE                     0x0B46
+#define GL_DEPTH_RANGE                    0x0B70
+#define GL_DEPTH_WRITEMASK                0x0B72
+#define GL_DEPTH_CLEAR_VALUE              0x0B73
+#define GL_DEPTH_FUNC                     0x0B74
+#define GL_STENCIL_CLEAR_VALUE            0x0B91
+#define GL_STENCIL_FUNC                   0x0B92
+#define GL_STENCIL_FAIL                   0x0B94
+#define GL_STENCIL_PASS_DEPTH_FAIL        0x0B95
+#define GL_STENCIL_PASS_DEPTH_PASS        0x0B96
+#define GL_STENCIL_REF                    0x0B97
+#define GL_STENCIL_VALUE_MASK             0x0B93
+#define GL_STENCIL_WRITEMASK              0x0B98
+#define GL_STENCIL_BACK_FUNC              0x8800
+#define GL_STENCIL_BACK_FAIL              0x8801
+#define GL_STENCIL_BACK_PASS_DEPTH_FAIL   0x8802
+#define GL_STENCIL_BACK_PASS_DEPTH_PASS   0x8803
+#define GL_STENCIL_BACK_REF               0x8CA3
+#define GL_STENCIL_BACK_VALUE_MASK        0x8CA4
+#define GL_STENCIL_BACK_WRITEMASK         0x8CA5
+#define GL_VIEWPORT                       0x0BA2
+#define GL_SCISSOR_BOX                    0x0C10
+/*      GL_SCISSOR_TEST */
+#define GL_COLOR_CLEAR_VALUE              0x0C22
+#define GL_COLOR_WRITEMASK                0x0C23
+#define GL_UNPACK_ALIGNMENT               0x0CF5
+#define GL_PACK_ALIGNMENT                 0x0D05
+#define GL_MAX_TEXTURE_SIZE               0x0D33
+#define GL_MAX_VIEWPORT_DIMS              0x0D3A
+#define GL_SUBPIXEL_BITS                  0x0D50
+#define GL_RED_BITS                       0x0D52
+#define GL_GREEN_BITS                     0x0D53
+#define GL_BLUE_BITS                      0x0D54
+#define GL_ALPHA_BITS                     0x0D55
+#define GL_DEPTH_BITS                     0x0D56
+#define GL_STENCIL_BITS                   0x0D57
+#define GL_POLYGON_OFFSET_UNITS           0x2A00
+/*      GL_POLYGON_OFFSET_FILL */
+#define GL_POLYGON_OFFSET_FACTOR          0x8038
+#define GL_TEXTURE_BINDING_2D             0x8069
+#define GL_SAMPLE_BUFFERS                 0x80A8
+#define GL_SAMPLES                        0x80A9
+#define GL_SAMPLE_COVERAGE_VALUE          0x80AA
+#define GL_SAMPLE_COVERAGE_INVERT         0x80AB
+
+/* GetTextureParameter */
+/*      GL_TEXTURE_MAG_FILTER */
+/*      GL_TEXTURE_MIN_FILTER */
+/*      GL_TEXTURE_WRAP_S */
+/*      GL_TEXTURE_WRAP_T */
+
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
+#define GL_COMPRESSED_TEXTURE_FORMATS     0x86A3
+
+/* HintMode */
+#define GL_DONT_CARE                      0x1100
+#define GL_FASTEST                        0x1101
+#define GL_NICEST                         0x1102
+
+/* HintTarget */
+#define GL_GENERATE_MIPMAP_HINT            0x8192
+
+/* DataType */
+#define GL_BYTE                           0x1400
+#define GL_UNSIGNED_BYTE                  0x1401
+#define GL_SHORT                          0x1402
+#define GL_UNSIGNED_SHORT                 0x1403
+#define GL_INT                            0x1404
+#define GL_UNSIGNED_INT                   0x1405
+#define GL_FLOAT                          0x1406
+#define GL_FIXED                          0x140C
+
+/* PixelFormat */
+#define GL_DEPTH_COMPONENT                0x1902
+#define GL_ALPHA                          0x1906
+#define GL_RGB                            0x1907
+#define GL_RGBA                           0x1908
+#define GL_LUMINANCE                      0x1909
+#define GL_LUMINANCE_ALPHA                0x190A
+
+/* PixelType */
+/*      GL_UNSIGNED_BYTE */
+#define GL_UNSIGNED_SHORT_4_4_4_4         0x8033
+#define GL_UNSIGNED_SHORT_5_5_5_1         0x8034
+#define GL_UNSIGNED_SHORT_5_6_5           0x8363
+
+/* Shaders */
+#define GL_FRAGMENT_SHADER                  0x8B30
+#define GL_VERTEX_SHADER                    0x8B31
+#define GL_MAX_VERTEX_ATTRIBS               0x8869
+#define GL_MAX_VERTEX_UNIFORM_VECTORS       0x8DFB
+#define GL_MAX_VARYING_VECTORS              0x8DFC
+#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
+#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS   0x8B4C
+#define GL_MAX_TEXTURE_IMAGE_UNITS          0x8872
+#define GL_MAX_FRAGMENT_UNIFORM_VECTORS     0x8DFD
+#define GL_SHADER_TYPE                      0x8B4F
+#define GL_DELETE_STATUS                    0x8B80
+#define GL_LINK_STATUS                      0x8B82
+#define GL_VALIDATE_STATUS                  0x8B83
+#define GL_ATTACHED_SHADERS                 0x8B85
+#define GL_ACTIVE_UNIFORMS                  0x8B86
+#define GL_ACTIVE_UNIFORM_MAX_LENGTH        0x8B87
+#define GL_ACTIVE_ATTRIBUTES                0x8B89
+#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH      0x8B8A
+#define GL_SHADING_LANGUAGE_VERSION         0x8B8C
+#define GL_CURRENT_PROGRAM                  0x8B8D
+
+/* StencilFunction */
+#define GL_NEVER                          0x0200
+#define GL_LESS                           0x0201
+#define GL_EQUAL                          0x0202
+#define GL_LEQUAL                         0x0203
+#define GL_GREATER                        0x0204
+#define GL_NOTEQUAL                       0x0205
+#define GL_GEQUAL                         0x0206
+#define GL_ALWAYS                         0x0207
+
+/* StencilOp */
+/*      GL_ZERO */
+#define GL_KEEP                           0x1E00
+#define GL_REPLACE                        0x1E01
+#define GL_INCR                           0x1E02
+#define GL_DECR                           0x1E03
+#define GL_INVERT                         0x150A
+#define GL_INCR_WRAP                      0x8507
+#define GL_DECR_WRAP                      0x8508
+
+/* StringName */
+#define GL_VENDOR                         0x1F00
+#define GL_RENDERER                       0x1F01
+#define GL_VERSION                        0x1F02
+#define GL_EXTENSIONS                     0x1F03
+
+/* TextureMagFilter */
+#define GL_NEAREST                        0x2600
+#define GL_LINEAR                         0x2601
+
+/* TextureMinFilter */
+/*      GL_NEAREST */
+/*      GL_LINEAR */
+#define GL_NEAREST_MIPMAP_NEAREST         0x2700
+#define GL_LINEAR_MIPMAP_NEAREST          0x2701
+#define GL_NEAREST_MIPMAP_LINEAR          0x2702
+#define GL_LINEAR_MIPMAP_LINEAR           0x2703
+
+/* TextureParameterName */
+#define GL_TEXTURE_MAG_FILTER             0x2800
+#define GL_TEXTURE_MIN_FILTER             0x2801
+#define GL_TEXTURE_WRAP_S                 0x2802
+#define GL_TEXTURE_WRAP_T                 0x2803
+
+/* TextureTarget */
+/*      GL_TEXTURE_2D */
+#define GL_TEXTURE                        0x1702
+
+#define GL_TEXTURE_CUBE_MAP               0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP       0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X    0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X    0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y    0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y    0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z    0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z    0x851A
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE      0x851C
+
+/* TextureUnit */
+#define GL_TEXTURE0                       0x84C0
+#define GL_TEXTURE1                       0x84C1
+#define GL_TEXTURE2                       0x84C2
+#define GL_TEXTURE3                       0x84C3
+#define GL_TEXTURE4                       0x84C4
+#define GL_TEXTURE5                       0x84C5
+#define GL_TEXTURE6                       0x84C6
+#define GL_TEXTURE7                       0x84C7
+#define GL_TEXTURE8                       0x84C8
+#define GL_TEXTURE9                       0x84C9
+#define GL_TEXTURE10                      0x84CA
+#define GL_TEXTURE11                      0x84CB
+#define GL_TEXTURE12                      0x84CC
+#define GL_TEXTURE13                      0x84CD
+#define GL_TEXTURE14                      0x84CE
+#define GL_TEXTURE15                      0x84CF
+#define GL_TEXTURE16                      0x84D0
+#define GL_TEXTURE17                      0x84D1
+#define GL_TEXTURE18                      0x84D2
+#define GL_TEXTURE19                      0x84D3
+#define GL_TEXTURE20                      0x84D4
+#define GL_TEXTURE21                      0x84D5
+#define GL_TEXTURE22                      0x84D6
+#define GL_TEXTURE23                      0x84D7
+#define GL_TEXTURE24                      0x84D8
+#define GL_TEXTURE25                      0x84D9
+#define GL_TEXTURE26                      0x84DA
+#define GL_TEXTURE27                      0x84DB
+#define GL_TEXTURE28                      0x84DC
+#define GL_TEXTURE29                      0x84DD
+#define GL_TEXTURE30                      0x84DE
+#define GL_TEXTURE31                      0x84DF
+#define GL_ACTIVE_TEXTURE                 0x84E0
+
+/* TextureWrapMode */
+#define GL_REPEAT                         0x2901
+#define GL_CLAMP_TO_EDGE                  0x812F
+#define GL_MIRRORED_REPEAT                0x8370
+
+/* Uniform Types */
+#define GL_FLOAT_VEC2                     0x8B50
+#define GL_FLOAT_VEC3                     0x8B51
+#define GL_FLOAT_VEC4                     0x8B52
+#define GL_INT_VEC2                       0x8B53
+#define GL_INT_VEC3                       0x8B54
+#define GL_INT_VEC4                       0x8B55
+#define GL_BOOL                           0x8B56
+#define GL_BOOL_VEC2                      0x8B57
+#define GL_BOOL_VEC3                      0x8B58
+#define GL_BOOL_VEC4                      0x8B59
+#define GL_FLOAT_MAT2                     0x8B5A
+#define GL_FLOAT_MAT3                     0x8B5B
+#define GL_FLOAT_MAT4                     0x8B5C
+#define GL_SAMPLER_2D                     0x8B5E
+#define GL_SAMPLER_CUBE                   0x8B60
+
+/* Vertex Arrays */
+#define GL_VERTEX_ATTRIB_ARRAY_ENABLED        0x8622
+#define GL_VERTEX_ATTRIB_ARRAY_SIZE           0x8623
+#define GL_VERTEX_ATTRIB_ARRAY_STRIDE         0x8624
+#define GL_VERTEX_ATTRIB_ARRAY_TYPE           0x8625
+#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED     0x886A
+#define GL_VERTEX_ATTRIB_ARRAY_POINTER        0x8645
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
+
+/* Read Format */
+#define GL_IMPLEMENTATION_COLOR_READ_TYPE   0x8B9A
+#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B
+
+/* Shader Source */
+#define GL_COMPILE_STATUS                 0x8B81
+#define GL_INFO_LOG_LENGTH                0x8B84
+#define GL_SHADER_SOURCE_LENGTH           0x8B88
+#define GL_SHADER_COMPILER                0x8DFA
+
+/* Shader Binary */
+#define GL_SHADER_BINARY_FORMATS          0x8DF8
+#define GL_NUM_SHADER_BINARY_FORMATS      0x8DF9
+
+/* Shader Precision-Specified Types */
+#define GL_LOW_FLOAT                      0x8DF0
+#define GL_MEDIUM_FLOAT                   0x8DF1
+#define GL_HIGH_FLOAT                     0x8DF2
+#define GL_LOW_INT                        0x8DF3
+#define GL_MEDIUM_INT                     0x8DF4
+#define GL_HIGH_INT                       0x8DF5
+
+/* Framebuffer Object. */
+#define GL_FRAMEBUFFER                    0x8D40
+#define GL_RENDERBUFFER                   0x8D41
+
+#define GL_RGBA4                          0x8056
+#define GL_RGB5_A1                        0x8057
+#define GL_RGB565                         0x8D62
+#define GL_DEPTH_COMPONENT16              0x81A5
+#define GL_STENCIL_INDEX                  0x1901
+#define GL_STENCIL_INDEX8                 0x8D48
+
+#define GL_RENDERBUFFER_WIDTH             0x8D42
+#define GL_RENDERBUFFER_HEIGHT            0x8D43
+#define GL_RENDERBUFFER_INTERNAL_FORMAT   0x8D44
+#define GL_RENDERBUFFER_RED_SIZE          0x8D50
+#define GL_RENDERBUFFER_GREEN_SIZE        0x8D51
+#define GL_RENDERBUFFER_BLUE_SIZE         0x8D52
+#define GL_RENDERBUFFER_ALPHA_SIZE        0x8D53
+#define GL_RENDERBUFFER_DEPTH_SIZE        0x8D54
+#define GL_RENDERBUFFER_STENCIL_SIZE      0x8D55
+
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE           0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME           0x8CD1
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL         0x8CD2
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3
+
+#define GL_COLOR_ATTACHMENT0              0x8CE0
+#define GL_DEPTH_ATTACHMENT               0x8D00
+#define GL_STENCIL_ATTACHMENT             0x8D20
+
+#define GL_NONE                           0
+
+#define GL_FRAMEBUFFER_COMPLETE                      0x8CD5
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT         0x8CD6
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
+#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS         0x8CD9
+#define GL_FRAMEBUFFER_UNSUPPORTED                   0x8CDD
+
+#define GL_FRAMEBUFFER_BINDING            0x8CA6
+#define GL_RENDERBUFFER_BINDING           0x8CA7
+#define GL_MAX_RENDERBUFFER_SIZE          0x84E8
+
+#define GL_INVALID_FRAMEBUFFER_OPERATION  0x0506
+
+/*-------------------------------------------------------------------------
+ * GL core functions.
+ *-----------------------------------------------------------------------*/
+
+GL_APICALL void         GL_APIENTRY glActiveTexture (GLenum texture);
+GL_APICALL void         GL_APIENTRY glAttachShader (GLuint program, GLuint shader);
+GL_APICALL void         GL_APIENTRY glBindAttribLocation (GLuint program, GLuint index, const char* name);
+GL_APICALL void         GL_APIENTRY glBindBuffer (GLenum target, GLuint buffer);
+GL_APICALL void         GL_APIENTRY glBindFramebuffer (GLenum target, GLuint framebuffer);
+GL_APICALL void         GL_APIENTRY glBindRenderbuffer (GLenum target, GLuint renderbuffer);
+GL_APICALL void         GL_APIENTRY glBindTexture (GLenum target, GLuint texture);
+GL_APICALL void         GL_APIENTRY glBlendColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+GL_APICALL void         GL_APIENTRY glBlendEquation ( GLenum mode );
+GL_APICALL void         GL_APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha);
+GL_APICALL void         GL_APIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor);
+GL_APICALL void         GL_APIENTRY glBlendFuncSeparate (GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+GL_APICALL void         GL_APIENTRY glBufferData (GLenum target, GLsizeiptr size, const void* data, GLenum usage);
+GL_APICALL void         GL_APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const void* data);
+GL_APICALL GLenum       GL_APIENTRY glCheckFramebufferStatus (GLenum target);
+GL_APICALL void         GL_APIENTRY glClear (GLbitfield mask);
+GL_APICALL void         GL_APIENTRY glClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+GL_APICALL void         GL_APIENTRY glClearDepthf (GLclampf depth);
+GL_APICALL void         GL_APIENTRY glClearStencil (GLint s);
+GL_APICALL void         GL_APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+GL_APICALL void         GL_APIENTRY glCompileShader (GLuint shader);
+GL_APICALL void         GL_APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data);
+GL_APICALL void         GL_APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data);
+GL_APICALL void         GL_APIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+GL_APICALL void         GL_APIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL GLuint       GL_APIENTRY glCreateProgram (void);
+GL_APICALL GLuint       GL_APIENTRY glCreateShader (GLenum type);
+GL_APICALL void         GL_APIENTRY glCullFace (GLenum mode);
+GL_APICALL void         GL_APIENTRY glDeleteBuffers (GLsizei n, const GLuint* buffers);
+GL_APICALL void         GL_APIENTRY glDeleteFramebuffers (GLsizei n, const GLuint* framebuffers);
+GL_APICALL void         GL_APIENTRY glDeleteProgram (GLuint program);
+GL_APICALL void         GL_APIENTRY glDeleteRenderbuffers (GLsizei n, const GLuint* renderbuffers);
+GL_APICALL void         GL_APIENTRY glDeleteShader (GLuint shader);
+GL_APICALL void         GL_APIENTRY glDeleteTextures (GLsizei n, const GLuint* textures);
+GL_APICALL void         GL_APIENTRY glDepthFunc (GLenum func);
+GL_APICALL void         GL_APIENTRY glDepthMask (GLboolean flag);
+GL_APICALL void         GL_APIENTRY glDepthRangef (GLclampf zNear, GLclampf zFar);
+GL_APICALL void         GL_APIENTRY glDetachShader (GLuint program, GLuint shader);
+GL_APICALL void         GL_APIENTRY glDisable (GLenum cap);
+GL_APICALL void         GL_APIENTRY glDisableVertexAttribArray (GLuint index);
+GL_APICALL void         GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count);
+GL_APICALL void         GL_APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const void* indices);
+GL_APICALL void         GL_APIENTRY glEnable (GLenum cap);
+GL_APICALL void         GL_APIENTRY glEnableVertexAttribArray (GLuint index);
+GL_APICALL void         GL_APIENTRY glFinish (void);
+GL_APICALL void         GL_APIENTRY glFlush (void);
+GL_APICALL void         GL_APIENTRY glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+GL_APICALL void         GL_APIENTRY glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+GL_APICALL void         GL_APIENTRY glFrontFace (GLenum mode);
+GL_APICALL void         GL_APIENTRY glGenBuffers (GLsizei n, GLuint* buffers);
+GL_APICALL void         GL_APIENTRY glGenerateMipmap (GLenum target);
+GL_APICALL void         GL_APIENTRY glGenFramebuffers (GLsizei n, GLuint* framebuffers);
+GL_APICALL void         GL_APIENTRY glGenRenderbuffers (GLsizei n, GLuint* renderbuffers);
+GL_APICALL void         GL_APIENTRY glGenTextures (GLsizei n, GLuint* textures);
+GL_APICALL void         GL_APIENTRY glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name);
+GL_APICALL void         GL_APIENTRY glGetActiveUniform (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name);
+GL_APICALL void         GL_APIENTRY glGetAttachedShaders (GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders);
+GL_APICALL int          GL_APIENTRY glGetAttribLocation (GLuint program, const char* name);
+GL_APICALL void         GL_APIENTRY glGetBooleanv (GLenum pname, GLboolean* params);
+GL_APICALL void         GL_APIENTRY glGetBufferParameteriv (GLenum target, GLenum pname, GLint* params);
+GL_APICALL GLenum       GL_APIENTRY glGetError (void);
+GL_APICALL void         GL_APIENTRY glGetFloatv (GLenum pname, GLfloat* params);
+GL_APICALL void         GL_APIENTRY glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint* params);
+GL_APICALL void         GL_APIENTRY glGetIntegerv (GLenum pname, GLint* params);
+GL_APICALL void         GL_APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint* params);
+GL_APICALL void         GL_APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufsize, GLsizei* length, char* infolog);
+GL_APICALL void         GL_APIENTRY glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint* params);
+GL_APICALL void         GL_APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint* params);
+GL_APICALL void         GL_APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog);
+GL_APICALL void         GL_APIENTRY glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision);
+GL_APICALL void         GL_APIENTRY glGetShaderSource (GLuint shader, GLsizei bufsize, GLsizei* length, char* source);
+GL_APICALL const GLubyte* GL_APIENTRY glGetString (GLenum name);
+GL_APICALL void         GL_APIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat* params);
+GL_APICALL void         GL_APIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint* params);
+GL_APICALL void         GL_APIENTRY glGetUniformfv (GLuint program, GLint location, GLfloat* params);
+GL_APICALL void         GL_APIENTRY glGetUniformiv (GLuint program, GLint location, GLint* params);
+GL_APICALL int          GL_APIENTRY glGetUniformLocation (GLuint program, const char* name);
+GL_APICALL void         GL_APIENTRY glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat* params);
+GL_APICALL void         GL_APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint* params);
+GL_APICALL void         GL_APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, void** pointer);
+GL_APICALL void         GL_APIENTRY glHint (GLenum target, GLenum mode);
+GL_APICALL GLboolean    GL_APIENTRY glIsBuffer (GLuint buffer);
+GL_APICALL GLboolean    GL_APIENTRY glIsEnabled (GLenum cap);
+GL_APICALL GLboolean    GL_APIENTRY glIsFramebuffer (GLuint framebuffer);
+GL_APICALL GLboolean    GL_APIENTRY glIsProgram (GLuint program);
+GL_APICALL GLboolean    GL_APIENTRY glIsRenderbuffer (GLuint renderbuffer);
+GL_APICALL GLboolean    GL_APIENTRY glIsShader (GLuint shader);
+GL_APICALL GLboolean    GL_APIENTRY glIsTexture (GLuint texture);
+GL_APICALL void         GL_APIENTRY glLineWidth (GLfloat width);
+GL_APICALL void         GL_APIENTRY glLinkProgram (GLuint program);
+GL_APICALL void         GL_APIENTRY glPixelStorei (GLenum pname, GLint param);
+GL_APICALL void         GL_APIENTRY glPolygonOffset (GLfloat factor, GLfloat units);
+GL_APICALL void         GL_APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels);
+GL_APICALL void         GL_APIENTRY glReleaseShaderCompiler (void);
+GL_APICALL void         GL_APIENTRY glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void         GL_APIENTRY glSampleCoverage (GLclampf value, GLboolean invert);
+GL_APICALL void         GL_APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL void         GL_APIENTRY glShaderBinary (GLsizei n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLsizei length);
+GL_APICALL void         GL_APIENTRY glShaderSource (GLuint shader, GLsizei count, const char** string, const GLint* length);
+GL_APICALL void         GL_APIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask);
+GL_APICALL void         GL_APIENTRY glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask);
+GL_APICALL void         GL_APIENTRY glStencilMask (GLuint mask);
+GL_APICALL void         GL_APIENTRY glStencilMaskSeparate (GLenum face, GLuint mask);
+GL_APICALL void         GL_APIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass);
+GL_APICALL void         GL_APIENTRY glStencilOpSeparate (GLenum face, GLenum fail, GLenum zfail, GLenum zpass);
+GL_APICALL void         GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat,  GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels);
+GL_APICALL void         GL_APIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param);
+GL_APICALL void         GL_APIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat* params);
+GL_APICALL void         GL_APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param);
+GL_APICALL void         GL_APIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint* params);
+GL_APICALL void         GL_APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels);
+GL_APICALL void         GL_APIENTRY glUniform1f (GLint location, GLfloat x);
+GL_APICALL void         GL_APIENTRY glUniform1fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void         GL_APIENTRY glUniform1i (GLint location, GLint x);
+GL_APICALL void         GL_APIENTRY glUniform1iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void         GL_APIENTRY glUniform2f (GLint location, GLfloat x, GLfloat y);
+GL_APICALL void         GL_APIENTRY glUniform2fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void         GL_APIENTRY glUniform2i (GLint location, GLint x, GLint y);
+GL_APICALL void         GL_APIENTRY glUniform2iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void         GL_APIENTRY glUniform3f (GLint location, GLfloat x, GLfloat y, GLfloat z);
+GL_APICALL void         GL_APIENTRY glUniform3fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void         GL_APIENTRY glUniform3i (GLint location, GLint x, GLint y, GLint z);
+GL_APICALL void         GL_APIENTRY glUniform3iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void         GL_APIENTRY glUniform4f (GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GL_APICALL void         GL_APIENTRY glUniform4fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void         GL_APIENTRY glUniform4i (GLint location, GLint x, GLint y, GLint z, GLint w);
+GL_APICALL void         GL_APIENTRY glUniform4iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void         GL_APIENTRY glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void         GL_APIENTRY glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void         GL_APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void         GL_APIENTRY glUseProgram (GLuint program);
+GL_APICALL void         GL_APIENTRY glValidateProgram (GLuint program);
+GL_APICALL void         GL_APIENTRY glVertexAttrib1f (GLuint indx, GLfloat x);
+GL_APICALL void         GL_APIENTRY glVertexAttrib1fv (GLuint indx, const GLfloat* values);
+GL_APICALL void         GL_APIENTRY glVertexAttrib2f (GLuint indx, GLfloat x, GLfloat y);
+GL_APICALL void         GL_APIENTRY glVertexAttrib2fv (GLuint indx, const GLfloat* values);
+GL_APICALL void         GL_APIENTRY glVertexAttrib3f (GLuint indx, GLfloat x, GLfloat y, GLfloat z);
+GL_APICALL void         GL_APIENTRY glVertexAttrib3fv (GLuint indx, const GLfloat* values);
+GL_APICALL void         GL_APIENTRY glVertexAttrib4f (GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GL_APICALL void         GL_APIENTRY glVertexAttrib4fv (GLuint indx, const GLfloat* values);
+GL_APICALL void         GL_APIENTRY glVertexAttribPointer (GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr);
+GL_APICALL void         GL_APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gl2_h_ */
diff --git a/opengl/include/GLES2/gl2ext.h b/opengl/include/GLES2/gl2ext.h
new file mode 100644
index 0000000..72f1ae7
--- /dev/null
+++ b/opengl/include/GLES2/gl2ext.h
@@ -0,0 +1,518 @@
+#ifndef __gl2ext_h_
+#define __gl2ext_h_
+
+/* $Revision: 8271 $ on $Date:: 2009-05-21 09:33:40 -0700 #$ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This document is licensed under the SGI Free Software B License Version
+ * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ .
+ */
+
+#ifndef GL_APIENTRYP
+#   define GL_APIENTRYP GL_APIENTRY*
+#endif
+
+/*------------------------------------------------------------------------*
+ * OES extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_OES_compressed_ETC1_RGB8_texture */
+#ifndef GL_OES_compressed_ETC1_RGB8_texture
+#define GL_ETC1_RGB8_OES                                        0x8D64
+#endif
+
+/* GL_OES_compressed_paletted_texture */
+#ifndef GL_OES_compressed_paletted_texture
+#define GL_PALETTE4_RGB8_OES                                    0x8B90
+#define GL_PALETTE4_RGBA8_OES                                   0x8B91
+#define GL_PALETTE4_R5_G6_B5_OES                                0x8B92
+#define GL_PALETTE4_RGBA4_OES                                   0x8B93
+#define GL_PALETTE4_RGB5_A1_OES                                 0x8B94
+#define GL_PALETTE8_RGB8_OES                                    0x8B95
+#define GL_PALETTE8_RGBA8_OES                                   0x8B96
+#define GL_PALETTE8_R5_G6_B5_OES                                0x8B97
+#define GL_PALETTE8_RGBA4_OES                                   0x8B98
+#define GL_PALETTE8_RGB5_A1_OES                                 0x8B99
+#endif
+
+/* GL_OES_depth24 */
+#ifndef GL_OES_depth24
+#define GL_DEPTH_COMPONENT24_OES                                0x81A6
+#endif
+
+/* GL_OES_depth32 */
+#ifndef GL_OES_depth32
+#define GL_DEPTH_COMPONENT32_OES                                0x81A7
+#endif
+
+/* GL_OES_depth_texture */
+/* No new tokens introduced by this extension. */
+
+/* GL_OES_EGL_image */
+#ifndef GL_OES_EGL_image
+typedef void* GLeglImageOES;
+#endif
+
+/* GL_OES_get_program_binary */
+#ifndef GL_OES_get_program_binary
+#define GL_PROGRAM_BINARY_LENGTH_OES                            0x8741
+#define GL_NUM_PROGRAM_BINARY_FORMATS_OES                       0x87FE
+#define GL_PROGRAM_BINARY_FORMATS_OES                           0x87FF
+#endif
+
+/* GL_OES_mapbuffer */
+#ifndef GL_OES_mapbuffer
+#define GL_WRITE_ONLY_OES                                       0x88B9
+#define GL_BUFFER_ACCESS_OES                                    0x88BB
+#define GL_BUFFER_MAPPED_OES                                    0x88BC
+#define GL_BUFFER_MAP_POINTER_OES                               0x88BD
+#endif
+
+/* GL_OES_packed_depth_stencil */
+#ifndef GL_OES_packed_depth_stencil
+#define GL_DEPTH_STENCIL_OES                                    0x84F9
+#define GL_UNSIGNED_INT_24_8_OES                                0x84FA
+#define GL_DEPTH24_STENCIL8_OES                                 0x88F0
+#endif
+
+/* GL_OES_rgb8_rgba8 */
+#ifndef GL_OES_rgb8_rgba8
+#define GL_RGB8_OES                                             0x8051
+#define GL_RGBA8_OES                                            0x8058
+#endif
+
+/* GL_OES_standard_derivatives */
+#ifndef GL_OES_standard_derivatives
+#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES                  0x8B8B
+#endif
+
+/* GL_OES_stencil1 */
+#ifndef GL_OES_stencil1
+#define GL_STENCIL_INDEX1_OES                                   0x8D46
+#endif
+
+/* GL_OES_stencil4 */
+#ifndef GL_OES_stencil4
+#define GL_STENCIL_INDEX4_OES                                   0x8D47
+#endif
+
+/* GL_OES_texture3D */
+#ifndef GL_OES_texture3D
+#define GL_TEXTURE_WRAP_R_OES                                   0x8072
+#define GL_TEXTURE_3D_OES                                       0x806F
+#define GL_TEXTURE_BINDING_3D_OES                               0x806A
+#define GL_MAX_3D_TEXTURE_SIZE_OES                              0x8073
+#define GL_SAMPLER_3D_OES                                       0x8B5F
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_OES        0x8CD4
+#endif
+
+/* GL_OES_texture_half_float */
+#ifndef GL_OES_texture_half_float
+#define GL_HALF_FLOAT_OES                                       0x8D61
+#endif
+
+/* GL_OES_vertex_half_float */
+/* GL_HALF_FLOAT_OES defined in GL_OES_texture_half_float already. */
+
+/* GL_OES_vertex_type_10_10_10_2 */
+#ifndef GL_OES_vertex_type_10_10_10_2
+#define GL_UNSIGNED_INT_10_10_10_2_OES                          0x8DF6
+#define GL_INT_10_10_10_2_OES                                   0x8DF7
+#endif
+
+/*------------------------------------------------------------------------*
+ * AMD extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_AMD_compressed_3DC_texture */
+#ifndef GL_AMD_compressed_3DC_texture
+#define GL_3DC_X_AMD                                            0x87F9
+#define GL_3DC_XY_AMD                                           0x87FA
+#endif
+
+/* GL_AMD_compressed_ATC_texture */
+#ifndef GL_AMD_compressed_ATC_texture
+#define GL_ATC_RGB_AMD                                          0x8C92
+#define GL_ATC_RGBA_EXPLICIT_ALPHA_AMD                          0x8C93
+#define GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD                      0x87EE
+#endif
+
+/* GL_AMD_program_binary_Z400 */
+#ifndef GL_AMD_program_binary_Z400
+#define GL_Z400_BINARY_AMD                                      0x8740
+#endif
+
+/* GL_AMD_performance_monitor */
+#ifndef GL_AMD_performance_monitor
+#define GL_COUNTER_TYPE_AMD                                     0x8BC0
+#define GL_COUNTER_RANGE_AMD                                    0x8BC1
+#define GL_UNSIGNED_INT64_AMD                                   0x8BC2
+#define GL_PERCENTAGE_AMD                                       0x8BC3
+#define GL_PERFMON_RESULT_AVAILABLE_AMD                         0x8BC4
+#define GL_PERFMON_RESULT_SIZE_AMD                              0x8BC5
+#define GL_PERFMON_RESULT_AMD                                   0x8BC6
+#endif
+
+/*------------------------------------------------------------------------*
+ * EXT extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_EXT_texture_filter_anisotropic */
+#ifndef GL_EXT_texture_filter_anisotropic
+#define GL_TEXTURE_MAX_ANISOTROPY_EXT                           0x84FE
+#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT                       0x84FF
+#endif
+
+/* GL_EXT_texture_type_2_10_10_10_REV */
+#ifndef GL_EXT_texture_type_2_10_10_10_REV
+#define GL_UNSIGNED_INT_2_10_10_10_REV_EXT                      0x8368
+#endif
+
+/* GL_EXT_texture_format_BGRA8888 */
+#ifndef GL_EXT_texture_format_BGRA8888
+#define GL_BGRA                                                 0x80E1
+#endif
+
+/*------------------------------------------------------------------------*
+ * IMG extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_IMG_read_format */
+#ifndef GL_IMG_read_format
+#define GL_BGRA                                                 0x80E1
+#define GL_UNSIGNED_SHORT_4_4_4_4_REV                           0x8365
+#define GL_UNSIGNED_SHORT_1_5_5_5_REV                           0x8366
+#endif
+
+/* GL_IMG_texture_compression_pvrtc */
+#ifndef GL_IMG_texture_compression_pvrtc
+#define GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG                      0x8C00
+#define GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG                      0x8C01
+#define GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG                     0x8C02
+#define GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG                     0x8C03
+#endif
+
+/*------------------------------------------------------------------------*
+ * NV extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_NV_fence */
+#ifndef GL_NV_fence
+#define GL_ALL_COMPLETED_NV                                     0x84F2
+#define GL_FENCE_STATUS_NV                                      0x84F3
+#define GL_FENCE_CONDITION_NV                                   0x84F4
+#endif
+
+/*------------------------------------------------------------------------*
+ * QCOM extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_QCOM_driver_control */
+/* No new tokens introduced by this extension. */
+
+/* GL_QCOM_perfmon_global_mode */
+#ifndef GL_QCOM_perfmon_global_mode
+#define GL_PERFMON_GLOBAL_MODE_QCOM                             0x8FA0
+#endif
+
+/*------------------------------------------------------------------------*
+ * End of extension tokens, start of corresponding extension functions
+ *------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------*
+ * OES extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_OES_compressed_ETC1_RGB8_texture */
+#ifndef GL_OES_compressed_ETC1_RGB8_texture
+#define GL_OES_compressed_ETC1_RGB8_texture 1
+#endif
+
+/* GL_OES_compressed_paletted_texture */
+#ifndef GL_OES_compressed_paletted_texture
+#define GL_OES_compressed_paletted_texture 1
+#endif
+
+/* GL_OES_EGL_image */
+#ifndef GL_OES_EGL_image
+#define GL_OES_EGL_image 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glEGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image);
+GL_APICALL void GL_APIENTRY glEGLImageTargetRenderbufferStorageOES (GLenum target, GLeglImageOES image);
+#endif
+typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image);
+typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image);
+#endif
+
+/* GL_OES_depth24 */
+#ifndef GL_OES_depth24
+#define GL_OES_depth24 1
+#endif
+
+/* GL_OES_depth32 */
+#ifndef GL_OES_depth32
+#define GL_OES_depth32 1
+#endif
+
+/* GL_OES_depth_texture */
+#ifndef GL_OES_depth_texture
+#define GL_OES_depth_texture 1
+#endif
+
+/* GL_OES_element_index_uint */
+#ifndef GL_OES_element_index_uint
+#define GL_OES_element_index_uint 1
+#endif
+
+/* GL_OES_fbo_render_mipmap */
+#ifndef GL_OES_fbo_render_mipmap
+#define GL_OES_fbo_render_mipmap 1
+#endif
+
+/* GL_OES_fragment_precision_high */
+#ifndef GL_OES_fragment_precision_high
+#define GL_OES_fragment_precision_high 1
+#endif
+
+/* GL_OES_get_program_binary */
+#ifndef GL_OES_get_program_binary
+#define GL_OES_get_program_binary 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glGetProgramBinaryOES (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary);
+GL_APICALL void GL_APIENTRY glProgramBinaryOES (GLuint program, GLenum binaryFormat, const void *binary, GLint length);
+#endif
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMBINARYOESPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary);
+typedef void (GL_APIENTRYP PFNGLPROGRAMBINARYOESPROC) (GLuint program, GLenum binaryFormat, const void *binary, GLint length);
+#endif
+
+/* GL_OES_mapbuffer */
+#ifndef GL_OES_mapbuffer
+#define GL_OES_mapbuffer 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void* GL_APIENTRY glMapBufferOES (GLenum target, GLenum access);
+GL_APICALL GLboolean GL_APIENTRY glUnmapBufferOES (GLenum target);
+GL_APICALL void GL_APIENTRY glGetBufferPointervOES (GLenum target, GLenum pname, void** params);
+#endif
+typedef void* (GL_APIENTRYP PFNGLMAPBUFFEROESPROC) (GLenum target, GLenum access);
+typedef GLboolean (GL_APIENTRYP PFNGLUNMAPBUFFEROESPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLGETBUFFERPOINTERVOESPROC) (GLenum target, GLenum pname, void** params);
+#endif
+
+/* GL_OES_packed_depth_stencil */
+#ifndef GL_OES_packed_depth_stencil
+#define GL_OES_packed_depth_stencil 1
+#endif
+
+/* GL_OES_rgb8_rgba8 */
+#ifndef GL_OES_rgb8_rgba8
+#define GL_OES_rgb8_rgba8 1
+#endif
+
+/* GL_OES_standard_derivatives */
+#ifndef GL_OES_standard_derivatives
+#define GL_OES_standard_derivatives 1
+#endif
+
+/* GL_OES_stencil1 */
+#ifndef GL_OES_stencil1
+#define GL_OES_stencil1 1
+#endif
+
+/* GL_OES_stencil4 */
+#ifndef GL_OES_stencil4
+#define GL_OES_stencil4 1
+#endif
+
+/* GL_OES_texture_3D */
+#ifndef GL_OES_texture_3D
+#define GL_OES_texture_3D 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glTexImage3DOES (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels);
+GL_APICALL void GL_APIENTRY glTexSubImage3DOES (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels);
+GL_APICALL void GL_APIENTRY glCopyTexSubImage3DOES (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glCompressedTexImage3DOES (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void* data);
+GL_APICALL void GL_APIENTRY glCompressedTexSubImage3DOES (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data);
+GL_APICALL void GL_APIENTRY glFramebufferTexture3DOES (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+#endif
+typedef void (GL_APIENTRYP PFNGLTEXIMAGE3DOESPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels);
+typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels);
+typedef void (GL_APIENTRYP PFNGLCOPYTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DOESPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void* data);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE3DOES) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+#endif
+
+/* GL_OES_texture_float_linear */
+#ifndef GL_OES_texture_float_linear
+#define GL_OES_texture_float_linear 1
+#endif
+
+/* GL_OES_texture_half_float_linear */
+#ifndef GL_OES_texture_half_float_linear
+#define GL_OES_texture_half_float_linear 1
+#endif
+
+/* GL_OES_texture_float */
+#ifndef GL_OES_texture_float
+#define GL_OES_texture_float 1
+#endif
+
+/* GL_OES_texture_half_float */
+#ifndef GL_OES_texture_half_float
+#define GL_OES_texture_half_float 1
+#endif
+
+/* GL_OES_texture_npot */
+#ifndef GL_OES_texture_npot
+#define GL_OES_texture_npot 1
+#endif
+
+/* GL_OES_vertex_half_float */
+#ifndef GL_OES_vertex_half_float
+#define GL_OES_vertex_half_float 1
+#endif
+
+/* GL_OES_vertex_type_10_10_10_2 */
+#ifndef GL_OES_vertex_type_10_10_10_2
+#define GL_OES_vertex_type_10_10_10_2 1
+#endif
+
+/*------------------------------------------------------------------------*
+ * AMD extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_AMD_compressed_3DC_texture */
+#ifndef GL_AMD_compressed_3DC_texture
+#define GL_AMD_compressed_3DC_texture 1
+#endif
+
+/* GL_AMD_compressed_ATC_texture */
+#ifndef GL_AMD_compressed_ATC_texture
+#define GL_AMD_compressed_ATC_texture 1
+#endif
+
+/* GL_AMD_program_binary_Z400 */
+#ifndef GL_AMD_program_binary_Z400
+#define GL_AMD_program_binary_Z400 1
+#endif
+
+/* AMD_performance_monitor */
+#ifndef GL_AMD_performance_monitor
+#define GL_AMD_performance_monitor 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glGetPerfMonitorGroupsAMD (GLint *numGroups, GLsizei groupsSize, GLuint *groups);
+GL_APICALL void GL_APIENTRY glGetPerfMonitorCountersAMD (GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters);
+GL_APICALL void GL_APIENTRY glGetPerfMonitorGroupStringAMD (GLuint group, GLsizei bufSize, GLsizei *length, char *groupString);
+GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterStringAMD (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, char *counterString);
+GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterInfoAMD (GLuint group, GLuint counter, GLenum pname, void *data);
+GL_APICALL void GL_APIENTRY glGenPerfMonitorsAMD (GLsizei n, GLuint *monitors);
+GL_APICALL void GL_APIENTRY glDeletePerfMonitorsAMD (GLsizei n, GLuint *monitors);
+GL_APICALL void GL_APIENTRY glSelectPerfMonitorCountersAMD (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *countersList);
+GL_APICALL void GL_APIENTRY glBeginPerfMonitorAMD (GLuint monitor);
+GL_APICALL void GL_APIENTRY glEndPerfMonitorAMD (GLuint monitor);
+GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterDataAMD (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten);
+#endif
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORGROUPSAMDPROC) (GLint *numGroups, GLsizei groupsSize, GLuint *groups);
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERSAMDPROC) (GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters);
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORGROUPSTRINGAMDPROC) (GLuint group, GLsizei bufSize, GLsizei *length, char *groupString);
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERSTRINGAMDPROC) (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, char *counterString);
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERINFOAMDPROC) (GLuint group, GLuint counter, GLenum pname, void *data);
+typedef void (GL_APIENTRYP PFNGLGENPERFMONITORSAMDPROC) (GLsizei n, GLuint *monitors);
+typedef void (GL_APIENTRYP PFNGLDELETEPERFMONITORSAMDPROC) (GLsizei n, GLuint *monitors);
+typedef void (GL_APIENTRYP PFNGLSELECTPERFMONITORCOUNTERSAMDPROC) (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *countersList);
+typedef void (GL_APIENTRYP PFNGLBEGINPERFMONITORAMDPROC) (GLuint monitor);
+typedef void (GL_APIENTRYP PFNGLENDPERFMONITORAMDPROC) (GLuint monitor);
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERDATAAMDPROC) (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten);
+#endif
+
+/*------------------------------------------------------------------------*
+ * EXT extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_EXT_texture_filter_anisotropic */
+#ifndef GL_EXT_texture_filter_anisotropic
+#define GL_EXT_texture_filter_anisotropic 1
+#endif
+
+/* GL_EXT_texture_type_2_10_10_10_REV */
+#ifndef GL_EXT_texture_type_2_10_10_10_REV
+#define GL_EXT_texture_type_2_10_10_10_REV 1
+#endif
+
+/* GL_EXT_texture_format_BGRA8888 */
+#ifndef GL_EXT_texture_format_BGRA8888
+#define GL_EXT_texture_format_BGRA8888 1
+#endif
+
+/*------------------------------------------------------------------------*
+ * IMG extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_IMG_read_format */
+#ifndef GL_IMG_read_format
+#define GL_IMG_read_format 1
+#endif
+
+/* GL_IMG_texture_compression_pvrtc */
+#ifndef GL_IMG_texture_compression_pvrtc
+#define GL_IMG_texture_compression_pvrtc 1
+#endif
+
+/*------------------------------------------------------------------------*
+ * NV extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_NV_fence */
+#ifndef GL_NV_fence
+#define GL_NV_fence 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDeleteFencesNV (GLsizei n, const GLuint *fences);
+GL_APICALL void GL_APIENTRY glGenFencesNV (GLsizei n, GLuint *fences);
+GL_APICALL GLboolean GL_APIENTRY glIsFenceNV (GLuint fence);
+GL_APICALL GLboolean GL_APIENTRY glTestFenceNV (GLuint fence);
+GL_APICALL void GL_APIENTRY glGetFenceivNV (GLuint fence, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glFinishFenceNV (GLuint fence);
+GL_APICALL void GL_APIENTRY glSetFenceNV (GLuint fence, GLenum condition);
+#endif
+typedef void (GL_APIENTRYP PFNGLDELETEFENCESNVPROC) (GLsizei n, const GLuint *fences);
+typedef void (GL_APIENTRYP PFNGLGENFENCESNVPROC) (GLsizei n, GLuint *fences);
+typedef GLboolean (GL_APIENTRYP PFNGLISFENCENVPROC) (GLuint fence);
+typedef GLboolean (GL_APIENTRYP PFNGLTESTFENCENVPROC) (GLuint fence);
+typedef void (GL_APIENTRYP PFNGLGETFENCEIVNVPROC) (GLuint fence, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLFINISHFENCENVPROC) (GLuint fence);
+typedef void (GL_APIENTRYP PFNGLSETFENCENVPROC) (GLuint fence, GLenum condition);
+#endif
+
+/*------------------------------------------------------------------------*
+ * QCOM extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_QCOM_driver_control */
+#ifndef GL_QCOM_driver_control
+#define GL_QCOM_driver_control 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glGetDriverControlsQCOM (GLint *num, GLsizei size, GLuint *driverControls);
+GL_APICALL void GL_APIENTRY glGetDriverControlStringQCOM (GLuint driverControl, GLsizei bufSize, GLsizei *length, char *driverControlString);
+GL_APICALL void GL_APIENTRY glEnableDriverControlQCOM (GLuint driverControl);
+GL_APICALL void GL_APIENTRY glDisableDriverControlQCOM (GLuint driverControl);
+#endif
+typedef void (GL_APIENTRYP PFNGLGETDRIVERCONTROLSQCOMPROC) (GLint *num, GLsizei size, GLuint *driverControls);
+typedef void (GL_APIENTRYP PFNGLGETDRIVERCONTROLSTRINGQCOMPROC) (GLuint driverControl, GLsizei bufSize, GLsizei *length, char *driverControlString);
+typedef void (GL_APIENTRYP PFNGLENABLEDRIVERCONTROLQCOMPROC) (GLuint driverControl);
+typedef void (GL_APIENTRYP PFNGLDISABLEDRIVERCONTROLQCOMPROC) (GLuint driverControl);
+#endif
+
+/* GL_QCOM_perfmon_global_mode */
+#ifndef GL_QCOM_perfmon_global_mode
+#define GL_QCOM_perfmon_global_mode 1
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gl2ext_h_ */
diff --git a/opengl/include/GLES2/gl2platform.h b/opengl/include/GLES2/gl2platform.h
new file mode 100644
index 0000000..3e9036c
--- /dev/null
+++ b/opengl/include/GLES2/gl2platform.h
@@ -0,0 +1,29 @@
+#ifndef __gl2platform_h_
+#define __gl2platform_h_
+
+/* $Revision: 7173 $ on $Date:: 2009-01-09 11:18:21 -0800 #$ */
+
+/*
+ * This document is licensed under the SGI Free Software B License Version
+ * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ .
+ */
+
+/* Platform-specific types and definitions for OpenGL ES 2.X  gl2.h
+ * Last modified on 2008/12/19
+ *
+ * Adopters may modify khrplatform.h and this file to suit their platform.
+ * You are encouraged to submit all modifications to the Khronos group so that
+ * they can be included in future versions of this file.  Please submit changes
+ * by sending them to the public Khronos Bugzilla (http://khronos.org/bugzilla)
+ * by filing a bug against product "OpenGL-ES" component "Registry".
+ */
+
+#include <KHR/khrplatform.h>
+
+#ifndef GL_APICALL
+#define GL_APICALL  KHRONOS_APICALL
+#endif
+
+#define GL_APIENTRY KHRONOS_APIENTRY
+
+#endif /* __gl2platform_h_ */
diff --git a/opengl/libagl/Android.mk b/opengl/libagl/Android.mk
index 3ce0414..9837845 100644
--- a/opengl/libagl/Android.mk
+++ b/opengl/libagl/Android.mk
@@ -6,6 +6,9 @@
 
 include $(CLEAR_VARS)
 
+# Set to 1 to use gralloc and copybits
+LIBAGL_USE_GRALLOC_COPYBITS := 1
+
 LOCAL_SRC_FILES:= \
 	egl.cpp                     \
 	state.cpp		            \
@@ -22,6 +25,13 @@
 	primitives.cpp.arm	        \
 	vertex.cpp.arm
 
+LOCAL_CFLAGS += -DLOG_TAG=\"libagl\"
+LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
+LOCAL_CFLAGS += -fvisibility=hidden
+
+LOCAL_SHARED_LIBRARIES := libcutils libhardware libutils libpixelflinger
+LOCAL_LDLIBS := -lpthread -ldl
+
 ifeq ($(TARGET_ARCH),arm)
 	LOCAL_SRC_FILES += fixed_asm.S iterators.S
 	LOCAL_CFLAGS += -fstrict-aliasing
@@ -29,13 +39,17 @@
 
 ifneq ($(TARGET_SIMULATOR),true)
     # we need to access the private Bionic header <bionic_tls.h>
-    LOCAL_CFLAGS += -I$(LOCAL_PATH)/../../../../bionic/libc/private
+    LOCAL_C_INCLUDES += bionic/libc/private
 endif
 
-LOCAL_SHARED_LIBRARIES := libcutils libutils libpixelflinger
-LOCAL_CFLAGS += -fvisibility=hidden
+ifeq ($(LIBAGL_USE_GRALLOC_COPYBITS),1)
+    LOCAL_CFLAGS += -DLIBAGL_USE_GRALLOC_COPYBITS
+    LOCAL_SRC_FILES += copybit.cpp
+    LOCAL_SHARED_LIBRARIES += libui
+endif
 
-LOCAL_LDLIBS := -lpthread -ldl
-LOCAL_MODULE:= libagl
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/egl
+LOCAL_MODULE:= libGLES_android
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/opengl/libagl/TextureObjectManager.cpp b/opengl/libagl/TextureObjectManager.cpp
index ce31854..255ccac 100644
--- a/opengl/libagl/TextureObjectManager.cpp
+++ b/opengl/libagl/TextureObjectManager.cpp
@@ -1,16 +1,16 @@
 /*
  ** Copyright 2006, 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 
+ ** 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 
+ **     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 
+ ** 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.
  */
 
@@ -19,11 +19,13 @@
 #include "context.h"
 #include "TextureObjectManager.h"
 
+#include <private/ui/android_natives_priv.h>
+
 namespace android {
 // ----------------------------------------------------------------------------
 
 EGLTextureObject::EGLTextureObject()
-    : mCount(0), mSize(0)
+    : mSize(0)
 {
     init();
 }
@@ -53,6 +55,10 @@
     memset(crop_rect, 0, sizeof(crop_rect));
     generate_mipmap = GL_FALSE;
     direct = GL_FALSE;
+#ifdef LIBAGL_USE_GRALLOC_COPYBITS
+    try_copybit = false;
+#endif // LIBAGL_USE_GRALLOC_COPYBITS
+    buffer = 0;
 }
 
 void EGLTextureObject::copyParameters(const sp<EGLTextureObject>& old)
@@ -123,6 +129,7 @@
     }
     surface = *s;
     internalformat = 0;
+    buffer = 0;
 
     // we should keep the crop_rect, but it's delicate because
     // the new size of the surface could make it invalid.
@@ -141,12 +148,26 @@
     return NO_ERROR;
 }
 
+status_t EGLTextureObject::setImage(android_native_buffer_t* native_buffer)
+{
+    GGLSurface sur;
+    sur.version = sizeof(GGLSurface);
+    sur.width = native_buffer->width;
+    sur.height= native_buffer->height;
+    sur.stride= native_buffer->stride;
+    sur.format= native_buffer->format;
+    sur.data  = 0;
+    setSurface(&sur);
+    buffer = native_buffer;
+    return NO_ERROR;
+}
+
 status_t EGLTextureObject::reallocate(
         GLint level, int w, int h, int s,
         int format, int compressedFormat, int bpr)
 {
     const size_t size = h * bpr;
-    if (level == 0) 
+    if (level == 0)
     {
         if (size!=mSize || !surface.data) {
             if (mSize && surface.data) {
@@ -177,9 +198,9 @@
                 return NO_MEMORY;
         }
 
-        LOGW_IF(level-1 >= mNumExtraLod, 
+        LOGW_IF(level-1 >= mNumExtraLod,
                 "specifying mipmap level %d, but # of level is %d",
-                level, mNumExtraLod+1);        
+                level, mNumExtraLod+1);
 
         GGLSurface& mipmap = editMip(level);
         if (mipmap.data)
@@ -224,7 +245,7 @@
 // ----------------------------------------------------------------------------
 
 EGLSurfaceManager::EGLSurfaceManager()
-    : TokenManager(), mCount(0)
+    : TokenManager()
 {
 }
 
diff --git a/opengl/libagl/TextureObjectManager.h b/opengl/libagl/TextureObjectManager.h
index 74ed1a4..279e040 100644
--- a/opengl/libagl/TextureObjectManager.h
+++ b/opengl/libagl/TextureObjectManager.h
@@ -1,16 +1,16 @@
 /*
 ** Copyright 2006, 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 
+** 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 
+**     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 
+** 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.
 */
 
@@ -30,6 +30,8 @@
 #include <private/pixelflinger/ggl_context.h>
 
 #include <GLES/gl.h>
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
 
 #include "Tokenizer.h"
 #include "TokenManager.h"
@@ -39,22 +41,20 @@
 
 // ----------------------------------------------------------------------------
 
-class EGLTextureObject
+class EGLTextureObject : public LightRefBase<EGLTextureObject>
 {
 public:
                     EGLTextureObject();
                    ~EGLTextureObject();
 
-    // protocol for sp<>
-    inline  void        incStrong(const void* id) const;
-    inline  void        decStrong(const void* id) const;
-    inline  uint32_t    getStrongCount() const;
+    status_t    setSurface(GGLSurface const* s);
+    status_t    setImage(android_native_buffer_t* buffer);
+    void        setImageBits(void* vaddr) { surface.data = (GGLubyte*)vaddr; }
 
-    status_t            setSurface(GGLSurface const* s);
     status_t            reallocate(GLint level,
                             int w, int h, int s,
                             int format, int compressedFormat, int bpr);
-    inline  size_t      size() const;
+    inline  size_t      size() const { return mSize; }
     const GGLSurface&   mip(int lod) const;
     GGLSurface&         editMip(int lod);
     bool                hasMipmaps() const { return mMipmaps!=0; }
@@ -65,7 +65,6 @@
         status_t        allocateMipmaps();
             void        freeMipmaps();
             void        init();
-    mutable int32_t     mCount;
     size_t              mSize;
     GGLSurface          *mMipmaps;
     int                 mNumExtraLod;
@@ -81,36 +80,22 @@
     GLint               crop_rect[4];
     GLint               generate_mipmap;
     GLint               direct;
+#ifdef LIBAGL_USE_GRALLOC_COPYBITS
+    bool                try_copybit;
+#endif // LIBAGL_USE_GRALLOC_COPYBITS
+    android_native_buffer_t* buffer;
 };
 
-void EGLTextureObject::incStrong(const void* id) const {
-    android_atomic_inc(&mCount);
-}
-void EGLTextureObject::decStrong(const void* id) const {
-    if (android_atomic_dec(&mCount) == 1) {
-        delete this;
-    }
-}
-uint32_t EGLTextureObject::getStrongCount() const {
-    return mCount;
-}
-size_t EGLTextureObject::size() const {
-    return mSize;
-}
-
 // ----------------------------------------------------------------------------
 
-class EGLSurfaceManager : public TokenManager
+class EGLSurfaceManager :
+    public LightRefBase<EGLSurfaceManager>,
+    public TokenManager
 {
 public:
                 EGLSurfaceManager();
                 ~EGLSurfaceManager();
 
-    // protocol for sp<>
-    inline  void    incStrong(const void* id) const;
-    inline  void    decStrong(const void* id) const;
-    typedef void    weakref_type;
-
     sp<EGLTextureObject>    createTexture(GLuint name);
     sp<EGLTextureObject>    removeTexture(GLuint name);
     sp<EGLTextureObject>    replaceTexture(GLuint name);
@@ -118,21 +103,10 @@
     sp<EGLTextureObject>    texture(GLuint name);
 
 private:
-    mutable int32_t                             mCount;
     mutable Mutex                               mLock;
     KeyedVector< GLuint, sp<EGLTextureObject> > mTextures;
 };
 
-void EGLSurfaceManager::incStrong(const void* id) const {
-    android_atomic_inc(&mCount);
-}
-void EGLSurfaceManager::decStrong(const void* id) const {
-    if (android_atomic_dec(&mCount) == 1) {
-        delete this;
-    }
-}
-
-
 // ----------------------------------------------------------------------------
 }; // namespace android
 
diff --git a/opengl/libagl/array.cpp b/opengl/libagl/array.cpp
index 3e9c6a5..4878722 100644
--- a/opengl/libagl/array.cpp
+++ b/opengl/libagl/array.cpp
@@ -1,16 +1,16 @@
-/* 
+/*
 ** Copyright 2006, 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 
+** 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 
+**     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 
+** 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.
 */
 
@@ -26,6 +26,9 @@
 #include "primitives.h"
 #include "texture.h"
 #include "BufferObjectManager.h"
+#ifdef LIBAGL_USE_GRALLOC_COPYBITS
+#include "copybit.h"
+#endif // LIBAGL_USE_GRALLOC_COPYBITS
 
 // ----------------------------------------------------------------------------
 
@@ -250,7 +253,7 @@
     v[2] = GGL_S_TO_X(p[2]);
 }
 
-typedef array_t::fetcher_t fn_t; 
+typedef array_t::fetcher_t fn_t;
 
 static const fn_t color_fct[2][16] = { // size={3,4}, type={ub,f,x}
     { 0, (fn_t)fetchExpand3ub, 0, 0, 0, 0,
@@ -334,7 +337,7 @@
     this->bounds = count;
 }
 
-inline void array_t::resolve() 
+inline void array_t::resolve()
 {
     physical_pointer = (bo) ? (bo->data + uintptr_t(pointer)) : pointer;
 }
@@ -465,7 +468,7 @@
         // We compute directly the index of a "free" entry from the locked
         // state of v[2] and v[3].
         v = c->vc.vBuffer + 2;
-        v += v[0].locked | (v[1].locked<<1);       
+        v += v[0].locked | (v[1].locked<<1);
     }
     // note: compileElement clears v->flags
     c->arrays.compileElement(c, v, index);
@@ -480,7 +483,7 @@
 
 #if VC_CACHE_TYPE == VC_CACHE_TYPE_INDEXED
 
-    vertex_t* const v = c->vc.vCache + 
+    vertex_t* const v = c->vc.vCache +
             (index & (vertex_cache_t::VERTEX_CACHE_SIZE-1));
 
     if (ggl_likely(v->index == index)) {
@@ -491,7 +494,7 @@
 
 #elif VC_CACHE_TYPE == VC_CACHE_TYPE_LRU
 
-    vertex_t* v = c->vc.vCache + 
+    vertex_t* v = c->vc.vCache +
             (index & ((vertex_cache_t::VERTEX_CACHE_SIZE-1)>>1))*2;
 
     // always record LRU in v[0]
@@ -532,12 +535,12 @@
         return;
 
     // vertex cache size must be multiple of 1
-    const GLsizei vcs = 
+    const GLsizei vcs =
             (vertex_cache_t::VERTEX_BUFFER_SIZE +
              vertex_cache_t::VERTEX_CACHE_SIZE);
     do {
         vertex_t* v = c->vc.vBuffer;
-        GLsizei num = count > vcs ? vcs : count; 
+        GLsizei num = count > vcs ? vcs : count;
         c->arrays.cull = vertex_t::CLIP_ALL;
         c->arrays.compileElements(c, v, first, num);
         first += num;
@@ -569,13 +572,13 @@
     count -= 1;
 
     // vertex cache size must be multiple of 1
-    const GLsizei vcs = 
+    const GLsizei vcs =
         (vertex_cache_t::VERTEX_BUFFER_SIZE +
          vertex_cache_t::VERTEX_CACHE_SIZE - 1);
     do {
-        v0 = c->vc.vBuffer + 0; 
+        v0 = c->vc.vBuffer + 0;
         v  = c->vc.vBuffer + 1;
-        GLsizei num = count > vcs ? vcs : count; 
+        GLsizei num = count > vcs ? vcs : count;
         c->arrays.compileElements(c, v, first, num);
         first += num;
         count -= num;
@@ -602,7 +605,7 @@
         return;
     drawPrimitivesLineStrip(c, first, count);
     if (ggl_likely(count >= 3)) {
-        vertex_t* v0 = c->vc.vBuffer; 
+        vertex_t* v0 = c->vc.vBuffer;
         vertex_t* v1 = c->vc.vBuffer + 1;
         c->arrays.compileElement(c, v1, first);
         const uint32_t cc = v0->flags & v1->flags;
@@ -617,12 +620,12 @@
         return;
 
     // vertex cache size must be multiple of 2
-    const GLsizei vcs = 
+    const GLsizei vcs =
         ((vertex_cache_t::VERTEX_BUFFER_SIZE +
         vertex_cache_t::VERTEX_CACHE_SIZE) / 2) * 2;
     do {
         vertex_t* v = c->vc.vBuffer;
-        GLsizei num = count > vcs ? vcs : count; 
+        GLsizei num = count > vcs ? vcs : count;
         c->arrays.cull = vertex_t::CLIP_ALL;
         c->arrays.compileElements(c, v, first, num);
         first += num;
@@ -662,14 +665,14 @@
     // because it allows us to preserve the same winding when the whole
     // batch is culled. We also need 2 extra vertices in the array, because
     // we always keep the two first ones.
-    const GLsizei vcs = 
+    const GLsizei vcs =
         ((vertex_cache_t::VERTEX_BUFFER_SIZE +
           vertex_cache_t::VERTEX_CACHE_SIZE - 2) / 2) * 2;
     do {
-        v0 = c->vc.vBuffer + 0; 
-        v1 = c->vc.vBuffer + 1; 
+        v0 = c->vc.vBuffer + 0;
+        v1 = c->vc.vBuffer + 1;
         v  = c->vc.vBuffer + 2;
-        GLsizei num = count > vcs ? vcs : count; 
+        GLsizei num = count > vcs ? vcs : count;
         c->arrays.compileElements(c, v, first, num);
         first += num;
         count -= num;
@@ -697,13 +700,19 @@
     } while (count > 0);
 }
 
-void drawPrimitivesTriangleStrip(ogles_context_t* c, 
+void drawPrimitivesTriangleStrip(ogles_context_t* c,
         GLint first, GLsizei count) {
     drawPrimitivesTriangleFanOrStrip(c, first, count, 1);
 }
 
 void drawPrimitivesTriangleFan(ogles_context_t* c,
         GLint first, GLsizei count) {
+#ifdef LIBAGL_USE_GRALLOC_COPYBITS
+    if (drawTriangleFanWithCopybit(c, first, count)) {
+        return;
+    }
+#endif // LIBAGL_USE_GRALLOC_COPYBITS
+
     drawPrimitivesTriangleFanOrStrip(c, first, count, 2);
 }
 
@@ -713,12 +722,12 @@
         return;
 
     // vertex cache size must be multiple of 3
-    const GLsizei vcs = 
+    const GLsizei vcs =
         ((vertex_cache_t::VERTEX_BUFFER_SIZE +
         vertex_cache_t::VERTEX_CACHE_SIZE) / 3) * 3;
     do {
         vertex_t* v = c->vc.vBuffer;
-        GLsizei num = count > vcs ? vcs : count; 
+        GLsizei num = count > vcs ? vcs : count;
         c->arrays.cull = vertex_t::CLIP_ALL;
         c->arrays.compileElements(c, v, first, num);
         first += num;
@@ -779,11 +788,11 @@
 {
     if (ggl_unlikely(count < 2))
         return;
-    
+
     vertex_t * const v = c->vc.vBuffer;
     vertex_t* v0 = v;
     vertex_t* v1;
-    
+
     const int type = (c->arrays.indicesType == GL_UNSIGNED_BYTE);
     c->arrays.compileElement(c, v0, read_index(type, indices));
     count -= 1;
@@ -806,11 +815,11 @@
         drawIndexedPrimitivesLines(c, count, indices);
         return;
     }
- 
+
     vertex_t * const v = c->vc.vBuffer;
     vertex_t* v0 = v;
     vertex_t* v1;
-    
+
     const int type = (c->arrays.indicesType == GL_UNSIGNED_BYTE);
     c->arrays.compileElement(c, v0, read_index(type, indices));
     count -= 1;
@@ -825,7 +834,7 @@
     } while (count);
     v1->locked = 0;
 
-    v1 = c->vc.vBuffer; 
+    v1 = c->vc.vBuffer;
     const uint32_t cc = v0->flags & v1->flags;
     if (ggl_likely(!(cc & vertex_t::CLIP_ALL)))
         c->prims.renderLine(c, v0, v1);
@@ -861,7 +870,7 @@
 
     if (ggl_unlikely(count < 3))
         return;
-    
+
     vertex_t * const v = c->vc.vBuffer;
     vertex_t* v0 = v;
     vertex_t* v1 = v+1;
@@ -985,17 +994,17 @@
     const GLfixed* vp = (const GLfixed*)c->arrays.vertex.element(first);
     const size_t stride = c->arrays.vertex.stride / 4;
 //    const GLfixed* const& m = c->transforms.mvp.matrix.m;
-    
+
     GLfixed m[16];
     memcpy(&m, c->transforms.mvp.matrix.m, sizeof(m));
-    
+
     do {
         const GLfixed rx = vp[0];
         const GLfixed ry = vp[1];
         const GLfixed rz = vp[2];
         vp += stride;
         v->index = first++;
-        v->clip.x = mla3a(rx, m[ 0], ry, m[ 4], rz, m[ 8], m[12]); 
+        v->clip.x = mla3a(rx, m[ 0], ry, m[ 4], rz, m[ 8], m[12]);
         v->clip.y = mla3a(rx, m[ 1], ry, m[ 5], rz, m[ 9], m[13]);
         v->clip.z = mla3a(rx, m[ 2], ry, m[ 6], rz, m[10], m[14]);
         v->clip.w = mla3a(rx, m[ 3], ry, m[ 7], rz, m[11], m[15]);
@@ -1023,7 +1032,7 @@
 #pragma mark clippers
 #endif
 
-static void clipVec4(vec4_t& nv, 
+static void clipVec4(vec4_t& nv,
         GLfixed t, const vec4_t& s, const vec4_t& p)
 {
     for (int i=0; i<4 ; i++)
@@ -1086,10 +1095,10 @@
     // automatically turn it off (in fact we could when the 4th coordinate
     // is not spcified in the vertex array).
     // W interpolation is never needed for points.
-    GLboolean perspective = 
+    GLboolean perspective =
         c->perspective && mode!=GL_POINTS && (enables & GGL_ENABLE_TMUS);
     c->rasterizer.procs.enableDisable(c, GGL_W_LERP, perspective);
-    
+
     // set anti-aliasing
     GLboolean smooth = GL_FALSE;
     switch (mode) {
@@ -1120,7 +1129,7 @@
     if (enables & GGL_ENABLE_TMUS) { // needs texture transforms
         want |= transform_state_t::TEXTURE;
     }
-    if (c->clipPlanes.enable || (enables & GGL_ENABLE_FOG)) { 
+    if (c->clipPlanes.enable || (enables & GGL_ENABLE_FOG)) {
         want |= transform_state_t::MODELVIEW; // needs eye coords
     }
     ogles_validate_transform(c, want);
@@ -1139,18 +1148,18 @@
 
     c->arrays.mv_transform =
         c->transforms.modelview.transform.pointv[c->arrays.vertex.size - 2];
-    
+
     /*
      * ***********************************************************************
      *  pick fetchers
      * ***********************************************************************
      */
-    
+
     array_machine_t& am = c->arrays;
     am.vertex.fetch = fetchNop;
     am.normal.fetch = currentNormal;
     am.color.fetch = currentColor;
-    
+
     if (am.vertex.enable) {
         am.vertex.resolve();
         if (am.vertex.bo || am.vertex.pointer) {
@@ -1257,9 +1266,7 @@
     GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
 {
     ogles_context_t* c = ogles_context_t::get();
-    // in theory ogles doesn't allow color arrays of size 3
-    // but it is very useful to 'visualize' the normal array.
-    if (size<3 || size>4 || stride<0) {
+    if (size!=4 || stride<0) {
         ogles_error(c, GL_INVALID_VALUE);
         return;
     }
@@ -1366,9 +1373,18 @@
     if ((c->cull.enable) && (c->cull.cullFace == GL_FRONT_AND_BACK))
         return; // all triangles are culled
 
+
     validate_arrays(c, mode);
+
+    const uint32_t enables = c->rasterizer.state.enables;
+    if (enables & GGL_ENABLE_TMUS)
+        ogles_lock_textures(c);
+
     drawArraysPrims[mode](c, first, count);
 
+    if (enables & GGL_ENABLE_TMUS)
+        ogles_unlock_textures(c);
+
 #if VC_CACHE_STATISTICS
     c->vc.total = count;
     c->vc.dump_stats(mode);
@@ -1413,15 +1429,23 @@
     // clear the vertex-cache
     c->vc.clear();
     validate_arrays(c, mode);
-    
+
     // if indices are in a buffer object, the pointer is treated as an
     // offset in that buffer.
     if (c->arrays.element_array_buffer) {
         indices = c->arrays.element_array_buffer->data + uintptr_t(indices);
     }
 
-    drawElementsPrims[mode](c, count, indices);
+    const uint32_t enables = c->rasterizer.state.enables;
+    if (enables & GGL_ENABLE_TMUS)
+        ogles_lock_textures(c);
 
+    drawElementsPrims[mode](c, count, indices);
+    
+    if (enables & GGL_ENABLE_TMUS)
+        ogles_unlock_textures(c);
+
+    
 #if VC_CACHE_STATISTICS
     c->vc.total = count;
     c->vc.dump_stats(mode);
@@ -1448,7 +1472,7 @@
             return;
         }
     }
-    ((target == GL_ARRAY_BUFFER) ? 
+    ((target == GL_ARRAY_BUFFER) ?
             c->arrays.array_buffer : c->arrays.element_array_buffer) = bo;
 }
 
@@ -1467,7 +1491,7 @@
         ogles_error(c, GL_INVALID_ENUM);
         return;
     }
-    buffer_t const* bo = ((target == GL_ARRAY_BUFFER) ? 
+    buffer_t const* bo = ((target == GL_ARRAY_BUFFER) ?
             c->arrays.array_buffer : c->arrays.element_array_buffer);
 
     if (bo == 0) {
@@ -1497,7 +1521,7 @@
         ogles_error(c, GL_INVALID_VALUE);
         return;
     }
-    buffer_t const* bo = ((target == GL_ARRAY_BUFFER) ? 
+    buffer_t const* bo = ((target == GL_ARRAY_BUFFER) ?
             c->arrays.array_buffer : c->arrays.element_array_buffer);
 
     if (bo == 0) {
@@ -1545,7 +1569,7 @@
                 }
             }
         }
-    }    
+    }
     c->bufferObjectManager->deleteBuffers(n, buffers);
     c->bufferObjectManager->recycleTokens(n, buffers);
 }
diff --git a/opengl/libagl/copybit.cpp b/opengl/libagl/copybit.cpp
new file mode 100644
index 0000000..a68750e
--- /dev/null
+++ b/opengl/libagl/copybit.cpp
@@ -0,0 +1,631 @@
+/*
+**
+** Copyright 2009, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "context.h"
+#include "fp.h"
+#include "state.h"
+#include "matrix.h"
+#include "vertex.h"
+#include "light.h"
+#include "primitives.h"
+#include "texture.h"
+#include "BufferObjectManager.h"
+#include "TextureObjectManager.h"
+
+#include <hardware/gralloc.h>
+#include <hardware/copybit.h>
+#include <private/ui/android_natives_priv.h>
+
+#include <ui/GraphicBuffer.h>
+#include <ui/Region.h>
+#include <ui/Rect.h>
+
+
+#define DEBUG_COPYBIT true
+
+// ----------------------------------------------------------------------------
+
+namespace android {
+
+static void textureToCopyBitImage(
+        const GGLSurface* surface, int32_t opFormat, 
+        android_native_buffer_t* buffer, copybit_image_t* img)
+{
+    uint32_t vstride = 0;
+    if (opFormat == COPYBIT_FORMAT_YCbCr_422_SP ||
+            opFormat == COPYBIT_FORMAT_YCbCr_420_SP) {
+        // NOTE: this static_cast is really not safe b/c we can't know for
+        // sure the buffer passed is of the right type.
+        // However, since we do this only for YUV formats, we should be safe
+        // since only SurfaceFlinger makes use of them.
+        GraphicBuffer* graphicBuffer = static_cast<GraphicBuffer*>(buffer);
+        vstride = graphicBuffer->getVerticalStride();
+    }
+
+    img->w      = surface->stride;
+    img->h      = vstride ? vstride : surface->height;
+    img->format = opFormat;
+    img->base   = surface->data;
+    img->handle = (native_handle_t *)buffer->handle;
+}
+
+struct clipRectRegion : public copybit_region_t {
+    clipRectRegion(ogles_context_t* c) 
+    {
+        scissor_t const* scissor = &c->rasterizer.state.scissor;
+        r.l = scissor->left;
+        r.t = scissor->top;
+        r.r = scissor->right;
+        r.b = scissor->bottom;
+        next = iterate; 
+    }
+private:
+    static int iterate(copybit_region_t const * self, copybit_rect_t* rect) {
+        *rect = static_cast<clipRectRegion const*>(self)->r;
+        const_cast<copybit_region_t *>(self)->next = iterate_done;
+        return 1;
+    }
+    static int iterate_done(copybit_region_t const *, copybit_rect_t*) {
+        return 0;
+    }
+public:
+    copybit_rect_t r;
+};
+
+static bool supportedCopybitsFormat(int format) {
+    switch (format) {
+    case COPYBIT_FORMAT_RGBA_8888:
+    case COPYBIT_FORMAT_RGBX_8888:
+    case COPYBIT_FORMAT_RGB_888:
+    case COPYBIT_FORMAT_RGB_565:
+    case COPYBIT_FORMAT_BGRA_8888:
+    case COPYBIT_FORMAT_RGBA_5551:
+    case COPYBIT_FORMAT_RGBA_4444:
+    case COPYBIT_FORMAT_YCbCr_422_SP:
+    case COPYBIT_FORMAT_YCbCr_420_SP:
+        return true;
+    default:
+        return false;
+    }
+}
+
+static bool hasAlpha(int format) {
+    switch (format) {
+    case COPYBIT_FORMAT_RGBA_8888:
+    case COPYBIT_FORMAT_BGRA_8888:
+    case COPYBIT_FORMAT_RGBA_5551:
+    case COPYBIT_FORMAT_RGBA_4444:
+        return true;
+    default:
+        return false;
+    }
+}
+
+static inline int fixedToByte(GGLfixed val) {
+    return (val - (val >> 8)) >> 8;
+}
+
+/**
+ * Performs a quick check of the rendering state. If this function returns
+ * false we cannot use the copybit driver.
+ */
+
+static bool checkContext(ogles_context_t* c) {
+
+	// By convention copybitQuickCheckContext() has already returned true.
+	// avoid checking the same information again.
+	
+    if (c->copybits.blitEngine == NULL) {
+        LOGD_IF(DEBUG_COPYBIT, "no copybit hal");
+        return false;
+    }
+
+    if (c->rasterizer.state.enables
+                    & (GGL_ENABLE_DEPTH_TEST|GGL_ENABLE_FOG)) {
+        LOGD_IF(DEBUG_COPYBIT, "depth test and/or fog");
+        return false;
+    }
+
+    // Note: The drawSurfaceBuffer is only set for destination
+    // surfaces types that are supported by the hardware and
+    // do not have an alpha channel. So we don't have to re-check that here.
+
+    static const int tmu = 0;
+    texture_unit_t& u(c->textures.tmu[tmu]);
+    EGLTextureObject* textureObject = u.texture;
+
+    if (!supportedCopybitsFormat(textureObject->surface.format)) {
+        LOGD_IF(DEBUG_COPYBIT, "texture format not supported");
+        return false;
+    }
+    return true;
+}
+
+
+static bool copybit(GLint x, GLint y,
+        GLint w, GLint h,
+        EGLTextureObject* textureObject,
+        const GLint* crop_rect,
+        int transform,
+        ogles_context_t* c)
+{
+    status_t err = NO_ERROR;
+
+    // We assume checkContext has already been called and has already
+    // returned true.
+
+    const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s;
+
+    y = cbSurface.height - (y + h);
+
+    const GLint Ucr = crop_rect[0];
+    const GLint Vcr = crop_rect[1];
+    const GLint Wcr = crop_rect[2];
+    const GLint Hcr = crop_rect[3];
+
+    GLint screen_w = w;
+    GLint screen_h = h;
+    int32_t dsdx = Wcr << 16;   // dsdx =  ((Wcr/screen_w)/Wt)*Wt
+    int32_t dtdy = Hcr << 16;   // dtdy = -((Hcr/screen_h)/Ht)*Ht
+    if (transform & COPYBIT_TRANSFORM_ROT_90) {
+        swap(screen_w, screen_h);
+    }
+    if (dsdx!=screen_w || dtdy!=screen_h) {
+        // in most cases the divide is not needed
+        dsdx /= screen_w;
+        dtdy /= screen_h;
+    }
+    dtdy = -dtdy; // see equation of dtdy above
+
+    // copybit doesn't say anything about filtering, so we can't
+    // discriminate. On msm7k, copybit will always filter.
+    // the code below handles min/mag filters, we keep it as a reference.
+    
+#ifdef MIN_MAG_FILTER
+    int32_t texelArea = gglMulx(dtdy, dsdx);
+    if (texelArea < FIXED_ONE && textureObject->mag_filter != GL_LINEAR) {
+        // Non-linear filtering on a texture enlargement.
+        LOGD_IF(DEBUG_COPYBIT, "mag filter is not GL_LINEAR");
+        return false;
+    }
+    if (texelArea > FIXED_ONE && textureObject->min_filter != GL_LINEAR) {
+        // Non-linear filtering on an texture shrink.
+        LOGD_IF(DEBUG_COPYBIT, "min filter is not GL_LINEAR");
+        return false;
+    }
+#endif
+    
+    const uint32_t enables = c->rasterizer.state.enables;
+    int planeAlpha = 255;
+    bool alphaPlaneWorkaround = false;
+    static const int tmu = 0;
+    texture_t& tev(c->rasterizer.state.texture[tmu]);
+    int32_t opFormat = textureObject->surface.format;
+    const bool srcTextureHasAlpha = hasAlpha(opFormat);
+    if (!srcTextureHasAlpha) {
+        planeAlpha = fixedToByte(c->currentColorClamped.a);
+    }
+
+    const bool cbHasAlpha = hasAlpha(cbSurface.format);
+    bool blending = false;
+    if ((enables & GGL_ENABLE_BLENDING)
+            && !(c->rasterizer.state.blend.src == GL_ONE
+                    && c->rasterizer.state.blend.dst == GL_ZERO)) {
+        // Blending is OK if it is
+        // the exact kind of blending that the copybits hardware supports.
+        // Note: The hardware only supports
+        // GL_SRC_ALPHA / GL_ONE_MINUS_SRC_ALPHA,
+        // But the surface flinger uses GL_ONE / GL_ONE_MINUS_SRC_ALPHA.
+        // We substitute GL_SRC_ALPHA / GL_ONE_MINUS_SRC_ALPHA in that case,
+        // because the performance is worth it, even if the results are
+        // not correct.
+        if (!((c->rasterizer.state.blend.src == GL_SRC_ALPHA
+                || c->rasterizer.state.blend.src == GL_ONE)
+                && c->rasterizer.state.blend.dst == GL_ONE_MINUS_SRC_ALPHA
+                && c->rasterizer.state.blend.alpha_separate == 0)) {
+            // Incompatible blend mode.
+            LOGD_IF(DEBUG_COPYBIT, "incompatible blend mode");
+            return false;
+        }
+        blending = true;
+    } else {
+        if (cbHasAlpha) {
+            // NOTE: the result will be slightly wrong in this case because
+            // the destination alpha channel will be set to 1.0 instead of
+            // the iterated alpha value. *shrug*.
+        }
+        // disable plane blending and src blending for supported formats
+        planeAlpha = 255;
+        if (opFormat == COPYBIT_FORMAT_RGBA_8888) {
+            opFormat = COPYBIT_FORMAT_RGBX_8888;
+        } else {
+            if (srcTextureHasAlpha) {
+                LOGD_IF(DEBUG_COPYBIT, "texture format requires blending");
+                return false;
+            }
+        }
+    }
+
+    switch (tev.env) {
+    case GGL_REPLACE:
+        break;
+    case GGL_MODULATE:
+        // only cases allowed is:
+        // RGB  source, color={1,1,1,a} -> can be done with GL_REPLACE
+        // RGBA source, color={1,1,1,1} -> can be done with GL_REPLACE
+        if (blending) {
+            if (c->currentColorClamped.r == c->currentColorClamped.a &&
+                c->currentColorClamped.g == c->currentColorClamped.a &&
+                c->currentColorClamped.b == c->currentColorClamped.a) {
+                // TODO: RGBA source, color={1,1,1,a} / regular-blending
+                // is equivalent
+                alphaPlaneWorkaround = true;
+                break;
+            }
+        }
+        LOGD_IF(DEBUG_COPYBIT, "GGL_MODULATE");
+        return false;
+    default:
+        // Incompatible texture environment.
+        LOGD_IF(DEBUG_COPYBIT, "incompatible texture environment");
+        return false;
+    }
+
+    copybit_device_t* copybit = c->copybits.blitEngine;
+    copybit_image_t src;
+    textureToCopyBitImage(&textureObject->surface, opFormat,
+            textureObject->buffer, &src);
+    copybit_rect_t srect = { Ucr, Vcr + Hcr, Ucr + Wcr, Vcr };
+
+    /*
+     *  Below we perform extra passes needed to emulate things the h/w
+     * cannot do.
+     */
+
+    const GLfixed minScaleInv = gglDivQ(0x10000, c->copybits.minScale, 16);
+    const GLfixed maxScaleInv = gglDivQ(0x10000, c->copybits.maxScale, 16);
+
+    sp<GraphicBuffer> tempBitmap;
+
+    if (dsdx < maxScaleInv || dsdx > minScaleInv ||
+        dtdy < maxScaleInv || dtdy > minScaleInv)
+    {
+        // The requested scale is out of the range the hardware
+        // can support.
+        LOGD_IF(DEBUG_COPYBIT,
+                "scale out of range dsdx=%08x (Wcr=%d / w=%d), "
+                "dtdy=%08x (Hcr=%d / h=%d), Ucr=%d, Vcr=%d",
+                dsdx, Wcr, w, dtdy, Hcr, h, Ucr, Vcr);
+
+        int32_t xscale=0x10000, yscale=0x10000;
+        if (dsdx > minScaleInv)         xscale = c->copybits.minScale;
+        else if (dsdx < maxScaleInv)    xscale = c->copybits.maxScale;
+        if (dtdy > minScaleInv)         yscale = c->copybits.minScale;
+        else if (dtdy < maxScaleInv)    yscale = c->copybits.maxScale;
+        dsdx = gglMulx(dsdx, xscale);
+        dtdy = gglMulx(dtdy, yscale);
+
+        /* we handle only one step of resizing below. Handling an arbitrary
+         * number is relatively easy (replace "if" above by "while"), but requires
+         * two intermediate buffers and so far we never had the need.
+         */
+
+        if (dsdx < maxScaleInv || dsdx > minScaleInv ||
+            dtdy < maxScaleInv || dtdy > minScaleInv) {
+            LOGD_IF(DEBUG_COPYBIT,
+                    "scale out of range dsdx=%08x (Wcr=%d / w=%d), "
+                    "dtdy=%08x (Hcr=%d / h=%d), Ucr=%d, Vcr=%d",
+                    dsdx, Wcr, w, dtdy, Hcr, h, Ucr, Vcr);
+            return false;
+        }
+
+        const int tmp_w = gglMulx(srect.r - srect.l, xscale, 16);
+        const int tmp_h = gglMulx(srect.b - srect.t, yscale, 16);
+
+        LOGD_IF(DEBUG_COPYBIT,
+                "xscale=%08x, yscale=%08x, dsdx=%08x, dtdy=%08x, tmp_w=%d, tmp_h=%d",
+                xscale, yscale, dsdx, dtdy, tmp_w, tmp_h);
+
+        tempBitmap = new GraphicBuffer(
+                    tmp_w, tmp_h, src.format,
+                    GraphicBuffer::USAGE_HW_2D);
+
+        err = tempBitmap->initCheck();
+        if (err == NO_ERROR) {
+            copybit_image_t tmp_dst;
+            copybit_rect_t tmp_rect;
+            tmp_dst.w = tmp_w;
+            tmp_dst.h = tmp_h;
+            tmp_dst.format = tempBitmap->format;
+            tmp_dst.handle = (native_handle_t*)tempBitmap->getNativeBuffer()->handle;
+            tmp_rect.l = 0;
+            tmp_rect.t = 0;
+            tmp_rect.r = tmp_dst.w;
+            tmp_rect.b = tmp_dst.h;
+            region_iterator tmp_it(Region(Rect(tmp_rect.r, tmp_rect.b)));
+            copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0);
+            copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF);
+            copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_DISABLE);
+            err = copybit->stretch(copybit,
+                    &tmp_dst, &src, &tmp_rect, &srect, &tmp_it);
+            src = tmp_dst;
+            srect = tmp_rect;
+        }
+    }
+
+    copybit_image_t dst;
+    textureToCopyBitImage(&cbSurface, cbSurface.format,
+            c->copybits.drawSurfaceBuffer, &dst);
+    copybit_rect_t drect = {x, y, x+w, y+h};
+
+
+    /* and now the alpha-plane hack. This handles the "Fade" case of a
+     * texture with an alpha channel.
+     */
+    if (alphaPlaneWorkaround) {
+        sp<GraphicBuffer> tempCb = new GraphicBuffer(
+                    w, h, COPYBIT_FORMAT_RGB_565,
+                    GraphicBuffer::USAGE_HW_2D);
+
+        err = tempCb->initCheck();
+
+        copybit_image_t tmpCbImg;
+        copybit_rect_t tmpCbRect;
+        copybit_rect_t tmpdrect = drect;
+        tmpCbImg.w = w;
+        tmpCbImg.h = h;
+        tmpCbImg.format = tempCb->format;
+        tmpCbImg.handle = (native_handle_t*)tempCb->getNativeBuffer()->handle;
+        tmpCbRect.l = 0;
+        tmpCbRect.t = 0;
+
+        if (drect.l < 0) {
+            tmpCbRect.l = -tmpdrect.l;
+            tmpdrect.l = 0;
+        }
+        if (drect.t < 0) {
+            tmpCbRect.t = -tmpdrect.t;
+            tmpdrect.t = 0;
+        }
+        if (drect.l + tmpCbImg.w > dst.w) {
+            tmpCbImg.w = dst.w - drect.l;
+            tmpdrect.r = dst.w;
+        }
+        if (drect.t + tmpCbImg.h > dst.h) {
+            tmpCbImg.h = dst.h - drect.t;
+            tmpdrect.b = dst.h;
+        }
+
+        tmpCbRect.r = tmpCbImg.w;
+        tmpCbRect.b = tmpCbImg.h;
+
+        if (!err) {
+            // first make a copy of the destination buffer
+            region_iterator tmp_it(Region(Rect(w, h)));
+            copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0);
+            copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF);
+            copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_DISABLE);
+            err = copybit->stretch(copybit,
+                    &tmpCbImg, &dst, &tmpCbRect, &tmpdrect, &tmp_it);
+        }
+        if (!err) {
+            // then proceed as usual, but without the alpha plane
+            copybit->set_parameter(copybit, COPYBIT_TRANSFORM, transform);
+            copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF);
+            copybit->set_parameter(copybit, COPYBIT_DITHER,
+                    (enables & GGL_ENABLE_DITHER) ?
+                            COPYBIT_ENABLE : COPYBIT_DISABLE);
+            clipRectRegion it(c);
+            err = copybit->stretch(copybit, &dst, &src, &drect, &srect, &it);
+        }
+        if (!err) {
+            // finally copy back the destination on top with 1-alphaplane
+            int invPlaneAlpha = 0xFF - fixedToByte(c->currentColorClamped.a);
+            clipRectRegion it(c);
+            copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0);
+            copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, invPlaneAlpha);
+            copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_ENABLE);
+            err = copybit->stretch(copybit,
+                    &dst, &tmpCbImg, &tmpdrect, &tmpCbRect, &it);
+        }
+    } else {
+        copybit->set_parameter(copybit, COPYBIT_TRANSFORM, transform);
+        copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, planeAlpha);
+        copybit->set_parameter(copybit, COPYBIT_DITHER,
+                (enables & GGL_ENABLE_DITHER) ?
+                        COPYBIT_ENABLE : COPYBIT_DISABLE);
+        clipRectRegion it(c);
+
+        LOGD_IF(0,
+             "dst={%d, %d, %d, %p, %p}, "
+             "src={%d, %d, %d, %p, %p}, "
+             "drect={%d,%d,%d,%d}, "
+             "srect={%d,%d,%d,%d}, "
+             "it={%d,%d,%d,%d}, " ,
+             dst.w, dst.h, dst.format, dst.base, dst.handle,
+             src.w, src.h, src.format, src.base, src.handle,
+             drect.l, drect.t, drect.r, drect.b,
+             srect.l, srect.t, srect.r, srect.b,
+             it.r.l, it.r.t, it.r.r, it.r.b
+        );
+
+        err = copybit->stretch(copybit, &dst, &src, &drect, &srect, &it);
+    }
+    if (err != NO_ERROR) {
+        c->textures.tmu[0].texture->try_copybit = false;
+    }
+    return err == NO_ERROR ? true : false;
+}
+
+/*
+ * Try to draw a triangle fan with copybit, return false if we fail.
+ */
+bool drawTriangleFanWithCopybit_impl(ogles_context_t* c, GLint first, GLsizei count)
+{
+    if (!checkContext(c)) {
+        return false;
+    }
+
+    // FIXME: we should handle culling  here
+    c->arrays.compileElements(c, c->vc.vBuffer, 0, 4);
+
+    // we detect if we're dealing with a rectangle, by comparing the
+    // rectangles {v0,v2} and {v1,v3} which should be identical.
+    
+    // NOTE: we should check that the rectangle is window aligned, however
+    // if we do that, the optimization won't be taken in a lot of cases.
+    // Since this code is intended to be used with SurfaceFlinger only,
+    // so it's okay...
+    
+    const vec4_t& v0 = c->vc.vBuffer[0].window;
+    const vec4_t& v1 = c->vc.vBuffer[1].window;
+    const vec4_t& v2 = c->vc.vBuffer[2].window;
+    const vec4_t& v3 = c->vc.vBuffer[3].window;
+    int l = min(v0.x, v2.x);
+    int b = min(v0.y, v2.y);
+    int r = max(v0.x, v2.x);
+    int t = max(v0.y, v2.y);
+    if ((l != min(v1.x, v3.x)) || (b != min(v1.y, v3.y)) ||
+        (r != max(v1.x, v3.x)) || (t != max(v1.y, v3.y))) {
+        LOGD_IF(DEBUG_COPYBIT, "geometry not a rectangle");
+        return false;
+    }
+
+    // fetch and transform texture coordinates
+    // NOTE: maybe it would be better to have a "compileElementsAll" method
+    // that would ensure all vertex data are fetched and transformed
+    const transform_t& tr = c->transforms.texture[0].transform; 
+    for (size_t i=0 ; i<4 ; i++) {
+        const GLubyte* tp = c->arrays.texture[0].element(i);
+        vertex_t* const v = &c->vc.vBuffer[i];
+        c->arrays.texture[0].fetch(c, v->texture[0].v, tp);
+        // FIXME: we should bail if q!=1
+        c->arrays.tex_transform[0](&tr, &v->texture[0], &v->texture[0]);
+    }
+    
+    const vec4_t& t0 = c->vc.vBuffer[0].texture[0];
+    const vec4_t& t1 = c->vc.vBuffer[1].texture[0];
+    const vec4_t& t2 = c->vc.vBuffer[2].texture[0];
+    const vec4_t& t3 = c->vc.vBuffer[3].texture[0];
+    int txl = min(t0.x, t2.x);
+    int txb = min(t0.y, t2.y);
+    int txr = max(t0.x, t2.x);
+    int txt = max(t0.y, t2.y);
+    if ((txl != min(t1.x, t3.x)) || (txb != min(t1.y, t3.y)) ||
+        (txr != max(t1.x, t3.x)) || (txt != max(t1.y, t3.y))) {
+        LOGD_IF(DEBUG_COPYBIT, "texcoord not a rectangle");
+        return false;
+    }
+    if ((txl != 0) || (txb != 0) ||
+        (txr != FIXED_ONE) || (txt != FIXED_ONE)) {
+        // we could probably handle this case, if we wanted to
+        LOGD_IF(DEBUG_COPYBIT, "texture is cropped: %08x,%08x,%08x,%08x",
+                txl, txb, txr, txt);
+        return false;
+    }
+
+    // at this point, we know we are dealing with a rectangle, so we 
+    // only need to consider 3 vertices for computing the jacobians
+    
+    const int dx01 = v1.x - v0.x;
+    const int dx02 = v2.x - v0.x;
+    const int dy01 = v1.y - v0.y;
+    const int dy02 = v2.y - v0.y;
+    const int ds01 = t1.S - t0.S;
+    const int ds02 = t2.S - t0.S;
+    const int dt01 = t1.T - t0.T;
+    const int dt02 = t2.T - t0.T;
+    const int area = dx01*dy02 - dy01*dx02;
+    int dsdx, dsdy, dtdx, dtdy;
+    if (area >= 0) {
+        dsdx = ds01*dy02 - ds02*dy01;
+        dtdx = dt01*dy02 - dt02*dy01;
+        dsdy = ds02*dx01 - ds01*dx02;
+        dtdy = dt02*dx01 - dt01*dx02;
+    } else {
+        dsdx = ds02*dy01 - ds01*dy02;
+        dtdx = dt02*dy01 - dt01*dy02;
+        dsdy = ds01*dx02 - ds02*dx01;
+        dtdy = dt01*dx02 - dt02*dx01;
+    }
+
+    // here we rely on the fact that we know the transform is
+    // a rigid-body transform AND that it can only rotate in 90 degrees
+    // increments
+
+    int transform = 0;
+    if (dsdx == 0) {
+        // 90 deg rotation case
+        // [ 0    dtdx  ]
+        // [ dsdx    0  ]
+        transform |= COPYBIT_TRANSFORM_ROT_90;
+        // FIXME: not sure if FLIP_H and FLIP_V shouldn't be inverted
+        if (dtdx > 0)
+            transform |= COPYBIT_TRANSFORM_FLIP_H;
+        if (dsdy < 0)
+            transform |= COPYBIT_TRANSFORM_FLIP_V;
+    } else {
+        // [ dsdx    0  ]
+        // [ 0     dtdy ]
+        if (dsdx < 0)
+            transform |= COPYBIT_TRANSFORM_FLIP_H;
+        if (dtdy < 0)
+            transform |= COPYBIT_TRANSFORM_FLIP_V;
+    }
+
+    //LOGD("l=%d, b=%d, w=%d, h=%d, tr=%d", x, y, w, h, transform);
+    //LOGD("A=%f\tB=%f\nC=%f\tD=%f",
+    //      dsdx/65536.0, dtdx/65536.0, dsdy/65536.0, dtdy/65536.0);
+
+    int x = l >> 4;
+    int y = b >> 4;
+    int w = (r-l) >> 4;
+    int h = (t-b) >> 4;
+    texture_unit_t& u(c->textures.tmu[0]);
+    EGLTextureObject* textureObject = u.texture;
+    GLint tWidth = textureObject->surface.width;
+    GLint tHeight = textureObject->surface.height;
+    GLint crop_rect[4] = {0, tHeight, tWidth, -tHeight};
+    const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s;
+    y = cbSurface.height - (y + h);
+    return copybit(x, y, w, h, textureObject, crop_rect, transform, c);
+}
+
+/*
+ * Try to drawTexiOESWithCopybit, return false if we fail.
+ */
+
+bool drawTexiOESWithCopybit_impl(GLint x, GLint y, GLint z,
+        GLint w, GLint h, ogles_context_t* c)
+{
+    // quickly process empty rects
+    if ((w|h) <= 0) {
+        return true;
+    }
+    if (!checkContext(c)) {
+        return false;
+    }
+    texture_unit_t& u(c->textures.tmu[0]);
+    EGLTextureObject* textureObject = u.texture;
+    return copybit(x, y, w, h, textureObject, textureObject->crop_rect, 0, c);
+}
+
+} // namespace android
+
diff --git a/opengl/libagl/copybit.h b/opengl/libagl/copybit.h
new file mode 100644
index 0000000..b8b5afd
--- /dev/null
+++ b/opengl/libagl/copybit.h
@@ -0,0 +1,75 @@
+/*
+**
+** Copyright 2009, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#ifndef ANDROID_OPENGLES_COPYBIT_H
+#define ANDROID_OPENGLES_COPYBIT_H
+
+#include <stdlib.h>
+
+#include <GLES/gl.h>
+
+#include "TextureObjectManager.h"
+namespace android {
+#ifdef LIBAGL_USE_GRALLOC_COPYBITS
+
+bool drawTexiOESWithCopybit_impl(GLint x, GLint y, GLint z,
+        GLint w, GLint h, ogles_context_t* c);
+
+bool drawTriangleFanWithCopybit_impl(ogles_context_t* c, GLint first,
+        GLsizei count);
+
+inline bool copybitQuickCheckContext(ogles_context_t* c) {
+        return  c->copybits.drawSurfaceBuffer != 0
+            && c->rasterizer.state.enabled_tmu == 1
+            && c->textures.tmu[0].texture->try_copybit;
+}
+
+/*
+ * Tries to draw a drawTexiOES using copybit hardware.
+ * Returns true if successful.
+ */
+inline bool drawTexiOESWithCopybit(GLint x, GLint y, GLint z,
+        GLint w, GLint h, ogles_context_t* c) {
+    if (!copybitQuickCheckContext(c)) {
+    	return false;
+   	}
+   	
+   	return drawTexiOESWithCopybit_impl(x, y, z, w, h, c);
+}
+
+/*
+ * Tries to draw a triangle fan using copybit hardware.
+ * Returns true if successful.
+ */
+inline bool drawTriangleFanWithCopybit(ogles_context_t* c, GLint first,
+        GLsizei count) {
+    /*
+     * We are looking for the glDrawArrays call made by SurfaceFlinger.
+     */
+
+    if ((count!=4) || first || !copybitQuickCheckContext(c))
+        return false;
+    
+    return drawTriangleFanWithCopybit_impl(c, first, count);
+}
+
+
+#endif // LIBAGL_USE_GRALLOC_COPYBITS
+
+} // namespace android
+
+#endif // ANDROID_OPENGLES_COPYBIT_H
diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp
index 4461567..673c174 100644
--- a/opengl/libagl/egl.cpp
+++ b/opengl/libagl/egl.cpp
@@ -15,8 +15,6 @@
 ** limitations under the License.
 */
 
-#define LOG_TAG "EGL"
-
 #include <assert.h>
 #include <errno.h>
 #include <stdlib.h>
@@ -41,6 +39,11 @@
 #include <pixelflinger/format.h>
 #include <pixelflinger/pixelflinger.h>
 
+#include <private/ui/android_natives_priv.h>
+#include <private/ui/sw_gralloc_handle.h>
+
+#include <hardware/copybit.h>
+
 #include "context.h"
 #include "state.h"
 #include "texture.h"
@@ -89,9 +92,9 @@
 struct egl_display_t
 {
     egl_display_t() : type(0), initialized(0) { }
-    
+
     static egl_display_t& get_display(EGLDisplay dpy);
-    
+
     static EGLBoolean is_valid(EGLDisplay dpy) {
         return ((uintptr_t(dpy)-1U) >= NUM_DISPLAYS) ? EGL_FALSE : EGL_TRUE;
     }
@@ -139,19 +142,23 @@
 
                 egl_surface_t(EGLDisplay dpy, EGLConfig config, int32_t depthFormat);
     virtual     ~egl_surface_t();
-    virtual     bool    isValid() const = 0;
-    
+                bool    isValid() const;
+    virtual     bool    initCheck() const = 0;
+
     virtual     EGLBoolean  bindDrawSurface(ogles_context_t* gl) = 0;
     virtual     EGLBoolean  bindReadSurface(ogles_context_t* gl) = 0;
+    virtual     EGLBoolean  connect() { return EGL_TRUE; }
+    virtual     void        disconnect() {}
     virtual     EGLint      getWidth() const = 0;
     virtual     EGLint      getHeight() const = 0;
-    virtual     void*       getBits() const = 0;
 
     virtual     EGLint      getHorizontalResolution() const;
     virtual     EGLint      getVerticalResolution() const;
     virtual     EGLint      getRefreshRate() const;
     virtual     EGLint      getSwapBehavior() const;
     virtual     EGLBoolean  swapBuffers();
+    virtual     EGLBoolean  setSwapRectangle(EGLint l, EGLint t, EGLint w, EGLint h);
+    virtual     EGLClientBuffer getRenderBuffer() const;
 protected:
     GGLSurface              depth;
 };
@@ -170,6 +177,11 @@
     magic = 0;
     free(depth.data);
 }
+bool egl_surface_t::isValid() const {
+    LOGE_IF(magic != MAGIC, "invalid EGLSurface (%p)", this);
+    return magic == MAGIC; 
+}
+
 EGLBoolean egl_surface_t::swapBuffers() {
     return EGL_FALSE;
 }
@@ -185,119 +197,519 @@
 EGLint egl_surface_t::getSwapBehavior() const {
     return EGL_BUFFER_PRESERVED;
 }
+EGLBoolean egl_surface_t::setSwapRectangle(
+        EGLint l, EGLint t, EGLint w, EGLint h)
+{
+    return EGL_FALSE;
+}
+EGLClientBuffer egl_surface_t::getRenderBuffer() const {
+    return 0;
+}
 
 // ----------------------------------------------------------------------------
 
-struct egl_window_surface_t : public egl_surface_t
+struct egl_window_surface_v2_t : public egl_surface_t
 {
-    egl_window_surface_t(
+    egl_window_surface_v2_t(
             EGLDisplay dpy, EGLConfig config,
             int32_t depthFormat,
-            egl_native_window_t* window);
+            android_native_window_t* window);
 
-     ~egl_window_surface_t();
+    ~egl_window_surface_v2_t();
 
-    virtual     bool        isValid() const { return nativeWindow->magic == 0x600913; }    
+    virtual     bool        initCheck() const { return true; } // TODO: report failure if ctor fails
     virtual     EGLBoolean  swapBuffers();
     virtual     EGLBoolean  bindDrawSurface(ogles_context_t* gl);
     virtual     EGLBoolean  bindReadSurface(ogles_context_t* gl);
-    virtual     EGLint      getWidth() const    { return nativeWindow->width;  }
-    virtual     EGLint      getHeight() const   { return nativeWindow->height; }
-    virtual     void*       getBits() const;
+    virtual     EGLBoolean  connect();
+    virtual     void        disconnect();
+    virtual     EGLint      getWidth() const    { return width;  }
+    virtual     EGLint      getHeight() const   { return height; }
     virtual     EGLint      getHorizontalResolution() const;
     virtual     EGLint      getVerticalResolution() const;
     virtual     EGLint      getRefreshRate() const;
     virtual     EGLint      getSwapBehavior() const;
+    virtual     EGLBoolean  setSwapRectangle(EGLint l, EGLint t, EGLint w, EGLint h);
+    virtual     EGLClientBuffer  getRenderBuffer() const;
+    
 private:
-    egl_native_window_t*    nativeWindow;
+    status_t lock(android_native_buffer_t* buf, int usage, void** vaddr);
+    status_t unlock(android_native_buffer_t* buf);
+    android_native_window_t*   nativeWindow;
+    android_native_buffer_t*   buffer;
+    android_native_buffer_t*   previousBuffer;
+    gralloc_module_t const*    module;
+    copybit_device_t*          blitengine;
+    int width;
+    int height;
+    void* bits;
+    GGLFormat const* pixelFormatTable;
+    
+    struct Rect {
+        inline Rect() { };
+        inline Rect(int32_t w, int32_t h)
+            : left(0), top(0), right(w), bottom(h) { }
+        inline Rect(int32_t l, int32_t t, int32_t r, int32_t b)
+            : left(l), top(t), right(r), bottom(b) { }
+        Rect& andSelf(const Rect& r) {
+            left   = max(left, r.left);
+            top    = max(top, r.top);
+            right  = min(right, r.right);
+            bottom = min(bottom, r.bottom);
+            return *this;
+        }
+        bool isEmpty() const {
+            return (left>=right || top>=bottom);
+        }
+        void dump(char const* what) {
+            LOGD("%s { %5d, %5d, w=%5d, h=%5d }", 
+                    what, left, top, right-left, bottom-top);
+        }
+        
+        int32_t left;
+        int32_t top;
+        int32_t right;
+        int32_t bottom;
+    };
+
+    struct Region {
+        inline Region() : count(0) { }
+        typedef Rect const* const_iterator;
+        const_iterator begin() const { return storage; }
+        const_iterator end() const { return storage+count; }
+        static Region subtract(const Rect& lhs, const Rect& rhs) {
+            Region reg;
+            Rect* storage = reg.storage;
+            if (!lhs.isEmpty()) {
+                if (lhs.top < rhs.top) { // top rect
+                    storage->left   = lhs.left;
+                    storage->top    = lhs.top;
+                    storage->right  = lhs.right;
+                    storage->bottom = rhs.top;
+                    storage++;
+                }
+                const int32_t top = max(lhs.top, rhs.top);
+                const int32_t bot = min(lhs.bottom, rhs.bottom);
+                if (top < bot) {
+                    if (lhs.left < rhs.left) { // left-side rect
+                        storage->left   = lhs.left;
+                        storage->top    = top;
+                        storage->right  = rhs.left;
+                        storage->bottom = bot;
+                        storage++;
+                    }
+                    if (lhs.right > rhs.right) { // right-side rect
+                        storage->left   = rhs.right;
+                        storage->top    = top;
+                        storage->right  = lhs.right;
+                        storage->bottom = bot;
+                        storage++;
+                    }
+                }
+                if (lhs.bottom > rhs.bottom) { // bottom rect
+                    storage->left   = lhs.left;
+                    storage->top    = rhs.bottom;
+                    storage->right  = lhs.right;
+                    storage->bottom = lhs.bottom;
+                    storage++;
+                }
+                reg.count = storage - reg.storage;
+            }
+            return reg;
+        }
+        bool isEmpty() const {
+            return count<=0;
+        }
+    private:
+        Rect storage[4];
+        ssize_t count;
+    };
+    
+    struct region_iterator : public copybit_region_t {
+        region_iterator(const Region& region)
+            : b(region.begin()), e(region.end()) {
+            this->next = iterate;
+        }
+    private:
+        static int iterate(copybit_region_t const * self, copybit_rect_t* rect) {
+            region_iterator const* me = static_cast<region_iterator const*>(self);
+            if (me->b != me->e) {
+                *reinterpret_cast<Rect*>(rect) = *me->b++;
+                return 1;
+            }
+            return 0;
+        }
+        mutable Region::const_iterator b;
+        Region::const_iterator const e;
+    };
+
+    void copyBlt(
+            android_native_buffer_t* dst, void* dst_vaddr,
+            android_native_buffer_t* src, void const* src_vaddr,
+            const Region& clip);
+
+    Rect dirtyRegion;
+    Rect oldDirtyRegion;
 };
 
-egl_window_surface_t::egl_window_surface_t(EGLDisplay dpy,
+egl_window_surface_v2_t::egl_window_surface_v2_t(EGLDisplay dpy,
         EGLConfig config,
         int32_t depthFormat,
-        egl_native_window_t* window)
-    : egl_surface_t(dpy, config, depthFormat), nativeWindow(window)
+        android_native_window_t* window)
+    : egl_surface_t(dpy, config, depthFormat), 
+    nativeWindow(window), buffer(0), previousBuffer(0), module(0),
+    blitengine(0), bits(NULL)
 {
-    if (depthFormat) {
-        depth.width   = window->width;
-        depth.height  = window->height;
+    hw_module_t const* pModule;
+    hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &pModule);
+    module = reinterpret_cast<gralloc_module_t const*>(pModule);
+
+    if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &pModule) == 0) {
+        copybit_open(pModule, &blitengine);
+    }
+
+    pixelFormatTable = gglGetPixelFormatTable();
+    
+    // keep a reference on the window
+    nativeWindow->common.incRef(&nativeWindow->common);
+    nativeWindow->query(nativeWindow, NATIVE_WINDOW_WIDTH, &width);
+    nativeWindow->query(nativeWindow, NATIVE_WINDOW_HEIGHT, &height);
+}
+
+egl_window_surface_v2_t::~egl_window_surface_v2_t() {
+    if (buffer) {
+        buffer->common.decRef(&buffer->common);
+    }
+    if (previousBuffer) {
+        previousBuffer->common.decRef(&previousBuffer->common); 
+    }
+    nativeWindow->common.decRef(&nativeWindow->common);
+    if (blitengine) {
+        copybit_close(blitengine);
+    }
+}
+
+EGLBoolean egl_window_surface_v2_t::connect() 
+{
+    // we're intending to do software rendering
+    native_window_set_usage(nativeWindow, 
+            GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
+
+    // dequeue a buffer
+    if (nativeWindow->dequeueBuffer(nativeWindow, &buffer) != NO_ERROR) {
+        return setError(EGL_BAD_ALLOC, EGL_FALSE);
+    }
+
+    // allocate a corresponding depth-buffer
+    width = buffer->width;
+    height = buffer->height;
+    if (depth.format) {
+        depth.width   = width;
+        depth.height  = height;
         depth.stride  = depth.width; // use the width here
         depth.data    = (GGLubyte*)malloc(depth.stride*depth.height*2);
         if (depth.data == 0) {
-            setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
-            return;
+            return setError(EGL_BAD_ALLOC, EGL_FALSE);
         }
     }
-    nativeWindow->incRef(nativeWindow);
-}
-egl_window_surface_t::~egl_window_surface_t() {
-    nativeWindow->decRef(nativeWindow);
+
+    // keep a reference on the buffer
+    buffer->common.incRef(&buffer->common);
+
+    // Lock the buffer
+    nativeWindow->lockBuffer(nativeWindow, buffer);
+    // pin the buffer down
+    if (lock(buffer, GRALLOC_USAGE_SW_READ_OFTEN | 
+            GRALLOC_USAGE_SW_WRITE_OFTEN, &bits) != NO_ERROR) {
+        LOGE("connect() failed to lock buffer %p (%ux%u)",
+                buffer, buffer->width, buffer->height);
+        return setError(EGL_BAD_ACCESS, EGL_FALSE);
+        // FIXME: we should make sure we're not accessing the buffer anymore
+    }
+    return EGL_TRUE;
 }
 
-EGLBoolean egl_window_surface_t::swapBuffers()
+void egl_window_surface_v2_t::disconnect() 
 {
-    uint32_t flags = nativeWindow->swapBuffers(nativeWindow);
-    if (flags & EGL_NATIVES_FLAG_SIZE_CHANGED) {
+    if (buffer && bits) {
+        bits = NULL;
+        unlock(buffer);
+    }
+    // enqueue the last frame
+    nativeWindow->queueBuffer(nativeWindow, buffer);
+    if (buffer) {
+        buffer->common.decRef(&buffer->common);
+        buffer = 0;
+    }
+    if (previousBuffer) {
+        previousBuffer->common.decRef(&previousBuffer->common); 
+        previousBuffer = 0;
+    }
+}
+
+status_t egl_window_surface_v2_t::lock(
+        android_native_buffer_t* buf, int usage, void** vaddr)
+{
+    int err;
+    if (sw_gralloc_handle_t::validate(buf->handle) < 0) {
+        err = module->lock(module, buf->handle,
+                usage, 0, 0, buf->width, buf->height, vaddr);
+    } else {
+        sw_gralloc_handle_t const* hnd =
+                reinterpret_cast<sw_gralloc_handle_t const*>(buf->handle);
+        *vaddr = (void*)hnd->base;
+        err = NO_ERROR;
+    }
+    return err;
+}
+
+status_t egl_window_surface_v2_t::unlock(android_native_buffer_t* buf)
+{
+    if (!buf) return BAD_VALUE;
+    int err = NO_ERROR;
+    if (sw_gralloc_handle_t::validate(buf->handle) < 0) {
+        err = module->unlock(module, buf->handle);
+    }
+    return err;
+}
+
+void egl_window_surface_v2_t::copyBlt(
+        android_native_buffer_t* dst, void* dst_vaddr,
+        android_native_buffer_t* src, void const* src_vaddr,
+        const Region& clip)
+{
+    // FIXME: use copybit if possible
+    // NOTE: dst and src must be the same format
+    
+    status_t err = NO_ERROR;
+    copybit_device_t* const copybit = blitengine;
+    if (copybit)  {
+        copybit_image_t simg;
+        simg.w = src->width;
+        simg.h = src->height;
+        simg.format = src->format;
+        simg.handle = const_cast<native_handle_t*>(src->handle);
+
+        copybit_image_t dimg;
+        dimg.w = dst->width;
+        dimg.h = dst->height;
+        dimg.format = dst->format;
+        dimg.handle = const_cast<native_handle_t*>(dst->handle);
+        
+        copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0);
+        copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 255);
+        copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_DISABLE);
+        region_iterator it(clip);
+        err = copybit->blit(copybit, &dimg, &simg, &it);
+        if (err != NO_ERROR) {
+            LOGE("copybit failed (%s)", strerror(err));
+        }
+    }
+
+    if (!copybit || err) {
+        Region::const_iterator cur = clip.begin();
+        Region::const_iterator end = clip.end();
+        
+        const size_t bpp = pixelFormatTable[src->format].size;
+        const size_t dbpr = dst->stride * bpp;
+        const size_t sbpr = src->stride * bpp;
+
+        uint8_t const * const src_bits = (uint8_t const *)src_vaddr;
+        uint8_t       * const dst_bits = (uint8_t       *)dst_vaddr;
+
+        while (cur != end) {
+            const Rect& r(*cur++);
+            ssize_t w = r.right - r.left;
+            ssize_t h = r.bottom - r.top;
+            if (w <= 0 || h<=0) continue;
+            size_t size = w * bpp;
+            uint8_t const * s = src_bits + (r.left + src->stride * r.top) * bpp;
+            uint8_t       * d = dst_bits + (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);
+        }
+    }
+}
+
+EGLBoolean egl_window_surface_v2_t::swapBuffers()
+{
+    if (!buffer) {
+        return setError(EGL_BAD_ACCESS, EGL_FALSE);
+    }
+    
+    /*
+     * Handle eglSetSwapRectangleANDROID()
+     * We copyback from the front buffer 
+     */
+    if (!dirtyRegion.isEmpty()) {
+        dirtyRegion.andSelf(Rect(buffer->width, buffer->height));
+        if (previousBuffer) {
+            const Region copyBack(Region::subtract(oldDirtyRegion, dirtyRegion));
+            if (!copyBack.isEmpty()) {
+                void* prevBits;
+                if (lock(previousBuffer, 
+                        GRALLOC_USAGE_SW_READ_OFTEN, &prevBits) == NO_ERROR) {
+                    // copy from previousBuffer to buffer
+                    copyBlt(buffer, bits, previousBuffer, prevBits, copyBack);
+                    unlock(previousBuffer);
+                }
+            }
+        }
+        oldDirtyRegion = dirtyRegion;
+    }
+
+    if (previousBuffer) {
+        previousBuffer->common.decRef(&previousBuffer->common); 
+        previousBuffer = 0;
+    }
+    
+    unlock(buffer);
+    previousBuffer = buffer;
+    nativeWindow->queueBuffer(nativeWindow, buffer);
+    buffer = 0;
+
+    // dequeue a new buffer
+    nativeWindow->dequeueBuffer(nativeWindow, &buffer);
+    
+    // TODO: lockBuffer should rather be executed when the very first
+    // direct rendering occurs.
+    nativeWindow->lockBuffer(nativeWindow, buffer);
+    
+    // reallocate the depth-buffer if needed
+    if ((width != buffer->width) || (height != buffer->height)) {
         // TODO: we probably should reset the swap rect here
         // if the window size has changed
+        width = buffer->width;
+        height = buffer->height;
         if (depth.data) {
             free(depth.data);
-            depth.width   = nativeWindow->width;
-            depth.height  = nativeWindow->height;
-            depth.stride  = nativeWindow->stride;
+            depth.width   = width;
+            depth.height  = height;
+            depth.stride  = buffer->stride;
             depth.data    = (GGLubyte*)malloc(depth.stride*depth.height*2);
             if (depth.data == 0) {
-                setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
+                setError(EGL_BAD_ALLOC, EGL_FALSE);
                 return EGL_FALSE;
             }
         }
     }
+    
+    // keep a reference on the buffer
+    buffer->common.incRef(&buffer->common);
+
+    // finally pin the buffer down
+    if (lock(buffer, GRALLOC_USAGE_SW_READ_OFTEN | 
+            GRALLOC_USAGE_SW_WRITE_OFTEN, &bits) != NO_ERROR) {
+        LOGE("eglSwapBuffers() failed to lock buffer %p (%ux%u)",
+                buffer, buffer->width, buffer->height);
+        return setError(EGL_BAD_ACCESS, EGL_FALSE);
+        // FIXME: we should make sure we're not accessing the buffer anymore
+    }
+
     return EGL_TRUE;
 }
 
-EGLBoolean egl_window_surface_t::bindDrawSurface(ogles_context_t* gl)
+EGLBoolean egl_window_surface_v2_t::setSwapRectangle(
+        EGLint l, EGLint t, EGLint w, EGLint h)
+{
+    dirtyRegion = Rect(l, t, l+w, t+h);
+    return EGL_TRUE;
+}
+
+EGLClientBuffer egl_window_surface_v2_t::getRenderBuffer() const
+{
+    return buffer;
+}
+
+#ifdef LIBAGL_USE_GRALLOC_COPYBITS
+
+static bool supportedCopybitsDestinationFormat(int format) {
+    // Hardware supported
+    switch (format) {
+    case HAL_PIXEL_FORMAT_RGB_565:
+    case HAL_PIXEL_FORMAT_RGBA_8888:
+    case HAL_PIXEL_FORMAT_RGBX_8888:
+    case HAL_PIXEL_FORMAT_RGBA_4444:
+    case HAL_PIXEL_FORMAT_RGBA_5551:
+    case HAL_PIXEL_FORMAT_BGRA_8888:
+        return true;
+    }
+    return false;
+}
+#endif
+
+EGLBoolean egl_window_surface_v2_t::bindDrawSurface(ogles_context_t* gl)
 {
     GGLSurface buffer;
     buffer.version = sizeof(GGLSurface);
-    buffer.width   = nativeWindow->width;
-    buffer.height  = nativeWindow->height;
-    buffer.stride  = nativeWindow->stride;
-    buffer.data    = (GGLubyte*)nativeWindow->base + nativeWindow->offset;
-    buffer.format  = nativeWindow->format;
+    buffer.width   = this->buffer->width;
+    buffer.height  = this->buffer->height;
+    buffer.stride  = this->buffer->stride;
+    buffer.data    = (GGLubyte*)bits;
+    buffer.format  = this->buffer->format;
     gl->rasterizer.procs.colorBuffer(gl, &buffer);
     if (depth.data != gl->rasterizer.state.buffers.depth.data)
         gl->rasterizer.procs.depthBuffer(gl, &depth);
+
+#ifdef LIBAGL_USE_GRALLOC_COPYBITS
+    gl->copybits.drawSurfaceBuffer = 0;
+    if (gl->copybits.blitEngine != NULL) {
+        if (supportedCopybitsDestinationFormat(buffer.format)) {
+            buffer_handle_t handle = this->buffer->handle;
+            if (handle != NULL) {
+                gl->copybits.drawSurfaceBuffer = this->buffer;
+            }
+        }
+    }
+#endif // LIBAGL_USE_GRALLOC_COPYBITS
+
     return EGL_TRUE;
 }
-EGLBoolean egl_window_surface_t::bindReadSurface(ogles_context_t* gl)
+EGLBoolean egl_window_surface_v2_t::bindReadSurface(ogles_context_t* gl)
 {
     GGLSurface buffer;
     buffer.version = sizeof(GGLSurface);
-    buffer.width   = nativeWindow->width;
-    buffer.height  = nativeWindow->height;
-    buffer.stride  = nativeWindow->stride;
-    buffer.data    = (GGLubyte*)nativeWindow->base + nativeWindow->offset;
-    buffer.format  = nativeWindow->format;
+    buffer.width   = this->buffer->width;
+    buffer.height  = this->buffer->height;
+    buffer.stride  = this->buffer->stride;
+    buffer.data    = (GGLubyte*)bits; // FIXME: hopefully is is LOCKED!!!
+    buffer.format  = this->buffer->format;
     gl->rasterizer.procs.readBuffer(gl, &buffer);
     return EGL_TRUE;
 }
-void* egl_window_surface_t::getBits() const {
-    return (GGLubyte*)nativeWindow->base + nativeWindow->offset;
-}
-EGLint egl_window_surface_t::getHorizontalResolution() const {
+EGLint egl_window_surface_v2_t::getHorizontalResolution() const {
     return (nativeWindow->xdpi * EGL_DISPLAY_SCALING) * (1.0f / 25.4f);
 }
-EGLint egl_window_surface_t::getVerticalResolution() const {
+EGLint egl_window_surface_v2_t::getVerticalResolution() const {
     return (nativeWindow->ydpi * EGL_DISPLAY_SCALING) * (1.0f / 25.4f);
 }
-EGLint egl_window_surface_t::getRefreshRate() const {
-    return (nativeWindow->fps * EGL_DISPLAY_SCALING);
+EGLint egl_window_surface_v2_t::getRefreshRate() const {
+    return (60 * EGL_DISPLAY_SCALING); // FIXME
 }
-EGLint egl_window_surface_t::getSwapBehavior() const {
-    uint32_t flags = nativeWindow->flags;
-    if (flags & EGL_NATIVES_FLAG_DESTROY_BACKBUFFER)
-        return EGL_BUFFER_DESTROYED;
-    return EGL_BUFFER_PRESERVED;
+EGLint egl_window_surface_v2_t::getSwapBehavior() const 
+{
+    /*
+     * EGL_BUFFER_PRESERVED means that eglSwapBuffers() completely preserves
+     * the content of the swapped buffer.
+     * 
+     * EGL_BUFFER_DESTROYED means that the content of the buffer is lost.
+     * 
+     * However when ANDROID_swap_retcangle is supported, EGL_BUFFER_DESTROYED
+     * only applies to the area specified by eglSetSwapRectangleANDROID(), that
+     * is, everything outside of this area is preserved.
+     * 
+     * This implementation of EGL assumes the later case.
+     * 
+     */
+
+    return EGL_BUFFER_DESTROYED;
 }
 
 // ----------------------------------------------------------------------------
@@ -311,12 +723,11 @@
 
     virtual ~egl_pixmap_surface_t() { }
 
-    virtual     bool        isValid() const { return nativePixmap.version == sizeof(egl_native_pixmap_t); }    
+    virtual     bool        initCheck() const { return !depth.format || depth.data!=0; } 
     virtual     EGLBoolean  bindDrawSurface(ogles_context_t* gl);
     virtual     EGLBoolean  bindReadSurface(ogles_context_t* gl);
     virtual     EGLint      getWidth() const    { return nativePixmap.width;  }
     virtual     EGLint      getHeight() const   { return nativePixmap.height; }
-    virtual     void*       getBits() const     { return nativePixmap.data; }
 private:
     egl_native_pixmap_t     nativePixmap;
 };
@@ -334,7 +745,6 @@
         depth.data    = (GGLubyte*)malloc(depth.stride*depth.height*2);
         if (depth.data == 0) {
             setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
-            return;
         }
     }
 }
@@ -347,7 +757,7 @@
     buffer.stride  = nativePixmap.stride;
     buffer.data    = nativePixmap.data;
     buffer.format  = nativePixmap.format;
-    
+
     gl->rasterizer.procs.colorBuffer(gl, &buffer);
     if (depth.data != gl->rasterizer.state.buffers.depth.data)
         gl->rasterizer.procs.depthBuffer(gl, &depth);
@@ -376,12 +786,11 @@
 
     virtual ~egl_pbuffer_surface_t();
 
-    virtual     bool        isValid() const { return pbuffer.data != 0; }    
+    virtual     bool        initCheck() const   { return pbuffer.data != 0; }
     virtual     EGLBoolean  bindDrawSurface(ogles_context_t* gl);
     virtual     EGLBoolean  bindReadSurface(ogles_context_t* gl);
     virtual     EGLint      getWidth() const    { return pbuffer.width;  }
     virtual     EGLint      getHeight() const   { return pbuffer.height; }
-    virtual     void*       getBits() const     { return pbuffer.data; }
 private:
     GGLSurface  pbuffer;
 };
@@ -396,6 +805,7 @@
         case GGL_PIXEL_FORMAT_A_8:          size *= 1; break;
         case GGL_PIXEL_FORMAT_RGB_565:      size *= 2; break;
         case GGL_PIXEL_FORMAT_RGBA_8888:    size *= 4; break;
+        case GGL_PIXEL_FORMAT_RGBX_8888:    size *= 4; break;
         default:
             LOGE("incompatible pixel format for pbuffer (format=%d)", f);
             pbuffer.data = 0;
@@ -407,7 +817,7 @@
     pbuffer.stride  = w;
     pbuffer.data    = (GGLubyte*)malloc(size);
     pbuffer.format  = f;
-    
+
     if (depthFormat) {
         depth.width   = pbuffer.width;
         depth.height  = pbuffer.height;
@@ -468,7 +878,13 @@
 static char const * const gVendorString     = "Google Inc.";
 static char const * const gVersionString    = "1.2 Android Driver";
 static char const * const gClientApiString  = "OpenGL ES";
-static char const * const gExtensionsString = "";
+static char const * const gExtensionsString =
+        "EGL_KHR_image_base "
+        // "KHR_image_pixmap "
+        "EGL_ANDROID_image_native_buffer "
+        "EGL_ANDROID_swap_rectangle "
+        "EGL_ANDROID_get_render_buffer "
+        ;
 
 // ----------------------------------------------------------------------------
 
@@ -496,6 +912,10 @@
             (__eglMustCastToProperFunctionPointerType)&glDrawTexxvOES },
     { "glQueryMatrixxOES",
             (__eglMustCastToProperFunctionPointerType)&glQueryMatrixxOES },
+    { "glEGLImageTargetTexture2DOES",
+            (__eglMustCastToProperFunctionPointerType)&glEGLImageTargetTexture2DOES },
+    { "glEGLImageTargetRenderbufferStorageOES",
+            (__eglMustCastToProperFunctionPointerType)&glEGLImageTargetRenderbufferStorageOES },
     { "glClipPlanef",
             (__eglMustCastToProperFunctionPointerType)&glClipPlanef },
     { "glClipPlanex",
@@ -510,9 +930,17 @@
             (__eglMustCastToProperFunctionPointerType)&glDeleteBuffers },
     { "glGenBuffers",
             (__eglMustCastToProperFunctionPointerType)&glGenBuffers },
+    { "eglCreateImageKHR",  
+            (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR }, 
+    { "eglDestroyImageKHR", 
+            (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR }, 
+    { "eglSetSwapRectangleANDROID", 
+            (__eglMustCastToProperFunctionPointerType)&eglSetSwapRectangleANDROID }, 
+    { "eglGetRenderBufferANDROID", 
+            (__eglMustCastToProperFunctionPointerType)&eglGetRenderBufferANDROID }, 
 };
 
-/* 
+/*
  * In the lists below, attributes names MUST be sorted.
  * Additionally, all configs must be sorted according to
  * the EGL specification.
@@ -523,7 +951,7 @@
         { EGL_CONFIG_CAVEAT,              EGL_SLOW_CONFIG                   },
         { EGL_LEVEL,                      0                                 },
         { EGL_MAX_PBUFFER_HEIGHT,         GGL_MAX_VIEWPORT_DIMS             },
-        { EGL_MAX_PBUFFER_PIXELS,         
+        { EGL_MAX_PBUFFER_PIXELS,
                 GGL_MAX_VIEWPORT_DIMS*GGL_MAX_VIEWPORT_DIMS                 },
         { EGL_MAX_PBUFFER_WIDTH,          GGL_MAX_VIEWPORT_DIMS             },
         { EGL_NATIVE_RENDERABLE,          EGL_TRUE                          },
@@ -538,12 +966,18 @@
         { EGL_BIND_TO_TEXTURE_RGBA,       EGL_FALSE                         },
         { EGL_BIND_TO_TEXTURE_RGB,        EGL_FALSE                         },
         { EGL_MIN_SWAP_INTERVAL,          1                                 },
-        { EGL_MAX_SWAP_INTERVAL,          4                                 },
+        { EGL_MAX_SWAP_INTERVAL,          1                                 },
+        { EGL_LUMINANCE_SIZE,             0                                 },
+        { EGL_ALPHA_MASK_SIZE,            0                                 },
+        { EGL_COLOR_BUFFER_TYPE,          EGL_RGB_BUFFER                    },
+        { EGL_RENDERABLE_TYPE,            EGL_OPENGL_ES_BIT                 },
+        { EGL_CONFORMANT,                 0                                 }
 };
 
 // These configs can override the base attribute list
 // NOTE: when adding a config here, don't forget to update eglCreate*Surface()
 
+// 565 configs
 static config_pair_t const config_0_attribute_list[] = {
         { EGL_BUFFER_SIZE,     16 },
         { EGL_ALPHA_SIZE,       0 },
@@ -566,8 +1000,32 @@
         { EGL_SURFACE_TYPE,     EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
 };
 
+// RGB 888 configs
 static config_pair_t const config_2_attribute_list[] = {
         { EGL_BUFFER_SIZE,     32 },
+        { EGL_ALPHA_SIZE,       0 },
+        { EGL_BLUE_SIZE,        8 },
+        { EGL_GREEN_SIZE,       8 },
+        { EGL_RED_SIZE,         8 },
+        { EGL_DEPTH_SIZE,       0 },
+        { EGL_CONFIG_ID,        6 },
+        { EGL_SURFACE_TYPE,     EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
+};
+
+static config_pair_t const config_3_attribute_list[] = {
+        { EGL_BUFFER_SIZE,     32 },
+        { EGL_ALPHA_SIZE,       0 },
+        { EGL_BLUE_SIZE,        8 },
+        { EGL_GREEN_SIZE,       8 },
+        { EGL_RED_SIZE,         8 },
+        { EGL_DEPTH_SIZE,      16 },
+        { EGL_CONFIG_ID,        7 },
+        { EGL_SURFACE_TYPE,     EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
+};
+
+// 8888 configs
+static config_pair_t const config_4_attribute_list[] = {
+        { EGL_BUFFER_SIZE,     32 },
         { EGL_ALPHA_SIZE,       8 },
         { EGL_BLUE_SIZE,        8 },
         { EGL_GREEN_SIZE,       8 },
@@ -577,7 +1035,7 @@
         { EGL_SURFACE_TYPE,     EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
 };
 
-static config_pair_t const config_3_attribute_list[] = {
+static config_pair_t const config_5_attribute_list[] = {
         { EGL_BUFFER_SIZE,     32 },
         { EGL_ALPHA_SIZE,       8 },
         { EGL_BLUE_SIZE,        8 },
@@ -588,7 +1046,8 @@
         { EGL_SURFACE_TYPE,     EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
 };
 
-static config_pair_t const config_4_attribute_list[] = {
+// A8 configs
+static config_pair_t const config_6_attribute_list[] = {
         { EGL_BUFFER_SIZE,      8 },
         { EGL_ALPHA_SIZE,       8 },
         { EGL_BLUE_SIZE,        0 },
@@ -599,7 +1058,7 @@
         { EGL_SURFACE_TYPE,     EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
 };
 
-static config_pair_t const config_5_attribute_list[] = {
+static config_pair_t const config_7_attribute_list[] = {
         { EGL_BUFFER_SIZE,      8 },
         { EGL_ALPHA_SIZE,       8 },
         { EGL_BLUE_SIZE,        0 },
@@ -617,6 +1076,8 @@
         { config_3_attribute_list, NELEM(config_3_attribute_list) },
         { config_4_attribute_list, NELEM(config_4_attribute_list) },
         { config_5_attribute_list, NELEM(config_5_attribute_list) },
+        { config_6_attribute_list, NELEM(config_6_attribute_list) },
+        { config_7_attribute_list, NELEM(config_7_attribute_list) },
 };
 
 static config_management_t const gConfigManagement[] = {
@@ -647,22 +1108,74 @@
         { EGL_BIND_TO_TEXTURE_RGB,        config_management_t::exact   },
         { EGL_MIN_SWAP_INTERVAL,          config_management_t::exact   },
         { EGL_MAX_SWAP_INTERVAL,          config_management_t::exact   },
+        { EGL_LUMINANCE_SIZE,             config_management_t::atLeast },
+        { EGL_ALPHA_MASK_SIZE,            config_management_t::atLeast },
+        { EGL_COLOR_BUFFER_TYPE,          config_management_t::exact   },
+        { EGL_RENDERABLE_TYPE,            config_management_t::mask    },
+        { EGL_CONFORMANT,                 config_management_t::mask    }
 };
 
+
 static config_pair_t const config_defaults[] = {
-        { EGL_SURFACE_TYPE,        EGL_WINDOW_BIT },
+    // attributes that are not specified are simply ignored, if a particular
+    // one needs not be ignored, it must be specified here, eg:
+    // { EGL_SURFACE_TYPE, EGL_WINDOW_BIT },
 };
 
 // ----------------------------------------------------------------------------
 
+static status_t getConfigFormatInfo(EGLint configID,
+        int32_t& pixelFormat, int32_t& depthFormat)
+{
+    switch(configID) {
+    case 0:
+        pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
+        depthFormat = 0;
+        break;
+    case 1:
+        pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
+        depthFormat = GGL_PIXEL_FORMAT_Z_16;
+        break;
+    case 2:
+        pixelFormat = GGL_PIXEL_FORMAT_RGBX_8888;
+        depthFormat = 0;
+        break;
+    case 3:
+        pixelFormat = GGL_PIXEL_FORMAT_RGBX_8888;
+        depthFormat = GGL_PIXEL_FORMAT_Z_16;
+        break;
+    case 4:
+        pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
+        depthFormat = 0;
+        break;
+    case 5:
+        pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
+        depthFormat = GGL_PIXEL_FORMAT_Z_16;
+        break;
+    case 6:
+        pixelFormat = GGL_PIXEL_FORMAT_A_8;
+        depthFormat = 0;
+        break;
+    case 7:
+        pixelFormat = GGL_PIXEL_FORMAT_A_8;
+        depthFormat = GGL_PIXEL_FORMAT_Z_16;
+        break;
+    default:
+        return NAME_NOT_FOUND;
+    }
+    return NO_ERROR;
+}
+
+// ----------------------------------------------------------------------------
+
 template<typename T>
 static int binarySearch(T const sortedArray[], int first, int last, EGLint key)
 {
    while (first <= last) {
        int mid = (first + last) / 2;
-       if (key > sortedArray[mid].key) { 
+       if (key > sortedArray[mid].key) {
            first = mid + 1;
-       } else if (key < sortedArray[mid].key) { 
+       } else if (key < sortedArray[mid].key) {
            last = mid - 1;
        } else {
            return mid;
@@ -674,13 +1187,13 @@
 static int isAttributeMatching(int i, EGLint attr, EGLint val)
 {
     // look for the attribute in all of our configs
-    config_pair_t const* configFound = gConfigs[i].array; 
+    config_pair_t const* configFound = gConfigs[i].array;
     int index = binarySearch<config_pair_t>(
             gConfigs[i].array,
             0, gConfigs[i].size-1,
             attr);
     if (index < 0) {
-        configFound = config_base_attribute_list; 
+        configFound = config_base_attribute_list;
         index = binarySearch<config_pair_t>(
                 config_base_attribute_list,
                 0, NELEM(config_base_attribute_list)-1,
@@ -787,38 +1300,18 @@
     if (!(surfaceType & EGL_WINDOW_BIT))
         return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
 
+    if (static_cast<android_native_window_t*>(window)->common.magic !=
+            ANDROID_NATIVE_WINDOW_MAGIC) {
+        return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
+    }
+        
     EGLint configID;
     if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE)
         return EGL_FALSE;
 
     int32_t depthFormat;
     int32_t pixelFormat;
-    switch(configID) {
-    case 0: 
-        pixelFormat = GGL_PIXEL_FORMAT_RGB_565; 
-        depthFormat = 0;
-        break;
-    case 1:
-        pixelFormat = GGL_PIXEL_FORMAT_RGB_565; 
-        depthFormat = GGL_PIXEL_FORMAT_Z_16;
-        break;
-    case 2:
-        pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; 
-        depthFormat = 0;
-        break;
-    case 3:
-        pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; 
-        depthFormat = GGL_PIXEL_FORMAT_Z_16;
-        break;
-    case 4:
-        pixelFormat = GGL_PIXEL_FORMAT_A_8; 
-        depthFormat = 0;
-        break;
-    case 5:
-        pixelFormat = GGL_PIXEL_FORMAT_A_8; 
-        depthFormat = GGL_PIXEL_FORMAT_Z_16;
-        break;
-    default:
+    if (getConfigFormatInfo(configID, pixelFormat, depthFormat) != NO_ERROR) {
         return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
     }
 
@@ -828,11 +1321,11 @@
     //if (EGLint(info.format) != pixelFormat)
     //    return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
 
-    egl_surface_t* surface =
-        new egl_window_surface_t(dpy, config, depthFormat,
-                static_cast<egl_native_window_t*>(window));
+    egl_surface_t* surface;
+    surface = new egl_window_surface_v2_t(dpy, config, depthFormat,
+            static_cast<android_native_window_t*>(window));
 
-    if (!surface->isValid()) {
+    if (!surface->initCheck()) {
         // there was a problem in the ctor, the error
         // flag has been set.
         delete surface;
@@ -856,38 +1349,18 @@
     if (!(surfaceType & EGL_PIXMAP_BIT))
         return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
 
+    if (static_cast<egl_native_pixmap_t*>(pixmap)->version != 
+            sizeof(egl_native_pixmap_t)) {
+        return setError(EGL_BAD_NATIVE_PIXMAP, EGL_NO_SURFACE);
+    }
+    
     EGLint configID;
     if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE)
         return EGL_FALSE;
 
     int32_t depthFormat;
     int32_t pixelFormat;
-    switch(configID) {
-    case 0: 
-        pixelFormat = GGL_PIXEL_FORMAT_RGB_565; 
-        depthFormat = 0;
-        break;
-    case 1:
-        pixelFormat = GGL_PIXEL_FORMAT_RGB_565; 
-        depthFormat = GGL_PIXEL_FORMAT_Z_16;
-        break;
-    case 2:
-        pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; 
-        depthFormat = 0;
-        break;
-    case 3:
-        pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; 
-        depthFormat = GGL_PIXEL_FORMAT_Z_16;
-        break;
-    case 4:
-        pixelFormat = GGL_PIXEL_FORMAT_A_8; 
-        depthFormat = 0;
-        break;
-    case 5:
-        pixelFormat = GGL_PIXEL_FORMAT_A_8; 
-        depthFormat = GGL_PIXEL_FORMAT_Z_16;
-        break;
-    default:
+    if (getConfigFormatInfo(configID, pixelFormat, depthFormat) != NO_ERROR) {
         return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
     }
 
@@ -898,7 +1371,7 @@
         new egl_pixmap_surface_t(dpy, config, depthFormat,
                 static_cast<egl_native_pixmap_t*>(pixmap));
 
-    if (!surface->isValid()) {
+    if (!surface->initCheck()) {
         // there was a problem in the ctor, the error
         // flag has been set.
         delete surface;
@@ -916,42 +1389,17 @@
     EGLint surfaceType;
     if (getConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE)
         return EGL_FALSE;
-    
+
     if (!(surfaceType & EGL_PBUFFER_BIT))
         return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
-        
+
     EGLint configID;
     if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE)
         return EGL_FALSE;
 
     int32_t depthFormat;
     int32_t pixelFormat;
-    switch(configID) {
-    case 0: 
-        pixelFormat = GGL_PIXEL_FORMAT_RGB_565; 
-        depthFormat = 0;
-        break;
-    case 1:
-        pixelFormat = GGL_PIXEL_FORMAT_RGB_565; 
-        depthFormat = GGL_PIXEL_FORMAT_Z_16;
-        break;
-    case 2:
-        pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; 
-        depthFormat = 0;
-        break;
-    case 3:
-        pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; 
-        depthFormat = GGL_PIXEL_FORMAT_Z_16;
-        break;
-    case 4:
-        pixelFormat = GGL_PIXEL_FORMAT_A_8; 
-        depthFormat = 0;
-        break;
-    case 5:
-        pixelFormat = GGL_PIXEL_FORMAT_A_8; 
-        depthFormat = GGL_PIXEL_FORMAT_Z_16;
-        break;
-    default:
+    if (getConfigFormatInfo(configID, pixelFormat, depthFormat) != NO_ERROR) {
         return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
     }
 
@@ -966,7 +1414,7 @@
     egl_surface_t* surface =
         new egl_pbuffer_surface_t(dpy, config, depthFormat, w, h, pixelFormat);
 
-    if (!surface->isValid()) {
+    if (!surface->initCheck()) {
         // there was a problem in the ctor, the error
         // flag has been set.
         delete surface;
@@ -1001,7 +1449,7 @@
         egl_display_t& d = egl_display_t::get_display(dpy);
         d.type = display;
         return dpy;
-    }    
+    }
     return EGL_NO_DISPLAY;
 }
 
@@ -1009,10 +1457,10 @@
 {
     if (egl_display_t::is_valid(dpy) == EGL_FALSE)
         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
-    
+
     EGLBoolean res = EGL_TRUE;
     egl_display_t& d = egl_display_t::get_display(dpy);
-    
+
     if (android_atomic_inc(&d.initialized) == 0) {
         // initialize stuff here if needed
         //pthread_mutex_lock(&gInitMutex);
@@ -1080,7 +1528,7 @@
         *num_config = 0;
         return EGL_TRUE;
     }
-    
+
     int numAttributes = 0;
     int numConfigs =  NELEM(gConfigs);
     uint32_t possibleMatch = (1<<numConfigs)-1;
@@ -1088,7 +1536,7 @@
         numAttributes++;
         EGLint attr = *attrib_list++;
         EGLint val  = *attrib_list++;
-        for (int i=0 ; i<numConfigs ; i++) {
+        for (int i=0 ; possibleMatch && i<numConfigs ; i++) {
             if (!(possibleMatch & (1<<i)))
                 continue;
             if (isAttributeMatching(i, attr, val) == 0) {
@@ -1098,15 +1546,15 @@
     }
 
     // now, handle the attributes which have a useful default value
-    for (size_t j=0 ; j<NELEM(config_defaults) ; j++) {
-        // see if this attribute was specified, if not apply its
+    for (size_t j=0 ; possibleMatch && j<NELEM(config_defaults) ; j++) {
+        // see if this attribute was specified, if not, apply its
         // default value
         if (binarySearch<config_pair_t>(
                 (config_pair_t const*)attrib_list,
                 0, numAttributes-1,
                 config_defaults[j].key) < 0)
         {
-            for (int i=0 ; i<numConfigs ; i++) {
+            for (int i=0 ; possibleMatch && i<numConfigs ; i++) {
                 if (!(possibleMatch & (1<<i)))
                     continue;
                 if (isAttributeMatching(i,
@@ -1161,7 +1609,7 @@
 {
     return createWindowSurface(dpy, config, window, attrib_list);
 }
-    
+
 EGLSurface eglCreatePixmapSurface(  EGLDisplay dpy, EGLConfig config,
                                     NativePixmapType pixmap,
                                     const EGLint *attrib_list)
@@ -1174,17 +1622,22 @@
 {
     return createPbufferSurface(dpy, config, attrib_list);
 }
-                                    
+
 EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface eglSurface)
 {
     if (egl_display_t::is_valid(dpy) == EGL_FALSE)
         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
     if (eglSurface != EGL_NO_SURFACE) {
         egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) );
-        if (surface->magic != egl_surface_t::MAGIC)
+        if (!surface->isValid())
             return setError(EGL_BAD_SURFACE, EGL_FALSE);
         if (surface->dpy != dpy)
             return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+        if (surface->ctx) {
+            // FIXME: this surface is current check what the spec says
+            surface->disconnect();
+            surface->ctx = 0;
+        }
         delete surface;
     }
     return EGL_TRUE;
@@ -1196,6 +1649,8 @@
     if (egl_display_t::is_valid(dpy) == EGL_FALSE)
         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
     egl_surface_t* surface = static_cast<egl_surface_t*>(eglSurface);
+    if (!surface->isValid())
+        return setError(EGL_BAD_SURFACE, EGL_FALSE);
     if (surface->dpy != dpy)
         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
 
@@ -1244,7 +1699,7 @@
             *value = (wr * EGL_DISPLAY_SCALING) / hr;
         } break;
         case EGL_SWAP_BEHAVIOR:
-            *value = surface->getSwapBehavior(); 
+            *value = surface->getSwapBehavior();
             break;
         default:
             ret = setError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
@@ -1288,13 +1743,23 @@
         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
     if (draw) {
         egl_surface_t* s = (egl_surface_t*)draw;
+        if (!s->isValid())
+            return setError(EGL_BAD_SURFACE, EGL_FALSE);
         if (s->dpy != dpy)
             return setError(EGL_BAD_DISPLAY, EGL_FALSE);
-        // TODO: check that draw and read are compatible with the context
+        // TODO: check that draw is compatible with the context
+    }
+    if (read && read!=draw) {
+        egl_surface_t* s = (egl_surface_t*)read;
+        if (!s->isValid())
+            return setError(EGL_BAD_SURFACE, EGL_FALSE);
+        if (s->dpy != dpy)
+            return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+        // TODO: check that read is compatible with the context
     }
 
     EGLContext current_ctx = EGL_NO_CONTEXT;
-    
+
     if ((read == EGL_NO_SURFACE && draw == EGL_NO_SURFACE) && (ctx != EGL_NO_CONTEXT))
         return setError(EGL_BAD_MATCH, EGL_FALSE);
 
@@ -1310,21 +1775,29 @@
         egl_surface_t* r = (egl_surface_t*)read;
         if ((d && d->ctx && d->ctx != ctx) ||
             (r && r->ctx && r->ctx != ctx)) {
-            // once of the surface is bound to a context in another thread
+            // one of the surface is bound to a context in another thread
             return setError(EGL_BAD_ACCESS, EGL_FALSE);
         }
     }
 
-    // TODO: call connect / disconnect on the surface
-
     ogles_context_t* gl = (ogles_context_t*)ctx;
     if (makeCurrent(gl) == 0) {
         if (ctx) {
             egl_context_t* c = egl_context_t::context(ctx);
             egl_surface_t* d = (egl_surface_t*)draw;
             egl_surface_t* r = (egl_surface_t*)read;
-            c->read = read;
+            
+            if (c->draw) {
+                egl_surface_t* s = reinterpret_cast<egl_surface_t*>(c->draw);
+                s->disconnect();
+            }
+            if (c->read) {
+                // FIXME: unlock/disconnect the read surface too 
+            }
+            
             c->draw = draw;
+            c->read = read;
+
             if (c->flags & egl_context_t::NEVER_CURRENT) {
                 c->flags &= ~egl_context_t::NEVER_CURRENT;
                 GLint w = 0;
@@ -1338,10 +1811,14 @@
                 ogles_scissor(gl, 0, 0, w, h);
             }
             if (d) {
+                if (d->connect() == EGL_FALSE) {
+                    return EGL_FALSE;
+                }
                 d->ctx = ctx;
                 d->bindDrawSurface(gl);
             }
             if (r) {
+                // FIXME: lock/connect the read surface too 
                 r->ctx = ctx;
                 r->bindReadSurface(gl);
             }
@@ -1352,8 +1829,16 @@
                 egl_context_t* c = egl_context_t::context(current_ctx);
                 egl_surface_t* d = (egl_surface_t*)c->draw;
                 egl_surface_t* r = (egl_surface_t*)c->read;
-                if (d) d->ctx = EGL_NO_CONTEXT;
-                if (r) r->ctx = EGL_NO_CONTEXT;
+                if (d) {
+                    c->draw = 0;
+                    d->ctx = EGL_NO_CONTEXT;
+                    d->disconnect();
+                }
+                if (r) {
+                    c->read = 0;
+                    r->ctx = EGL_NO_CONTEXT;
+                    // FIXME: unlock/disconnect the read surface too 
+                }
             }
         }
         return EGL_TRUE;
@@ -1425,8 +1910,10 @@
 {
     if (egl_display_t::is_valid(dpy) == EGL_FALSE)
         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
-    
+
     egl_surface_t* d = static_cast<egl_surface_t*>(draw);
+    if (!d->isValid())
+        return setError(EGL_BAD_SURFACE, EGL_FALSE);
     if (d->dpy != dpy)
         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
 
@@ -1558,7 +2045,7 @@
 }
 
 // ----------------------------------------------------------------------------
-// Android extensions
+// EGL_EGLEXT_VERSION 3
 // ----------------------------------------------------------------------------
 
 void (*eglGetProcAddress (const char *procname))()
@@ -1571,3 +2058,97 @@
     }
     return NULL;
 }
+
+EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
+        const EGLint *attrib_list)
+{
+    EGLBoolean result = EGL_FALSE;
+    return result;
+}
+
+EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
+{
+    EGLBoolean result = EGL_FALSE;
+    return result;
+}
+
+EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
+        EGLClientBuffer buffer, const EGLint *attrib_list)
+{
+    if (egl_display_t::is_valid(dpy) == EGL_FALSE) {
+        return setError(EGL_BAD_DISPLAY, EGL_NO_IMAGE_KHR);
+    }
+    if (ctx != EGL_NO_CONTEXT) {
+        return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
+    }
+    if (target != EGL_NATIVE_BUFFER_ANDROID) {
+        return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
+    }
+
+    android_native_buffer_t* native_buffer = (android_native_buffer_t*)buffer;
+
+    if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
+        return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
+
+    if (native_buffer->common.version != sizeof(android_native_buffer_t))
+        return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
+    
+    native_buffer->common.incRef(&native_buffer->common);
+    return (EGLImageKHR)native_buffer;
+}
+
+EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
+{
+    if (egl_display_t::is_valid(dpy) == EGL_FALSE) {
+        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+    }
+
+    android_native_buffer_t* native_buffer = (android_native_buffer_t*)img;
+
+    if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
+        return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+
+    if (native_buffer->common.version != sizeof(android_native_buffer_t))
+        return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+
+    native_buffer->common.decRef(&native_buffer->common);
+
+    return EGL_TRUE;
+}
+
+// ----------------------------------------------------------------------------
+// ANDROID extensions
+// ----------------------------------------------------------------------------
+
+EGLBoolean eglSetSwapRectangleANDROID(EGLDisplay dpy, EGLSurface draw,
+        EGLint left, EGLint top, EGLint width, EGLint height)
+{
+    if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+
+    egl_surface_t* d = static_cast<egl_surface_t*>(draw);
+    if (!d->isValid())
+        return setError(EGL_BAD_SURFACE, EGL_FALSE);
+    if (d->dpy != dpy)
+        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+
+    // post the surface
+    d->setSwapRectangle(left, top, width, height);
+
+    return EGL_TRUE;
+}
+
+EGLClientBuffer eglGetRenderBufferANDROID(EGLDisplay dpy, EGLSurface draw)
+{
+    if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+        return setError(EGL_BAD_DISPLAY, (EGLClientBuffer)0);
+
+    egl_surface_t* d = static_cast<egl_surface_t*>(draw);
+    if (!d->isValid())
+        return setError(EGL_BAD_SURFACE, (EGLClientBuffer)0);
+    if (d->dpy != dpy)
+        return setError(EGL_BAD_DISPLAY, (EGLClientBuffer)0);
+
+    // post the surface
+    return d->getRenderBuffer();
+}
diff --git a/opengl/libagl/light.cpp b/opengl/libagl/light.cpp
index 8ae32cc..f211bca 100644
--- a/opengl/libagl/light.cpp
+++ b/opengl/libagl/light.cpp
@@ -216,6 +216,8 @@
 static inline void validate_light_mvi(ogles_context_t* c)
 {
     uint32_t en = c->lighting.enabledLights;
+    // Vector from object to viewer, in eye coordinates
+    const vec4_t eyeViewer = { 0, 0, 0x1000, 0 };
     while (en) {
         const int i = 31 - gglClz(en);
         en &= ~(1<<i);
@@ -223,6 +225,9 @@
         c->transforms.mvui.point4(&c->transforms.mvui,
                 &l.objPosition, &l.position);
         vnorm3(l.normalizedObjPosition.v, l.objPosition.v);
+        c->transforms.mvui.point4(&c->transforms.mvui,
+                &l.objViewer, &eyeViewer);
+        vnorm3(l.objViewer.v, l.objViewer.v);
     }
 }
 
@@ -379,9 +384,9 @@
             // specular
             if (ggl_unlikely(s && l.implicitSpecular.v[3])) {
                 vec4_t h;
-                h.x = d.x;
-                h.y = d.y;
-                h.z = d.z + 0x10000;
+                h.x = d.x + l.objViewer.x;
+                h.y = d.y + l.objViewer.y;
+                h.z = d.z + l.objViewer.z;
                 vnorm3(h.v, h.v);
                 s = dot3(n.v, h.v);
                 s = (s<0) ? (twoSide?(-s):0) : s;
diff --git a/opengl/libagl/matrix.cpp b/opengl/libagl/matrix.cpp
index 0b68dc0..3c50977 100644
--- a/opengl/libagl/matrix.cpp
+++ b/opengl/libagl/matrix.cpp
@@ -696,6 +696,8 @@
     f[2] = 0;   f[6] = 0;   f[10] = A;  f[14] = B;
     f[3] = 0;   f[7] = 0;   f[11] = 0;  f[15] = 1;
     c->transforms.dirty |= transform_state_t::VIEWPORT;
+    if (c->transforms.mvp4.flags & transform_t::FLAGS_2D_PROJECTION)
+        c->transforms.dirty |= transform_state_t::MVP;
 }
 
 // ----------------------------------------------------------------------------
@@ -739,20 +741,19 @@
 
 void point4__mvui(transform_t const* mx, vec4_t* lhs, vec4_t const* rhs) {
     // this used for transforming light positions back to object space.
-    // Lights have 3 components positions, so w is always 1.
-    // however, it is used as a switch for directional lights, so we need
+    // w is used as a switch for directional lights, so we need
     // to preserve it.
     const GLfixed* const m = mx->matrix.m;
     const GLfixed rx = rhs->x;
     const GLfixed ry = rhs->y;
     const GLfixed rz = rhs->z;
-    lhs->x = mla3a(rx, m[ 0], ry, m[ 4], rz, m[ 8], m[12]); 
-    lhs->y = mla3a(rx, m[ 1], ry, m[ 5], rz, m[ 9], m[13]);
-    lhs->z = mla3a(rx, m[ 2], ry, m[ 6], rz, m[10], m[14]);
-    lhs->w = rhs->w;
+    const GLfixed rw = rhs->w;
+    lhs->x = mla4(rx, m[ 0], ry, m[ 4], rz, m[ 8], rw, m[12]);
+    lhs->y = mla4(rx, m[ 1], ry, m[ 5], rz, m[ 9], rw, m[13]);
+    lhs->z = mla4(rx, m[ 2], ry, m[ 6], rz, m[10], rw, m[14]);
+    lhs->w = rw;
 }
 
-
 void point2__nop(transform_t const*, vec4_t* lhs, vec4_t const* rhs) {
     lhs->z = 0;
     lhs->w = 0x10000;
diff --git a/opengl/libagl/primitives.cpp b/opengl/libagl/primitives.cpp
index f164c02..769ec40 100644
--- a/opengl/libagl/primitives.cpp
+++ b/opengl/libagl/primitives.cpp
@@ -369,7 +369,7 @@
         int32_t c0, int32_t c1, int32_t c2) const
 {
     int64_t it64[3];
-    iterators0032(it, c0, c1, c2);
+    iterators0032(it64, c0, c1, c2);
     it[0] = it64[0];
     it[1] = it64[1];
     it[2] = it64[2];
diff --git a/opengl/libagl/state.cpp b/opengl/libagl/state.cpp
index 5cbabea..a59b3b0 100644
--- a/opengl/libagl/state.cpp
+++ b/opengl/libagl/state.cpp
@@ -2,16 +2,16 @@
 **
 ** Copyright 2006, 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 
+** 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 
+**     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 
+** 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.
 */
 
@@ -28,12 +28,16 @@
 #include "BufferObjectManager.h"
 #include "TextureObjectManager.h"
 
+#ifdef LIBAGL_USE_GRALLOC_COPYBITS
+#include <hardware/copybit.h>
+#endif // LIBAGL_USE_GRALLOC_COPYBITS
+
 namespace android {
 
 // ----------------------------------------------------------------------------
 
 static char const * const gVendorString     = "Android";
-static char const * const gRendererString   = "Android PixelFlinger 1.0";
+static char const * const gRendererString   = "Android PixelFlinger 1.1";
 static char const * const gVersionString    = "OpenGL ES-CM 1.0";
 static char const * const gExtensionsString =
     "GL_OES_byte_coordinates "              // OK
@@ -46,9 +50,9 @@
     "GL_OES_query_matrix "                  // OK
     //        "GL_OES_point_size_array "              // TODO
     //        "GL_OES_point_sprite "                  // TODO
+    "GL_OES_EGL_image "                     // OK
     "GL_ARB_texture_compression "           // OK
     "GL_ARB_texture_non_power_of_two "      // OK
-    "GL_ANDROID_direct_texture "            // OK
     "GL_ANDROID_user_clip_plane "           // OK
     "GL_ANDROID_vertex_buffer_object "      // OK
     "GL_ANDROID_generate_mipmap "           // OK
@@ -62,13 +66,13 @@
 ogles_context_t *ogles_init(size_t extra)
 {
     void* const base = malloc(extra + sizeof(ogles_context_t) + 32);
-	if (!base) return 0;
+    if (!base) return 0;
 
     ogles_context_t *c =
             (ogles_context_t *)((ptrdiff_t(base) + extra + 31) & ~0x1FL);
     memset(c, 0, sizeof(ogles_context_t));
     ggl_init_context(&(c->rasterizer));
-    
+
     // XXX: this should be passed as an argument
     sp<EGLSurfaceManager> smgr(new EGLSurfaceManager());
     c->surfaceManager = smgr.get();
@@ -87,13 +91,42 @@
     c->rasterizer.base = base;
     c->point.size = TRI_ONE;
     c->line.width = TRI_ONE;
-            
+
     // in OpenGL, writing to the depth buffer is enabled by default.
     c->rasterizer.procs.depthMask(c, 1);
-    
+
     // OpenGL enables dithering by default
     c->rasterizer.procs.enable(c, GL_DITHER);
 
+    c->copybits.blitEngine = NULL;
+    c->copybits.minScale = 0;
+    c->copybits.maxScale = 0;
+    c->copybits.drawSurfaceBuffer = 0;
+
+#ifdef LIBAGL_USE_GRALLOC_COPYBITS
+    hw_module_t const* module;
+    if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) {
+        struct copybit_device_t* copyBits;
+        if (copybit_open(module, &copyBits) == 0) {
+            c->copybits.blitEngine = copyBits;
+            {
+                int minLim = copyBits->get(copyBits,
+                        COPYBIT_MINIFICATION_LIMIT);
+                if (minLim != -EINVAL && minLim > 0) {
+                    c->copybits.minScale = (1 << 16) / minLim;
+                }
+            }
+            {
+                int magLim = copyBits->get(copyBits,
+                        COPYBIT_MAGNIFICATION_LIMIT);
+                if (magLim != -EINVAL && magLim > 0) {
+                    c->copybits.maxScale = min(32*1024-1, magLim) << 16;
+                }
+            }
+        }
+    }
+#endif // LIBAGL_USE_GRALLOC_COPYBITS
+
     return c;
 }
 
@@ -107,7 +140,12 @@
     c->surfaceManager->decStrong(c);
     c->bufferObjectManager->decStrong(c);
     ggl_uninit_context(&(c->rasterizer));
-	free(c->rasterizer.base);
+    free(c->rasterizer.base);
+#ifdef LIBAGL_USE_GRALLOC_COPYBITS
+    if (c->copybits.blitEngine != NULL) {
+        copybit_close((struct copybit_device_t*) c->copybits.blitEngine);
+    }
+#endif // LIBAGL_USE_GRALLOC_COPYBITS
 }
 
 void _ogles_error(ogles_context_t* c, GLenum error)
@@ -188,7 +226,7 @@
         // these need to fall through into the rasterizer
         c->rasterizer.procs.enableDisable(c, cap, enabled);
         break;
-        
+
     case GL_MULTISAMPLE:
     case GL_SAMPLE_ALPHA_TO_COVERAGE:
     case GL_SAMPLE_ALPHA_TO_ONE:
@@ -281,7 +319,7 @@
     case GL_LINE_SMOOTH_HINT:
         break;
     case GL_POINT_SMOOTH_HINT:
-        c->rasterizer.procs.enableDisable(c, 
+        c->rasterizer.procs.enableDisable(c,
                 GGL_POINT_SMOOTH_NICE, mode==GL_NICEST);
         break;
     case GL_PERSPECTIVE_CORRECTION_HINT:
@@ -323,7 +361,7 @@
         c->error = 0;
         return ret;
     }
-    
+
     if (c->rasterizer.error) {
         const GLenum ret(c->rasterizer.error);
         c->rasterizer.error = 0;
@@ -362,25 +400,25 @@
         int index = c->rasterizer.state.buffers.color.format;
         GGLFormat const * formats = gglGetPixelFormatTable();
         params[0] = formats[index].ah - formats[index].al;
-        break; 
+        break;
         }
     case GL_RED_BITS: {
         int index = c->rasterizer.state.buffers.color.format;
         GGLFormat const * formats = gglGetPixelFormatTable();
         params[0] = formats[index].rh - formats[index].rl;
-        break; 
+        break;
         }
     case GL_GREEN_BITS: {
         int index = c->rasterizer.state.buffers.color.format;
         GGLFormat const * formats = gglGetPixelFormatTable();
         params[0] = formats[index].gh - formats[index].gl;
-        break; 
+        break;
         }
     case GL_BLUE_BITS: {
         int index = c->rasterizer.state.buffers.color.format;
         GGLFormat const * formats = gglGetPixelFormatTable();
         params[0] = formats[index].bh - formats[index].bl;
-        break; 
+        break;
         }
     case GL_COMPRESSED_TEXTURE_FORMATS:
         params[ 0] = GL_PALETTE4_RGB8_OES;
diff --git a/opengl/libagl/texture.cpp b/opengl/libagl/texture.cpp
index 14a910c..13d078e 100644
--- a/opengl/libagl/texture.cpp
+++ b/opengl/libagl/texture.cpp
@@ -2,16 +2,16 @@
 **
 ** Copyright 2006, 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 
+** 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 
+**     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 
+** 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.
 */
 
@@ -23,6 +23,12 @@
 #include "texture.h"
 #include "TextureObjectManager.h"
 
+#include <private/ui/android_natives_priv.h>
+
+#ifdef LIBAGL_USE_GRALLOC_COPYBITS
+#include "copybit.h"
+#endif // LIBAGL_USE_GRALLOC_COPYBITS
+
 namespace android {
 
 // ----------------------------------------------------------------------------
@@ -48,7 +54,7 @@
     // each context has a default named (0) texture (not shared)
     c->textures.defaultTexture = new EGLTextureObject();
     c->textures.defaultTexture->incStrong(c);
-    
+
     // bind the default texture to each texture unit
     for (int i=0; i<GGL_TEXTURE_UNIT_COUNT ; i++) {
         bindTextureTmu(c, i, 0, c->textures.defaultTexture);
@@ -96,7 +102,7 @@
     }
 }
 
-void ogles_validate_texture_impl(ogles_context_t* c)
+void ogles_validate_texture(ogles_context_t* c)
 {
     for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) {
         if (c->rasterizer.state.texture[i].enable)
@@ -110,6 +116,66 @@
     c->textures.tmu[tmu].dirty = flags;
 }
 
+/*
+ * If the active textures are EGLImage, they need to be locked before
+ * they can be used.
+ *
+ * FIXME: code below is far from being optimal
+ *
+ */
+
+void ogles_lock_textures(ogles_context_t* c)
+{
+    for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) {
+        if (c->rasterizer.state.texture[i].enable) {
+            texture_unit_t& u(c->textures.tmu[i]);
+            android_native_buffer_t* native_buffer = u.texture->buffer;
+            if (native_buffer) {
+                c->rasterizer.procs.activeTexture(c, i);
+                hw_module_t const* pModule;
+                if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &pModule))
+                    continue;
+
+                gralloc_module_t const* module =
+                    reinterpret_cast<gralloc_module_t const*>(pModule);
+
+                void* vaddr;
+                int err = module->lock(module, native_buffer->handle,
+                        GRALLOC_USAGE_SW_READ_OFTEN,
+                        0, 0, native_buffer->width, native_buffer->height,
+                        &vaddr);
+
+                u.texture->setImageBits(vaddr);
+                c->rasterizer.procs.bindTexture(c, &(u.texture->surface));
+            }
+        }
+    }
+}
+
+void ogles_unlock_textures(ogles_context_t* c)
+{
+    for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) {
+        if (c->rasterizer.state.texture[i].enable) {
+            texture_unit_t& u(c->textures.tmu[i]);
+            android_native_buffer_t* native_buffer = u.texture->buffer;
+            if (native_buffer) {
+                c->rasterizer.procs.activeTexture(c, i);
+                hw_module_t const* pModule;
+                if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &pModule))
+                    continue;
+
+                gralloc_module_t const* module =
+                    reinterpret_cast<gralloc_module_t const*>(pModule);
+
+                module->unlock(module, native_buffer->handle);
+                u.texture->setImageBits(NULL);
+                c->rasterizer.procs.bindTexture(c, &(u.texture->surface));
+            }
+        }
+    }
+    c->rasterizer.procs.activeTexture(c, c->textures.active);
+}
+
 // ----------------------------------------------------------------------------
 #if 0
 #pragma mark -
@@ -255,7 +321,7 @@
         u.texture->decStrong(c);
 
     if (name == 0) {
-        // 0 is our local texture object, not shared with anyone. 
+        // 0 is our local texture object, not shared with anyone.
         // But it affects all bound TMUs immediately.
         // (we need to invalidate all units bound to this texture object)
         tex = c->textures.defaultTexture;
@@ -273,7 +339,7 @@
     u.texture = tex.get();
     u.texture->incStrong(c);
     u.name = name;
-    invalidate_texture(c, active);    
+    invalidate_texture(c, active);
     return tex;
 }
 
@@ -282,7 +348,7 @@
 {
     if (tex.get() == c->textures.tmu[tmu].texture)
         return;
-    
+
     // free the reference to the previously bound object
     texture_unit_t& u(c->textures.tmu[tmu]);
     if (u.texture)
@@ -310,7 +376,7 @@
     if (formatIdx == 0) { // we don't know what to do with this
         return GL_INVALID_OPERATION;
     }
-    
+
     // figure out the size we need as well as the stride
     const GGLFormat& pixelFormat(c->rasterizer.formats[formatIdx]);
     const int32_t align = c->textures.unpackAlignment-1;
@@ -343,6 +409,49 @@
     return 0;
 }
 
+static size_t dataSizePalette4(int numLevels, int width, int height, int format)
+{
+    int indexBits = 8;
+    int entrySize = 0;
+    switch (format) {
+    case GL_PALETTE4_RGB8_OES:
+        indexBits = 4;
+        /* FALLTHROUGH */
+    case GL_PALETTE8_RGB8_OES:
+        entrySize = 3;
+        break;
+
+    case GL_PALETTE4_RGBA8_OES:
+        indexBits = 4;
+        /* FALLTHROUGH */
+    case GL_PALETTE8_RGBA8_OES:
+        entrySize = 4;
+        break;
+
+    case GL_PALETTE4_R5_G6_B5_OES:
+    case GL_PALETTE4_RGBA4_OES:
+    case GL_PALETTE4_RGB5_A1_OES:
+        indexBits = 4;
+        /* FALLTHROUGH */
+    case GL_PALETTE8_R5_G6_B5_OES:
+    case GL_PALETTE8_RGBA4_OES:
+    case GL_PALETTE8_RGB5_A1_OES:
+        entrySize = 2;
+        break;
+    }
+
+    size_t size = (1 << indexBits) * entrySize; // palette size
+
+    for (int i=0 ; i< numLevels ; i++) {
+        int w = (width  >> i) ? : 1;
+        int h = (height >> i) ? : 1;
+        int levelSize = h * ((w * indexBits) / 8) ? : 1;
+        size += levelSize;
+    }
+
+    return size;
+}
+
 static void decodePalette4(const GLvoid *data, int level, int width, int height,
                            void *surface, int stride, int format)
 
@@ -377,6 +486,7 @@
     }
 
     const int paletteSize = (1 << indexBits) * entrySize;
+
     uint8_t const* pixels = (uint8_t *)data + paletteSize;
     for (int i=0 ; i<level ; i++) {
         int w = (width  >> i) ? : 1;
@@ -530,8 +640,8 @@
         ogles_error(c, GL_INVALID_ENUM);
         return;
     }
-    
-    EGLTextureObject* textureObject = c->textures.tmu[c->textures.active].texture;    
+
+    EGLTextureObject* textureObject = c->textures.tmu[c->textures.active].texture;
     switch (pname) {
     case GL_TEXTURE_WRAP_S:
         if ((param == GL_REPEAT) ||
@@ -581,12 +691,11 @@
 }
 
 
-static void drawTexxOES(GLfixed x, GLfixed y, GLfixed z, GLfixed w, GLfixed h,
+
+static void drawTexxOESImp(GLfixed x, GLfixed y, GLfixed z, GLfixed w, GLfixed h,
         ogles_context_t* c)
 {
-    // quickly reject empty rects
-    if ((w|h) <= 0)
-        return;                
+    ogles_lock_textures(c);
 
     const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s;
     y = gglIntToFixed(cbSurface.height) - (y + h);
@@ -610,7 +719,7 @@
                 GGL_TEXTURE_2D, GGL_TEXTURE_WRAP_T, GGL_CLAMP);
         u.dirty = 0xFF; // XXX: should be more subtle
 
-        EGLTextureObject* textureObject = u.texture;  
+        EGLTextureObject* textureObject = u.texture;
         const GLint Ucr = textureObject->crop_rect[0] << 16;
         const GLint Vcr = textureObject->crop_rect[1] << 16;
         const GLint Wcr = textureObject->crop_rect[2] << 16;
@@ -641,11 +750,30 @@
     c->rasterizer.procs.disable(c, GGL_W_LERP);
     c->rasterizer.procs.disable(c, GGL_AA);
     c->rasterizer.procs.shadeModel(c, GL_FLAT);
-    c->rasterizer.procs.recti(c, 
+    c->rasterizer.procs.recti(c,
             gglFixedToIntRound(x),
             gglFixedToIntRound(y),
             gglFixedToIntRound(x)+w,
             gglFixedToIntRound(y)+h);
+
+    ogles_unlock_textures(c);
+}
+
+static void drawTexxOES(GLfixed x, GLfixed y, GLfixed z, GLfixed w, GLfixed h,
+        ogles_context_t* c)
+{
+#ifdef LIBAGL_USE_GRALLOC_COPYBITS
+    if (drawTexiOESWithCopybit(gglFixedToIntRound(x),
+            gglFixedToIntRound(y), gglFixedToIntRound(z),
+            gglFixedToIntRound(w), gglFixedToIntRound(h), c)) {
+        return;
+    }
+#else
+    // quickly reject empty rects
+    if ((w|h) <= 0)
+        return;
+#endif
+    drawTexxOESImp(x, y, z, w, h, c);
 }
 
 static void drawTexiOES(GLint x, GLint y, GLint z, GLint w, GLint h, ogles_context_t* c)
@@ -656,14 +784,21 @@
     // which is a lot faster.
 
     if (ggl_likely(c->rasterizer.state.enabled_tmu == 1)) {
+#ifdef LIBAGL_USE_GRALLOC_COPYBITS
+        if (drawTexiOESWithCopybit(x, y, z, w, h, c)) {
+            return;
+        }
+#endif
         const int tmu = 0;
         texture_unit_t& u(c->textures.tmu[tmu]);
-        EGLTextureObject* textureObject = u.texture;  
+        EGLTextureObject* textureObject = u.texture;
         const GLint Wcr = textureObject->crop_rect[2];
         const GLint Hcr = textureObject->crop_rect[3];
 
         if ((w == Wcr) && (h == -Hcr)) {
+#ifndef LIBAGL_USE_GRALLOC_COPYBITS
             if ((w|h) <= 0) return; // quickly reject empty rects
+#endif
 
             if (u.dirty) {
                 c->rasterizer.procs.activeTexture(c, tmu);
@@ -679,14 +814,14 @@
                     GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE);
             u.dirty = 0xFF; // XXX: should be more subtle
             c->rasterizer.procs.activeTexture(c, c->textures.active);
-            
+
             const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s;
             y = cbSurface.height - (y + h);
             const GLint Ucr = textureObject->crop_rect[0];
             const GLint Vcr = textureObject->crop_rect[1];
             const GLint s0  = Ucr - x;
             const GLint t0  = (Vcr + Hcr) - y;
-            
+
             const GLuint tw = textureObject->surface.width;
             const GLuint th = textureObject->surface.height;
             if ((uint32_t(s0+x+w) > tw) || (uint32_t(t0+y+h) > th)) {
@@ -694,7 +829,9 @@
                 // in this case, so we just use the slow case, which
                 // at least won't crash
                 goto slow_case;
-            } 
+            }
+
+            ogles_lock_textures(c);
 
             c->rasterizer.procs.texCoord2i(c, s0, t0);
             const uint32_t enables = c->rasterizer.state.enables;
@@ -706,12 +843,15 @@
             c->rasterizer.procs.disable(c, GGL_AA);
             c->rasterizer.procs.shadeModel(c, GL_FLAT);
             c->rasterizer.procs.recti(c, x, y, x+w, y+h);
+
+            ogles_unlock_textures(c);
+
             return;
         }
     }
 
 slow_case:
-    drawTexxOES(
+    drawTexxOESImp(
             gglIntToFixed(x), gglIntToFixed(y), gglIntToFixed(z),
             gglIntToFixed(w), gglIntToFixed(h),
             c);
@@ -749,7 +889,7 @@
     }
 
     // Bind or create a texture
-    sp<EGLTextureObject> tex;    
+    sp<EGLTextureObject> tex;
     if (texture == 0) {
         // 0 is our local texture object
         tex = c->textures.defaultTexture;
@@ -837,7 +977,7 @@
     if ((pname != GL_PACK_ALIGNMENT) && (pname != GL_UNPACK_ALIGNMENT)) {
         ogles_error(c, GL_INVALID_ENUM);
         return;
-    }    
+    }
     if ((param<=0 || param>8) || (param & (param-1))) {
         ogles_error(c, GL_INVALID_VALUE);
         return;
@@ -952,7 +1092,7 @@
     }
 
     // "uncompress" the texture since pixelflinger doesn't support
-    // any compressed texture format natively. 
+    // any compressed texture format natively.
     GLenum format;
     GLenum type;
     switch (internalformat) {
@@ -995,6 +1135,12 @@
     GGLSurface* surface;
     // all mipmap levels are specified at once.
     const int numLevels = level<0 ? -level : 1;
+
+    if (dataSizePalette4(numLevels, width, height, format) > imageSize) {
+        ogles_error(c, GL_INVALID_VALUE);
+        return;
+    }
+
     for (int i=0 ; i<numLevels ; i++) {
         int lod_w = (width  >> i) ? : 1;
         int lod_h = (height >> i) ? : 1;
@@ -1016,7 +1162,7 @@
         GLenum format, GLenum type, const GLvoid *pixels)
 {
     ogles_context_t* c = ogles_context_t::get();
-    if (target != GL_TEXTURE_2D && target != GL_DIRECT_TEXTURE_2D_QUALCOMM) {
+    if (target != GL_TEXTURE_2D) {
         ogles_error(c, GL_INVALID_ENUM);
         return;
     }
@@ -1024,7 +1170,7 @@
         ogles_error(c, GL_INVALID_VALUE);
         return;
     }
-    if (format != internalformat) {
+    if (format != (GLenum)internalformat) {
         ogles_error(c, GL_INVALID_OPERATION);
         return;
     }
@@ -1034,16 +1180,10 @@
 
     int32_t size = 0;
     GGLSurface* surface = 0;
-    if (target != GL_DIRECT_TEXTURE_2D_QUALCOMM) {
-        int error = createTextureSurface(c, &surface, &size,
-                level, format, type, width, height);
-        if (error) {
-            ogles_error(c, error);
-            return;
-        }
-    } else if (pixels == 0 || level != 0) {
-        // pixel can't be null for direct texture
-        ogles_error(c, GL_INVALID_OPERATION);
+    int error = createTextureSurface(c, &surface, &size,
+            level, format, type, width, height);
+    if (error) {
+        ogles_error(c, error);
         return;
     }
 
@@ -1064,18 +1204,12 @@
         userSurface.compressedFormat = 0;
         userSurface.data = (GLubyte*)pixels;
 
-        if (target != GL_DIRECT_TEXTURE_2D_QUALCOMM) {
-            int err = copyPixels(c, *surface, 0, 0, userSurface, 0, 0, width, height); 
-            if (err) {
-                ogles_error(c, err);
-                return;
-            }
-            generateMipmap(c, level);
-        } else {
-            // bind it to the texture unit
-            sp<EGLTextureObject> tex = getAndBindActiveTextureObject(c);
-            tex->setSurface(&userSurface);
+        int err = copyPixels(c, *surface, 0, 0, userSurface, 0, 0, width, height);
+        if (err) {
+            ogles_error(c, err);
+            return;
         }
+        generateMipmap(c, level);
     }
 }
 
@@ -1118,6 +1252,11 @@
         ogles_error(c, GL_INVALID_OPERATION);
         return;
     }
+
+    if (format != tex->internalformat) {
+        ogles_error(c, GL_INVALID_OPERATION);
+        return;
+    }
     if ((xoffset + width  > GLsizei(surface.width)) ||
         (yoffset + height > GLsizei(surface.height))) {
         ogles_error(c, GL_INVALID_VALUE);
@@ -1150,7 +1289,7 @@
 
     int err = copyPixels(c,
             surface, xoffset, yoffset,
-            userSurface, 0, 0, width, height); 
+            userSurface, 0, 0, width, height);
     if (err) {
         ogles_error(c, err);
         return;
@@ -1203,7 +1342,7 @@
     case GL_LUMINANCE_ALPHA:
     case GL_LUMINANCE:
         type = GL_UNSIGNED_BYTE;
-        break;    
+        break;
     }
 
     // figure out the format to use for the new texture
@@ -1213,7 +1352,7 @@
     case GGL_PIXEL_FORMAT_RGBA_5551:
     case GGL_PIXEL_FORMAT_RGBA_4444:
         format = internalformat;
-        break;    
+        break;
     case GGL_PIXEL_FORMAT_RGBX_8888:
     case GGL_PIXEL_FORMAT_RGB_888:
     case GGL_PIXEL_FORMAT_RGB_565:
@@ -1222,7 +1361,7 @@
         case GL_LUMINANCE:
         case GL_RGB:
             format = internalformat;
-            break;    
+            break;
         }
         break;
     }
@@ -1242,7 +1381,7 @@
         ogles_error(c, error);
         return;
     }
-    
+
     // The bottom row is stored first in textures
     GGLSurface txSurface(*surface);
     txSurface.stride = -txSurface.stride;
@@ -1252,7 +1391,7 @@
 
     int err = copyPixels(c,
             txSurface, 0, 0,
-            cbSurface, x, y, cbSurface.width, cbSurface.height);  
+            cbSurface, x, y, cbSurface.width, cbSurface.height);
     if (err) {
         ogles_error(c, err);
     }
@@ -1302,7 +1441,7 @@
 
     int err = copyPixels(c,
             surface, xoffset, yoffset,
-            cbSurface, x, y, width, height);  
+            cbSurface, x, y, width, height);
     if (err) {
         ogles_error(c, err);
         return;
@@ -1372,7 +1511,7 @@
         return;
     }
 
-    ggl->colorBuffer(ggl, &userSurface);  // destination is user buffer 
+    ggl->colorBuffer(ggl, &userSurface);  // destination is user buffer
     ggl->bindTexture(ggl, &readSurface);  // source is read-buffer
     ggl->texCoord2i(ggl, x, readSurface.height - (y + height));
     ggl->recti(ggl, 0, 0, width, height);
@@ -1426,3 +1565,43 @@
     ogles_context_t* c = ogles_context_t::get();
     drawTexxOES(x, y, z, w, h, c);
 }
+
+// ----------------------------------------------------------------------------
+#if 0
+#pragma mark -
+#pragma mark EGL Image Extension
+#endif
+
+void glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image)
+{
+    ogles_context_t* c = ogles_context_t::get();
+    if (target != GL_TEXTURE_2D) {
+        ogles_error(c, GL_INVALID_ENUM);
+        return;
+    }
+
+    android_native_buffer_t* native_buffer = (android_native_buffer_t*)image;
+    if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC) {
+        ogles_error(c, GL_INVALID_VALUE);
+        return;
+    }
+    if (native_buffer->common.version != sizeof(android_native_buffer_t)) {
+        ogles_error(c, GL_INVALID_VALUE);
+        return;
+    }
+
+    // bind it to the texture unit
+    sp<EGLTextureObject> tex = getAndBindActiveTextureObject(c);
+    tex->setImage(native_buffer);
+
+#ifdef LIBAGL_USE_GRALLOC_COPYBITS
+    tex->try_copybit = false;
+    if (c->copybits.blitEngine != NULL) {
+        tex->try_copybit = true;
+    }
+#endif // LIBAGL_USE_GRALLOC_COPYBITS
+}
+
+void glEGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
+{
+}
diff --git a/opengl/libagl/texture.h b/opengl/libagl/texture.h
index 5c57948..98f7550 100644
--- a/opengl/libagl/texture.h
+++ b/opengl/libagl/texture.h
@@ -32,13 +32,9 @@
 
 void ogles_init_texture(ogles_context_t* c);
 void ogles_uninit_texture(ogles_context_t* c);
-void ogles_validate_texture_impl(ogles_context_t* c);
-
-inline void ogles_validate_texture(ogles_context_t* c) {
-    if (c->rasterizer.state.enables & GGL_ENABLE_TMUS)
-        ogles_validate_texture_impl(c);
-}
-
+void ogles_validate_texture(ogles_context_t* c);
+void ogles_lock_textures(ogles_context_t* c);
+void ogles_unlock_textures(ogles_context_t* c);
 
 }; // namespace android
 
diff --git a/opengl/libs/Android.mk b/opengl/libs/Android.mk
index 23304d5..6d20e80 100644
--- a/opengl/libs/Android.mk
+++ b/opengl/libs/Android.mk
@@ -1,17 +1,18 @@
 LOCAL_PATH:= $(call my-dir)
 
-#
+###############################################################################
 # Build META EGL library
 #
 
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:= 	\
-	EGL/egl.cpp 		\
-	EGL/gpu.cpp			\
+	EGL/egl.cpp 	\
+	EGL/hooks.cpp 	\
+	EGL/Loader.cpp 	\
 #
 
-LOCAL_SHARED_LIBRARIES += libcutils libutils libui
+LOCAL_SHARED_LIBRARIES += libcutils libutils
 LOCAL_LDLIBS := -lpthread -ldl
 LOCAL_MODULE:= libEGL
 
@@ -19,24 +20,50 @@
 ifeq ($(TARGET_SIMULATOR),true)
 else
     LOCAL_SHARED_LIBRARIES += libdl
-    # we need to access the Bionic private header <bionic_tls.h>
-    LOCAL_CFLAGS += -I$(LOCAL_PATH)/../../../../bionic/libc/private
+    # we need to access the private Bionic header <bionic_tls.h>
+    LOCAL_C_INCLUDES += bionic/libc/private
 endif
 
+LOCAL_CFLAGS += -DLOG_TAG=\"libEGL\"
+LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
 LOCAL_CFLAGS += -fvisibility=hidden
 
+ifeq ($(TARGET_BOARD_PLATFORM),msm7k)
+LOCAL_CFLAGS += -DADRENO130=1
+endif
+
+ifeq ($(ARCH_ARM_HAVE_TLS_REGISTER),true)
+  LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
+endif
+
 include $(BUILD_SHARED_LIBRARY)
+installed_libEGL := $(LOCAL_INSTALLED_MODULE)
 
 
+# OpenGL drivers config file
+ifneq ($(BOARD_EGL_CFG),)
 
-#
-# Build the wrapper OpenGL ES library
+include $(CLEAR_VARS)
+LOCAL_MODULE := egl.cfg
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_OUT)/lib/egl
+LOCAL_SRC_FILES := ../../../../$(BOARD_EGL_CFG)
+include $(BUILD_PREBUILT)
+
+# make sure we depend on egl.cfg, so it gets installed
+$(installed_libEGL): | egl.cfg
+
+endif
+
+###############################################################################
+# Build the wrapper OpenGL ES 1.x library
 #
 
 include $(CLEAR_VARS)
 
-LOCAL_SRC_FILES:= 	\
-	GLES_CM/gl.cpp.arm 		\
+LOCAL_SRC_FILES:= 		\
+	GLES_CM/gl.cpp.arm 	\
 #
 
 LOCAL_SHARED_LIBRARIES += libcutils libEGL
@@ -47,10 +74,49 @@
 ifeq ($(TARGET_SIMULATOR),true)
 else
     LOCAL_SHARED_LIBRARIES += libdl
-    # we need to access the Bionic private header <bionic_tls.h>
-    LOCAL_CFLAGS += -I$(LOCAL_PATH)/../../../../bionic/libc/private
+    # we need to access the private Bionic header <bionic_tls.h>
+    LOCAL_C_INCLUDES += bionic/libc/private
 endif
 
+LOCAL_CFLAGS += -DLOG_TAG=\"libGLESv1\"
+LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
 LOCAL_CFLAGS += -fvisibility=hidden
 
+ifeq ($(ARCH_ARM_HAVE_TLS_REGISTER),true)
+  LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
+endif
+
+include $(BUILD_SHARED_LIBRARY)
+
+
+###############################################################################
+# Build the wrapper OpenGL ES 2.x library
+#
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= 		\
+	GLES2/gl2.cpp.arm 	\
+#
+
+LOCAL_SHARED_LIBRARIES += libcutils libEGL
+LOCAL_LDLIBS := -lpthread -ldl
+LOCAL_MODULE:= libGLESv2
+
+# needed on sim build because of weird logging issues
+ifeq ($(TARGET_SIMULATOR),true)
+else
+    LOCAL_SHARED_LIBRARIES += libdl
+    # we need to access the private Bionic header <bionic_tls.h>
+    LOCAL_C_INCLUDES += bionic/libc/private
+endif
+
+LOCAL_CFLAGS += -DLOG_TAG=\"libGLESv2\"
+LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
+LOCAL_CFLAGS += -fvisibility=hidden
+
+ifeq ($(ARCH_ARM_HAVE_TLS_REGISTER),true)
+  LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
+endif
+
 include $(BUILD_SHARED_LIBRARY)
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
new file mode 100644
index 0000000..5d6ac26
--- /dev/null
+++ b/opengl/libs/EGL/Loader.cpp
@@ -0,0 +1,287 @@
+/* 
+ ** 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.
+ */
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <dlfcn.h>
+#include <limits.h>
+
+#include <cutils/log.h>
+
+#include <EGL/egl.h>
+
+#include "hooks.h"
+#include "egl_impl.h"
+
+#include "Loader.h"
+
+// ----------------------------------------------------------------------------
+namespace android {
+// ----------------------------------------------------------------------------
+
+
+/*
+ * EGL drivers are called
+ * 
+ * /system/lib/egl/lib{[EGL|GLESv1_CM|GLESv2] | GLES}_$TAG.so 
+ * 
+ */
+
+ANDROID_SINGLETON_STATIC_INSTANCE( Loader )
+
+// ----------------------------------------------------------------------------
+
+Loader::driver_t::driver_t(void* gles) 
+{
+    dso[0] = gles;
+    for (size_t i=1 ; i<NELEM(dso) ; i++)
+        dso[i] = 0;
+}
+
+Loader::driver_t::~driver_t() 
+{
+    for (size_t i=0 ; i<NELEM(dso) ; i++) {
+        if (dso[i]) {
+            dlclose(dso[i]);
+            dso[i] = 0;
+        }
+    }
+}
+
+status_t Loader::driver_t::set(void* hnd, int32_t api)
+{
+    switch (api) {
+        case EGL:
+            dso[0] = hnd;
+            break;
+        case GLESv1_CM:
+            dso[1] = hnd;
+            break;
+        case GLESv2:
+            dso[2] = hnd;
+            break;
+        default:
+            return BAD_INDEX;
+    }
+    return NO_ERROR;
+}
+
+// ----------------------------------------------------------------------------
+
+Loader::entry_t::entry_t(int dpy, int impl, const char* tag)
+    : dpy(dpy), impl(impl), tag(tag) {
+}
+
+// ----------------------------------------------------------------------------
+
+Loader::Loader()
+{
+    char line[256];
+    char tag[256];
+    FILE* cfg = fopen("/system/lib/egl/egl.cfg", "r");
+    if (cfg == NULL) {
+        // default config
+        LOGD("egl.cfg not found, using default config");
+        gConfig.add( entry_t(0, 0, "android") );
+    } else {
+        while (fgets(line, 256, cfg)) {
+            int dpy;
+            int impl;
+            if (sscanf(line, "%u %u %s", &dpy, &impl, tag) == 3) {
+                //LOGD(">>> %u %u %s", dpy, impl, tag);
+                gConfig.add( entry_t(dpy, impl, tag) );
+            }
+        }
+        fclose(cfg);
+    }
+}
+
+Loader::~Loader()
+{
+}
+
+const char* Loader::getTag(int dpy, int impl)
+{
+    const Vector<entry_t>& cfgs(gConfig);    
+    const size_t c = cfgs.size();
+    for (size_t i=0 ; i<c ; i++) {
+        if (dpy == cfgs[i].dpy)
+            if (impl == cfgs[i].impl)
+                return cfgs[i].tag.string();
+    }
+    return 0;
+}
+
+void* Loader::open(EGLNativeDisplayType display, int impl, egl_connection_t* cnx)
+{
+    /*
+     * TODO: if we don't find display/0, then use 0/0
+     * (0/0 should always work)
+     */
+    
+    void* dso;
+    char path[PATH_MAX];
+    int index = int(display);
+    driver_t* hnd = 0;
+    const char* const format = "/system/lib/egl/lib%s_%s.so";
+    
+    char const* tag = getTag(index, impl);
+    if (tag) {
+        snprintf(path, PATH_MAX, format, "GLES", tag);
+        dso = load_driver(path, cnx, EGL | GLESv1_CM | GLESv2);
+        if (dso) {
+            hnd = new driver_t(dso);
+        } else {
+            // Always load EGL first
+            snprintf(path, PATH_MAX, format, "EGL", tag);
+            dso = load_driver(path, cnx, EGL);
+            if (dso) {
+                hnd = new driver_t(dso);
+
+                // TODO: make this more automated
+                snprintf(path, PATH_MAX, format, "GLESv1_CM", tag);
+                hnd->set( load_driver(path, cnx, GLESv1_CM), GLESv1_CM );
+
+                snprintf(path, PATH_MAX, format, "GLESv2", tag);
+                hnd->set( load_driver(path, cnx, GLESv2), GLESv2 );
+            }
+        }
+    }
+
+    LOG_FATAL_IF(!index && !impl && !hnd, 
+            "couldn't find the default OpenGL ES implementation "
+            "for default display");
+    
+    return (void*)hnd;
+}
+
+status_t Loader::close(void* driver)
+{
+    driver_t* hnd = (driver_t*)driver;
+    delete hnd;
+    return NO_ERROR;
+}
+
+void Loader::init_api(void* dso, 
+        char const * const * api, 
+        __eglMustCastToProperFunctionPointerType* curr, 
+        getProcAddressType getProcAddress) 
+{
+    char scrap[256];
+    while (*api) {
+        char const * name = *api;
+        __eglMustCastToProperFunctionPointerType f = 
+            (__eglMustCastToProperFunctionPointerType)dlsym(dso, name);
+        if (f == NULL) {
+            // couldn't find the entry-point, use eglGetProcAddress()
+            f = getProcAddress(name);
+        }
+        if (f == NULL) {
+            // Try without the OES postfix
+            ssize_t index = ssize_t(strlen(name)) - 3;
+            if ((index>0 && (index<255)) && (!strcmp(name+index, "OES"))) {
+                strncpy(scrap, name, index);
+                scrap[index] = 0;
+                f = (__eglMustCastToProperFunctionPointerType)dlsym(dso, scrap);
+                //LOGD_IF(f, "found <%s> instead", scrap);
+            }
+        }
+        if (f == NULL) {
+            // Try with the OES postfix
+            ssize_t index = ssize_t(strlen(name)) - 3;
+            if ((index>0 && (index<252)) && (strcmp(name+index, "OES"))) {
+                strncpy(scrap, name, index);
+                scrap[index] = 0;
+                strcat(scrap, "OES");
+                f = (__eglMustCastToProperFunctionPointerType)dlsym(dso, scrap);
+                //LOGD_IF(f, "found <%s> instead", scrap);
+            }
+        }
+        if (f == NULL) {
+            //LOGD("%s", name);
+            f = (__eglMustCastToProperFunctionPointerType)gl_unimplemented;
+        }
+        *curr++ = f;
+        api++;
+    }
+}
+
+void *Loader::load_driver(const char* driver_absolute_path,
+        egl_connection_t* cnx, uint32_t mask)
+{
+    if (access(driver_absolute_path, R_OK)) {
+        // this happens often, we don't want to log an error
+        return 0;
+    }
+
+    void* dso = dlopen(driver_absolute_path, RTLD_NOW | RTLD_LOCAL);
+    if (dso == 0) {
+        const char* err = dlerror();
+        LOGE("load_driver(%s): %s", driver_absolute_path, err?err:"unknown");
+        return 0;
+    }
+
+    LOGD("loaded %s", driver_absolute_path);
+
+    if (mask & EGL) {
+        getProcAddress = (getProcAddressType)dlsym(dso, "eglGetProcAddress");
+
+        LOGE_IF(!getProcAddress, 
+                "can't find eglGetProcAddress() in %s", driver_absolute_path);
+
+        egl_t* egl = &cnx->egl;
+        __eglMustCastToProperFunctionPointerType* curr =
+            (__eglMustCastToProperFunctionPointerType*)egl;
+        char const * const * api = egl_names;
+        while (*api) {
+            char const * name = *api;
+            __eglMustCastToProperFunctionPointerType f = 
+                (__eglMustCastToProperFunctionPointerType)dlsym(dso, name);
+            if (f == NULL) {
+                // couldn't find the entry-point, use eglGetProcAddress()
+                f = getProcAddress(name);
+                if (f == NULL) {
+                    f = (__eglMustCastToProperFunctionPointerType)0;
+                }
+            }
+            *curr++ = f;
+            api++;
+        }
+    }
+    
+    if (mask & GLESv1_CM) {
+        init_api(dso, gl_names,
+            (__eglMustCastToProperFunctionPointerType*)
+                &cnx->hooks[GLESv1_INDEX]->gl,
+            getProcAddress);
+    }
+
+    if (mask & GLESv2) {
+      init_api(dso, gl_names,
+            (__eglMustCastToProperFunctionPointerType*)
+                &cnx->hooks[GLESv2_INDEX]->gl,
+            getProcAddress);
+    }
+    
+    return dso;
+}
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+// ----------------------------------------------------------------------------
diff --git a/opengl/libs/EGL/Loader.h b/opengl/libs/EGL/Loader.h
new file mode 100644
index 0000000..8659b0b
--- /dev/null
+++ b/opengl/libs/EGL/Loader.h
@@ -0,0 +1,90 @@
+/* 
+ ** Copyright 2009, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License"); 
+ ** you may not use this file except in compliance with the License. 
+ ** You may obtain a copy of the License at 
+ **
+ **     http://www.apache.org/licenses/LICENSE-2.0 
+ **
+ ** Unless required by applicable law or agreed to in writing, software 
+ ** distributed under the License is distributed on an "AS IS" BASIS, 
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ ** See the License for the specific language governing permissions and 
+ ** limitations under the License.
+ */
+
+#ifndef ANDROID_EGL_LOADER_H
+#define ANDROID_EGL_LOADER_H
+
+#include <ctype.h>
+#include <string.h>
+#include <errno.h>
+
+#include <utils/Errors.h>
+#include <utils/Singleton.h>
+#include <utils/String8.h>
+#include <utils/Vector.h>
+
+#include <EGL/egl.h>
+
+// ----------------------------------------------------------------------------
+namespace android {
+// ----------------------------------------------------------------------------
+
+struct egl_connection_t;
+
+class Loader : public Singleton<Loader>
+{
+    friend class Singleton<Loader>;
+
+    typedef __eglMustCastToProperFunctionPointerType (*getProcAddressType)(
+            const char*);
+   
+    enum {
+        EGL         = 0x01,
+        GLESv1_CM   = 0x02,
+        GLESv2      = 0x04
+    };
+    struct driver_t {
+        driver_t(void* gles);
+        ~driver_t();
+        status_t set(void* hnd, int32_t api);
+        void* dso[3];
+    };
+    
+    struct entry_t {
+        entry_t() { }
+        entry_t(int dpy, int impl, const char* tag);
+        int dpy;
+        int impl;
+        String8 tag;
+    };
+
+    Vector<entry_t> gConfig;    
+    getProcAddressType getProcAddress;
+    
+    const char* getTag(int dpy, int impl);
+
+public:
+    ~Loader();
+    
+    void* open(EGLNativeDisplayType display, int impl, egl_connection_t* cnx);
+    status_t close(void* driver);
+    
+private:
+    Loader();
+    void *load_driver(const char* driver, egl_connection_t* cnx, uint32_t mask);
+
+    static __attribute__((noinline))
+    void init_api(void* dso, 
+            char const * const * api, 
+            __eglMustCastToProperFunctionPointerType* curr, 
+            getProcAddressType getProcAddress); 
+};
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+// ----------------------------------------------------------------------------
+
+#endif /* ANDROID_EGL_LOADER_H */
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index c6e0f50..c22c21b 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -14,9 +14,8 @@
  ** limitations under the License.
  */
 
-#define LOG_TAG "libEGL"
-
 #include <ctype.h>
+#include <stdlib.h>
 #include <string.h>
 #include <errno.h>
 #include <dlfcn.h>
@@ -37,11 +36,11 @@
 #include <cutils/properties.h>
 #include <cutils/memory.h>
 
-#include <utils/RefBase.h>
+#include <utils/SortedVector.h>
 
 #include "hooks.h"
 #include "egl_impl.h"
-
+#include "Loader.h"
 
 #define MAKE_CONFIG(_impl, _index)  ((EGLConfig)(((_impl)<<24) | (_index)))
 #define setError(_e, _r) setErrorEtc(__FUNCTION__, __LINE__, _e, _r)
@@ -53,64 +52,152 @@
 #define VERSION_MAJOR 1
 #define VERSION_MINOR 4
 static char const * const gVendorString     = "Android";
-static char const * const gVersionString    = "1.31 Android META-EGL";
+static char const * const gVersionString    = "1.4 Android META-EGL";
 static char const * const gClientApiString  = "OpenGL ES";
-static char const * const gExtensionString  = "";
+static char const * const gExtensionString  = 
+        "EGL_KHR_image "
+        "EGL_KHR_image_base "
+        "EGL_KHR_image_pixmap "
+        "EGL_ANDROID_image_native_buffer "
+        "EGL_ANDROID_swap_rectangle "
+        "EGL_ANDROID_get_render_buffer "
+        ;
 
-template <int MAGIC>
-struct egl_object_t
-{
-    egl_object_t() : magic(MAGIC) { }
-    ~egl_object_t() { magic = 0; }
-    bool isValid() const { return magic == MAGIC; }
+// ----------------------------------------------------------------------------
+
+class egl_object_t {
+    static SortedVector<egl_object_t*> sObjects;
+    static Mutex sLock;
+
+            volatile int32_t  terminated;
+    mutable volatile int32_t  count;
+
+public:
+    egl_object_t() : terminated(0), count(1) { 
+        Mutex::Autolock _l(sLock);
+        sObjects.add(this);
+    }
+
+    inline bool isAlive() const { return !terminated; }
+
 private:
-    uint32_t    magic;
+    bool get() {
+        Mutex::Autolock _l(sLock);
+        if (egl_object_t::sObjects.indexOf(this) >= 0) {
+            android_atomic_inc(&count);
+            return true;
+        }
+        return false;
+    }
+
+    bool put() {
+        Mutex::Autolock _l(sLock);
+        if (android_atomic_dec(&count) == 1) {
+            sObjects.remove(this);
+            return true;
+        }
+        return false;
+    }    
+
+public:
+    template <typename N, typename T>
+    struct LocalRef {
+        N* ref;
+        LocalRef(T o) : ref(0) {
+            N* native = reinterpret_cast<N*>(o);
+            if (o && native->get()) {
+                ref = native;
+            }
+        }
+        ~LocalRef() { 
+            if (ref && ref->put()) {
+                delete ref;
+            }
+        }
+        inline N* get() {
+            return ref;
+        }
+        void acquire() const {
+            if (ref) {
+                android_atomic_inc(&ref->count);
+            }
+        }
+        void release() const {
+            if (ref) {
+                int32_t c = android_atomic_dec(&ref->count);
+                // ref->count cannot be 1 prior atomic_dec because we have
+                // a reference, and if we have one, it means there was
+                // already one before us.
+                LOGE_IF(c==1, "refcount is now 0 in release()");
+            }
+        }
+        void terminate() {
+            if (ref) {
+                ref->terminated = 1;
+                release();
+            }
+        }
+    };
 };
 
-struct egl_display_t : public egl_object_t<'_dpy'>
-{
-    EGLDisplay  dpys[IMPL_NUM_DRIVERS_IMPLEMENTATIONS];
-    EGLConfig*  configs[IMPL_NUM_DRIVERS_IMPLEMENTATIONS];
-    EGLint      numConfigs[IMPL_NUM_DRIVERS_IMPLEMENTATIONS];
-    EGLint      numTotalConfigs;
-    char const* extensionsString;
-    volatile int32_t refs;
+SortedVector<egl_object_t*> egl_object_t::sObjects;
+Mutex egl_object_t::sLock;
+
+struct egl_display_t {
+    enum { NOT_INITIALIZED, INITIALIZED, TERMINATED };
+    
     struct strings_t {
         char const * vendor;
         char const * version;
         char const * clientApi;
         char const * extensions;
     };
-    strings_t   queryString[IMPL_NUM_DRIVERS_IMPLEMENTATIONS];
+
+    struct DisplayImpl {
+        DisplayImpl() : dpy(EGL_NO_DISPLAY), config(0),
+                        state(NOT_INITIALIZED), numConfigs(0) { }
+        EGLDisplay  dpy;
+        EGLConfig*  config;
+        EGLint      state;
+        EGLint      numConfigs;
+        strings_t   queryString;
+    };
+
+    uint32_t    magic;
+    DisplayImpl disp[IMPL_NUM_IMPLEMENTATIONS];
+    EGLint      numTotalConfigs;
+    volatile int32_t refs;
+    
+    egl_display_t() : magic('_dpy'), numTotalConfigs(0) { }
+    ~egl_display_t() { magic = 0; }
+    inline bool isValid() const { return magic == '_dpy'; }
+    inline bool isAlive() const { return isValid(); }
 };
 
-struct egl_surface_t : public egl_object_t<'_srf'>
+struct egl_surface_t : public egl_object_t
 {
+    typedef egl_object_t::LocalRef<egl_surface_t, EGLSurface> Ref;
+
     egl_surface_t(EGLDisplay dpy, EGLSurface surface,
-            NativeWindowType window, int impl, egl_connection_t const* cnx) 
-    : dpy(dpy), surface(surface), window(window), impl(impl), cnx(cnx)
-    {
-        // NOTE: window must be incRef'ed and connected already
+            int impl, egl_connection_t const* cnx) 
+    : dpy(dpy), surface(surface), impl(impl), cnx(cnx) {
     }
     ~egl_surface_t() {
-        if (window) {
-            if (window->disconnect)
-                window->disconnect(window);
-            window->decRef(window);
-        }
     }
     EGLDisplay                  dpy;
     EGLSurface                  surface;
-    NativeWindowType            window;
     int                         impl;
     egl_connection_t const*     cnx;
 };
 
-struct egl_context_t : public egl_object_t<'_ctx'>
+struct egl_context_t : public egl_object_t
 {
+    typedef egl_object_t::LocalRef<egl_context_t, EGLContext> Ref;
+    
     egl_context_t(EGLDisplay dpy, EGLContext context,
-            int impl, egl_connection_t const* cnx) 
-    : dpy(dpy), context(context), read(0), draw(0), impl(impl), cnx(cnx)
+            int impl, egl_connection_t const* cnx, int version) 
+    : dpy(dpy), context(context), read(0), draw(0), impl(impl), cnx(cnx),
+      version(version)
     {
     }
     EGLDisplay                  dpy;
@@ -119,52 +206,47 @@
     EGLSurface                  draw;
     int                         impl;
     egl_connection_t const*     cnx;
+    int                         version;
 };
 
+struct egl_image_t : public egl_object_t
+{
+    typedef egl_object_t::LocalRef<egl_image_t, EGLImageKHR> Ref;
+
+    egl_image_t(EGLDisplay dpy, EGLContext context)
+        : dpy(dpy), context(context)
+    {
+        memset(images, 0, sizeof(images));
+    }
+    EGLDisplay dpy;
+    EGLConfig context;
+    EGLImageKHR images[IMPL_NUM_IMPLEMENTATIONS];
+};
+
+typedef egl_surface_t::Ref  SurfaceRef;
+typedef egl_context_t::Ref  ContextRef;
+typedef egl_image_t::Ref    ImageRef;
+
 struct tls_t
 {
-    tls_t() : error(EGL_SUCCESS), ctx(0) { }
+    tls_t() : error(EGL_SUCCESS), ctx(0), logCallWithNoContext(EGL_TRUE) { }
     EGLint      error;
     EGLContext  ctx;
+    EGLBoolean  logCallWithNoContext;
 };
 
-static void gl_unimplemented() {
-    LOGE("called unimplemented OpenGL ES API");
-}
-
-// ----------------------------------------------------------------------------
-// GL / EGL hooks
-// ----------------------------------------------------------------------------
-
-#undef GL_ENTRY
-#undef EGL_ENTRY
-#define GL_ENTRY(_r, _api, ...) #_api,
-#define EGL_ENTRY(_r, _api, ...) #_api,
-
-static char const * const gl_names[] = {
-    #include "gl_entries.in"
-    #include "glext_entries.in"
-    NULL
-};
-
-static char const * const egl_names[] = {
-    #include "egl_entries.in"
-    NULL
-};
-
-#undef GL_ENTRY
-#undef EGL_ENTRY
 
 // ----------------------------------------------------------------------------
 
-egl_connection_t gEGLImpl[IMPL_NUM_DRIVERS_IMPLEMENTATIONS];
+egl_connection_t gEGLImpl[IMPL_NUM_IMPLEMENTATIONS];
 static egl_display_t gDisplay[NUM_DISPLAYS];
 static pthread_mutex_t gThreadLocalStorageKeyMutex = PTHREAD_MUTEX_INITIALIZER;
 static pthread_key_t gEGLThreadLocalStorageKey = -1;
 
 // ----------------------------------------------------------------------------
 
-EGLAPI gl_hooks_t gHooks[IMPL_NUM_IMPLEMENTATIONS];
+EGLAPI gl_hooks_t gHooks[2][IMPL_NUM_IMPLEMENTATIONS];
+EGLAPI gl_hooks_t gHooksNoContext;
 EGLAPI pthread_key_t gGLWrapperKey = -1;
 
 // ----------------------------------------------------------------------------
@@ -262,110 +344,8 @@
     return tls->ctx;
 }
 
-
 /*****************************************************************************/
 
-class ISurfaceComposer;
-const sp<ISurfaceComposer>& getSurfaceFlinger();
-request_gpu_t* gpu_acquire(void* user);
-int gpu_release(void*, request_gpu_t* gpu);
-
-static __attribute__((noinline))
-void *load_driver(const char* driver, gl_hooks_t* hooks)
-{
-    //LOGD("%s", driver);
-    char scrap[256];
-    void* dso = dlopen(driver, RTLD_NOW | RTLD_LOCAL);
-    LOGE_IF(!dso,
-            "couldn't load <%s> library (%s)",
-            driver, dlerror());
-
-    if (dso) {
-        // first find the symbol for eglGetProcAddress
-        
-        typedef __eglMustCastToProperFunctionPointerType (*getProcAddressType)(
-                const char*);
-        
-        getProcAddressType getProcAddress = 
-            (getProcAddressType)dlsym(dso, "eglGetProcAddress");
-        
-        LOGE_IF(!getProcAddress, 
-                "can't find eglGetProcAddress() in %s", driver);        
-        
-        __eglMustCastToProperFunctionPointerType* curr;
-        char const * const * api;
-
-        gl_hooks_t::egl_t* egl = &hooks->egl;
-        curr = (__eglMustCastToProperFunctionPointerType*)egl;
-        api = egl_names;
-        while (*api) {
-            char const * name = *api;
-            __eglMustCastToProperFunctionPointerType f = 
-                (__eglMustCastToProperFunctionPointerType)dlsym(dso, name);
-            if (f == NULL) {
-                // couldn't find the entry-point, use eglGetProcAddress()
-                f = getProcAddress(name);
-                if (f == NULL) {
-                    f = (__eglMustCastToProperFunctionPointerType)0;
-                }
-            }
-            *curr++ = f;
-            api++;
-        }
-
-        gl_hooks_t::gl_t* gl = &hooks->gl;
-        curr = (__eglMustCastToProperFunctionPointerType*)gl;
-        api = gl_names;
-        while (*api) {
-            char const * name = *api;
-            __eglMustCastToProperFunctionPointerType f = 
-                (__eglMustCastToProperFunctionPointerType)dlsym(dso, name);
-            if (f == NULL) {
-                // couldn't find the entry-point, use eglGetProcAddress()
-                f = getProcAddress(name);
-            }
-            if (f == NULL) {
-                // Try without the OES postfix
-                ssize_t index = ssize_t(strlen(name)) - 3;
-                if ((index>0 && (index<255)) && (!strcmp(name+index, "OES"))) {
-                    strncpy(scrap, name, index);
-                    scrap[index] = 0;
-                    f = (__eglMustCastToProperFunctionPointerType)dlsym(dso, scrap);
-                    //LOGD_IF(f, "found <%s> instead", scrap);
-                }
-            }
-            if (f == NULL) {
-                // Try with the OES postfix
-                ssize_t index = ssize_t(strlen(name)) - 3;
-                if ((index>0 && (index<252)) && (strcmp(name+index, "OES"))) {
-                    strncpy(scrap, name, index);
-                    scrap[index] = 0;
-                    strcat(scrap, "OES");
-                    f = (__eglMustCastToProperFunctionPointerType)dlsym(dso, scrap);
-                    //LOGD_IF(f, "found <%s> instead", scrap);
-                }
-            }
-            if (f == NULL) {
-                //LOGD("%s", name);
-                f = (__eglMustCastToProperFunctionPointerType)gl_unimplemented;
-            }
-            *curr++ = f;
-            api++;
-        }
-
-        // hook this driver up with surfaceflinger if needed
-        register_gpu_t register_gpu = 
-            (register_gpu_t)dlsym(dso, "oem_register_gpu");
-
-        if (register_gpu != NULL) {
-            if (getSurfaceFlinger() != 0) {
-                register_gpu(dso, gpu_acquire, gpu_release);
-            }
-        }
-    }
-    return dso;
-}
-
 template<typename T>
 static __attribute__((noinline))
 int binarySearch(
@@ -387,14 +367,14 @@
 static EGLint configToUniqueId(egl_display_t const* dp, int i, int index) 
 {
     // NOTE: this mapping works only if we have no more than two EGLimpl
-    return (i>0 ? dp->numConfigs[0] : 0) + index;
+    return (i>0 ? dp->disp[0].numConfigs : 0) + index;
 }
 
 static void uniqueIdToConfig(egl_display_t const* dp, EGLint configId,
         int& i, int& index) 
 {
     // NOTE: this mapping works only if we have no more than two EGLimpl
-    size_t numConfigs = dp->numConfigs[0];
+    size_t numConfigs = dp->disp[0].numConfigs;
     i = configId / numConfigs;
     index = configId % numConfigs;
 }
@@ -412,6 +392,18 @@
 };
 
 static const extention_map_t gExtentionMap[] = {
+    { "eglLockSurfaceKHR",  
+            (__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR }, 
+    { "eglUnlockSurfaceKHR", 
+            (__eglMustCastToProperFunctionPointerType)&eglUnlockSurfaceKHR }, 
+    { "eglCreateImageKHR",  
+            (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR }, 
+    { "eglDestroyImageKHR", 
+            (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR }, 
+    { "eglSetSwapRectangleANDROID", 
+            (__eglMustCastToProperFunctionPointerType)&eglSetSwapRectangleANDROID }, 
+    { "eglGetRenderBufferANDROID", 
+            (__eglMustCastToProperFunctionPointerType)&eglGetRenderBufferANDROID }, 
 };
 
 static extention_map_t gGLExtentionMap[MAX_NUMBER_OF_GL_EXTENSIONS];
@@ -429,29 +421,15 @@
 
 // ----------------------------------------------------------------------------
 
-static int gl_context_lost() {
-    setGlThreadSpecific(&gHooks[IMPL_CONTEXT_LOST]);
-    return 0;
-}
-static int egl_context_lost() {
-    setGlThreadSpecific(&gHooks[IMPL_CONTEXT_LOST]);
-    return EGL_FALSE;
-}
-static EGLBoolean egl_context_lost_swap_buffers(void*, void*) {
-    usleep(100000); // don't use all the CPU
-    setGlThreadSpecific(&gHooks[IMPL_CONTEXT_LOST]);
-    return EGL_FALSE;
-}
-static GLint egl_context_lost_get_error() {
-    return EGL_CONTEXT_LOST;
-}
-static int ext_context_lost() {
-    return 0;
+static void gl_no_context() {
+    tls_t* tls = getTLS();
+    if (tls->logCallWithNoContext == EGL_TRUE) {
+        tls->logCallWithNoContext = EGL_FALSE;
+        LOGE("call to OpenGL ES API with no current context "
+             "(logged once per thread)");
+    }
 }
 
-static void gl_no_context() {
-    LOGE("call to OpenGL ES API with no current context");
-}
 static void early_egl_init(void) 
 {
 #if !USE_FAST_TLS_KEY
@@ -459,10 +437,10 @@
 #endif
     uint32_t addr = (uint32_t)((void*)gl_no_context);
     android_memset32(
-            (uint32_t*)(void*)&gHooks[IMPL_NO_CONTEXT], 
+            (uint32_t*)(void*)&gHooksNoContext, 
             addr, 
-            sizeof(gHooks[IMPL_NO_CONTEXT]));
-    setGlThreadSpecific(&gHooks[IMPL_NO_CONTEXT]);
+            sizeof(gHooksNoContext));
+    setGlThreadSpecific(&gHooksNoContext);
 }
 
 static pthread_once_t once_control = PTHREAD_ONCE_INIT;
@@ -491,6 +469,11 @@
     return egl_to_native_cast<egl_context_t>(context);
 }
 
+static inline
+egl_image_t* get_image(EGLImageKHR image) {
+    return egl_to_native_cast<egl_image_t>(image);
+}
+
 static egl_connection_t* validate_display_config(
         EGLDisplay dpy, EGLConfig config,
         egl_display_t const*& dp, int& impl, int& index)
@@ -499,11 +482,11 @@
     if (!dp) return setError(EGL_BAD_DISPLAY, (egl_connection_t*)NULL);
 
     impl = uintptr_t(config)>>24;
-    if (uint32_t(impl) >= IMPL_NUM_DRIVERS_IMPLEMENTATIONS) {
+    if (uint32_t(impl) >= IMPL_NUM_IMPLEMENTATIONS) {
         return setError(EGL_BAD_CONFIG, (egl_connection_t*)NULL);
     } 
     index = uintptr_t(config) & 0xFFFFFF;
-    if (index >= dp->numConfigs[impl]) {
+    if (index >= dp->disp[impl].numConfigs) {
         return setError(EGL_BAD_CONFIG, (egl_connection_t*)NULL);
     }
     egl_connection_t* const cnx = &gEGLImpl[impl];
@@ -517,11 +500,9 @@
 {
     if ((uintptr_t(dpy)-1U) >= NUM_DISPLAYS)
         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
-    if (!get_display(dpy)->isValid())
+    if (!get_display(dpy)->isAlive())
         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
-    if (!ctx) // TODO: make sure context is a valid object
-        return setError(EGL_BAD_CONTEXT, EGL_FALSE);
-    if (!get_context(ctx)->isValid())
+    if (!get_context(ctx)->isAlive())
         return setError(EGL_BAD_CONTEXT, EGL_FALSE);
     return EGL_TRUE;
 }
@@ -530,92 +511,108 @@
 {
     if ((uintptr_t(dpy)-1U) >= NUM_DISPLAYS)
         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
-    if (!get_display(dpy)->isValid())
+    if (!get_display(dpy)->isAlive())
         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
-    if (!surface) // TODO: make sure surface is a valid object
-        return setError(EGL_BAD_SURFACE, EGL_FALSE);
-    if (!get_surface(surface)->isValid())
+    if (!get_surface(surface)->isAlive())
         return setError(EGL_BAD_SURFACE, EGL_FALSE);
     return EGL_TRUE;
 }
 
+EGLImageKHR egl_get_image_for_current_context(EGLImageKHR image)
+{
+    ImageRef _i(image);
+    if (!_i.get()) return EGL_NO_IMAGE_KHR;
+    
+    EGLContext context = getContext();
+    if (context == EGL_NO_CONTEXT || image == EGL_NO_IMAGE_KHR)
+        return EGL_NO_IMAGE_KHR;
+    
+    egl_context_t const * const c = get_context(context);
+    if (!c->isAlive())
+        return EGL_NO_IMAGE_KHR;
 
-EGLDisplay egl_init_displays(NativeDisplayType display)
+    egl_image_t const * const i = get_image(image);
+    return i->images[c->impl];
+}
+
+// ----------------------------------------------------------------------------
+
+// this mutex protects:
+//    d->disp[]
+//    egl_init_drivers_locked()
+//
+static pthread_mutex_t gInitDriverMutex = PTHREAD_MUTEX_INITIALIZER;
+
+EGLBoolean egl_init_drivers_locked()
 {
     if (sEarlyInitState) {
-        return EGL_NO_DISPLAY;
+        // initialized by static ctor. should be set here.
+        return EGL_FALSE;
     }
 
-    uint32_t index = uint32_t(display);
-    if (index >= NUM_DISPLAYS) {
-        return EGL_NO_DISPLAY;
-    }
+    // get our driver loader
+    Loader& loader(Loader::getInstance());
     
-    EGLDisplay dpy = EGLDisplay(uintptr_t(display) + 1LU);
-    egl_display_t* d = &gDisplay[index];
+    // dynamically load all our EGL implementations for all displays
+    // and retrieve the corresponding EGLDisplay
+    // if that fails, don't use this driver.
+    // TODO: currently we only deal with EGL_DEFAULT_DISPLAY
+    egl_connection_t* cnx;
+    egl_display_t* d = &gDisplay[0];
 
-    // dynamically load all our EGL implementations for that display
-    // and call into the real eglGetGisplay()
-    egl_connection_t* cnx = &gEGLImpl[IMPL_SOFTWARE];
+    cnx = &gEGLImpl[IMPL_SOFTWARE];
     if (cnx->dso == 0) {
-        cnx->hooks = &gHooks[IMPL_SOFTWARE];
-        cnx->dso = load_driver("libagl.so", cnx->hooks);
-    }
-    if (cnx->dso && d->dpys[IMPL_SOFTWARE]==EGL_NO_DISPLAY) {
-        d->dpys[IMPL_SOFTWARE] = cnx->hooks->egl.eglGetDisplay(display);
-        LOGE_IF(d->dpys[IMPL_SOFTWARE]==EGL_NO_DISPLAY,
-                "No EGLDisplay for software EGL!");
+        cnx->hooks[GLESv1_INDEX] = &gHooks[GLESv1_INDEX][IMPL_SOFTWARE];
+        cnx->hooks[GLESv2_INDEX] = &gHooks[GLESv2_INDEX][IMPL_SOFTWARE];
+        cnx->dso = loader.open(EGL_DEFAULT_DISPLAY, 0, cnx);
+        if (cnx->dso) {
+            EGLDisplay dpy = cnx->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
+            LOGE_IF(dpy==EGL_NO_DISPLAY, "No EGLDisplay for software EGL!");
+            d->disp[IMPL_SOFTWARE].dpy = dpy; 
+            if (dpy == EGL_NO_DISPLAY) {
+                loader.close(cnx->dso);
+                cnx->dso = NULL;
+            }
+        }
     }
 
     cnx = &gEGLImpl[IMPL_HARDWARE];
-    if (cnx->dso == 0 && cnx->unavailable == 0) {
+    if (cnx->dso == 0) {
         char value[PROPERTY_VALUE_MAX];
         property_get("debug.egl.hw", value, "1");
         if (atoi(value) != 0) {
-            cnx->hooks = &gHooks[IMPL_HARDWARE];
-            cnx->dso = load_driver("libhgl.so", cnx->hooks);
+            cnx->hooks[GLESv1_INDEX] = &gHooks[GLESv1_INDEX][IMPL_HARDWARE];
+            cnx->hooks[GLESv2_INDEX] = &gHooks[GLESv2_INDEX][IMPL_HARDWARE];
+            cnx->dso = loader.open(EGL_DEFAULT_DISPLAY, 1, cnx);
+            if (cnx->dso) {
+                EGLDisplay dpy = cnx->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
+                LOGE_IF(dpy==EGL_NO_DISPLAY, "No EGLDisplay for hardware EGL!");
+                d->disp[IMPL_HARDWARE].dpy = dpy; 
+                if (dpy == EGL_NO_DISPLAY) {
+                    loader.close(cnx->dso);
+                    cnx->dso = NULL;
+                }
+            }
         } else {
             LOGD("3D hardware acceleration is disabled");
         }
     }
-    if (cnx->dso && d->dpys[IMPL_HARDWARE]==EGL_NO_DISPLAY) {
-        android_memset32(
-                (uint32_t*)(void*)&gHooks[IMPL_CONTEXT_LOST].gl,
-                (uint32_t)((void*)gl_context_lost),
-                sizeof(gHooks[IMPL_CONTEXT_LOST].gl));
-        android_memset32(
-                (uint32_t*)(void*)&gHooks[IMPL_CONTEXT_LOST].egl,
-                (uint32_t)((void*)egl_context_lost),
-                sizeof(gHooks[IMPL_CONTEXT_LOST].egl));
-        android_memset32(
-                (uint32_t*)(void*)&gHooks[IMPL_CONTEXT_LOST].ext,
-                (uint32_t)((void*)ext_context_lost),
-                sizeof(gHooks[IMPL_CONTEXT_LOST].ext));
 
-        gHooks[IMPL_CONTEXT_LOST].egl.eglSwapBuffers =
-                egl_context_lost_swap_buffers;
-        
-        gHooks[IMPL_CONTEXT_LOST].egl.eglGetError =
-                egl_context_lost_get_error;
-
-        gHooks[IMPL_CONTEXT_LOST].egl.eglTerminate =
-                gHooks[IMPL_HARDWARE].egl.eglTerminate;
-        
-        d->dpys[IMPL_HARDWARE] = cnx->hooks->egl.eglGetDisplay(display);
-        if (d->dpys[IMPL_HARDWARE] == EGL_NO_DISPLAY) {
-            LOGE("h/w accelerated eglGetDisplay() failed (%s)",
-                    egl_strerror(cnx->hooks->egl.eglGetError()));
-            dlclose((void*)cnx->dso);
-            cnx->dso = 0;
-            // in case of failure, we want to make sure we don't try again
-            // as it's expensive.
-            cnx->unavailable = 1;
-        }
+    if (!gEGLImpl[IMPL_SOFTWARE].dso && !gEGLImpl[IMPL_HARDWARE].dso) {
+        return EGL_FALSE;
     }
 
-    return dpy;
+    return EGL_TRUE;
 }
 
+EGLBoolean egl_init_drivers()
+{
+    EGLBoolean res;
+    pthread_mutex_lock(&gInitDriverMutex);
+    res = egl_init_drivers_locked();
+    pthread_mutex_unlock(&gInitDriverMutex);
+    return res;
+}
 
 // ----------------------------------------------------------------------------
 }; // namespace android
@@ -625,7 +622,17 @@
 
 EGLDisplay eglGetDisplay(NativeDisplayType display)
 {
-    return egl_init_displays(display);
+    uint32_t index = uint32_t(display);
+    if (index >= NUM_DISPLAYS) {
+        return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
+    }
+
+    if (egl_init_drivers() == EGL_FALSE) {
+        return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
+    }
+    
+    EGLDisplay dpy = EGLDisplay(uintptr_t(display) + 1LU);
+    return dpy;
 }
 
 // ----------------------------------------------------------------------------
@@ -643,55 +650,73 @@
         return EGL_TRUE;
     }
     
-    setGlThreadSpecific(&gHooks[IMPL_NO_CONTEXT]);
+    setGlThreadSpecific(&gHooksNoContext);
     
     // initialize each EGL and
     // build our own extension string first, based on the extension we know
     // and the extension supported by our client implementation
-    dp->extensionsString = strdup(gExtensionString);
-    for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
+    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
         egl_connection_t* const cnx = &gEGLImpl[i];
         cnx->major = -1;
         cnx->minor = -1;
         if (!cnx->dso) 
             continue;
 
-        if (cnx->hooks->egl.eglInitialize(
-                dp->dpys[i], &cnx->major, &cnx->minor)) {
+#if defined(ADRENO130)
+#warning "Adreno-130 eglInitialize() workaround"
+        /*
+         * The ADRENO 130 driver returns a different EGLDisplay each time
+         * eglGetDisplay() is called, but also makes the EGLDisplay invalid
+         * after eglTerminate() has been called, so that eglInitialize() 
+         * cannot be called again. Therefore, we need to make sure to call
+         * eglGetDisplay() before calling eglInitialize();
+         */
+        if (i == IMPL_HARDWARE) {
+            dp->disp[i].dpy =
+                cnx->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
+        }
+#endif
 
+
+        EGLDisplay idpy = dp->disp[i].dpy;
+        if (cnx->egl.eglInitialize(idpy, &cnx->major, &cnx->minor)) {
             //LOGD("initialized %d dpy=%p, ver=%d.%d, cnx=%p",
-            //        i, dp->dpys[i], cnx->major, cnx->minor, cnx);
+            //        i, idpy, cnx->major, cnx->minor, cnx);
+
+            // display is now initialized
+            dp->disp[i].state = egl_display_t::INITIALIZED;
 
             // get the query-strings for this display for each implementation
-            dp->queryString[i].vendor =
-                cnx->hooks->egl.eglQueryString(dp->dpys[i], EGL_VENDOR);
-            dp->queryString[i].version =
-                cnx->hooks->egl.eglQueryString(dp->dpys[i], EGL_VERSION);
-            dp->queryString[i].extensions = strdup(
-                    cnx->hooks->egl.eglQueryString(dp->dpys[i], EGL_EXTENSIONS));
-            dp->queryString[i].clientApi =
-                cnx->hooks->egl.eglQueryString(dp->dpys[i], EGL_CLIENT_APIS);
+            dp->disp[i].queryString.vendor =
+                cnx->egl.eglQueryString(idpy, EGL_VENDOR);
+            dp->disp[i].queryString.version =
+                cnx->egl.eglQueryString(idpy, EGL_VERSION);
+            dp->disp[i].queryString.extensions =
+                    cnx->egl.eglQueryString(idpy, EGL_EXTENSIONS);
+            dp->disp[i].queryString.clientApi =
+                cnx->egl.eglQueryString(idpy, EGL_CLIENT_APIS);
 
         } else {
-            LOGD("%d: eglInitialize() failed (%s)", 
-                    i, egl_strerror(cnx->hooks->egl.eglGetError()));
+            LOGW("%d: eglInitialize(%p) failed (%s)", i, idpy,
+                    egl_strerror(cnx->egl.eglGetError()));
         }
     }
 
     EGLBoolean res = EGL_FALSE;
-    for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
+    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso && cnx->major>=0 && cnx->minor>=0) {
             EGLint n;
-            if (cnx->hooks->egl.eglGetConfigs(dp->dpys[i], 0, 0, &n)) {
-                dp->configs[i] = (EGLConfig*)malloc(sizeof(EGLConfig)*n);
-                if (dp->configs[i]) {
-                    if (cnx->hooks->egl.eglGetConfigs(
-                            dp->dpys[i], dp->configs[i], n, &dp->numConfigs[i]))
+            if (cnx->egl.eglGetConfigs(dp->disp[i].dpy, 0, 0, &n)) {
+                dp->disp[i].config = (EGLConfig*)malloc(sizeof(EGLConfig)*n);
+                if (dp->disp[i].config) {
+                    if (cnx->egl.eglGetConfigs(
+                            dp->disp[i].dpy, dp->disp[i].config, n,
+                            &dp->disp[i].numConfigs))
                     {
                         // sort the configurations so we can do binary searches
-                        qsort(  dp->configs[i],
-                                dp->numConfigs[i],
+                        qsort(  dp->disp[i].config,
+                                dp->disp[i].numConfigs,
                                 sizeof(EGLConfig), cmp_configs);
 
                         dp->numTotalConfigs += n;
@@ -712,33 +737,36 @@
 
 EGLBoolean eglTerminate(EGLDisplay dpy)
 {
+    // NOTE: don't unload the drivers b/c some APIs can be called
+    // after eglTerminate() has been called. eglTerminate() only
+    // terminates an EGLDisplay, not a EGL itself.
+
     egl_display_t* const dp = get_display(dpy);
     if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
     if (android_atomic_dec(&dp->refs) != 1)
         return EGL_TRUE;
-        
+
     EGLBoolean res = EGL_FALSE;
-    for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
+    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
         egl_connection_t* const cnx = &gEGLImpl[i];
-        if (cnx->dso) {
-            cnx->hooks->egl.eglTerminate(dp->dpys[i]);
-            
-            /* REVISIT: it's unclear what to do if eglTerminate() fails,
-             * on one end we shouldn't care, on the other end if it fails
-             * it might not be safe to call dlclose() (there could be some
-             * threads around). */
-            
-            free(dp->configs[i]);
-            free((void*)dp->queryString[i].extensions);
-            dp->numConfigs[i] = 0;
-            dp->dpys[i] = EGL_NO_DISPLAY;
-            dlclose((void*)cnx->dso);
-            cnx->dso = 0;
+        if (cnx->dso && dp->disp[i].state == egl_display_t::INITIALIZED) {
+            if (cnx->egl.eglTerminate(dp->disp[i].dpy) == EGL_FALSE) {
+                LOGW("%d: eglTerminate(%p) failed (%s)", i, dp->disp[i].dpy,
+                        egl_strerror(cnx->egl.eglGetError()));
+            }
+            // REVISIT: it's unclear what to do if eglTerminate() fails
+            free(dp->disp[i].config);
+
+            dp->disp[i].numConfigs = 0;
+            dp->disp[i].config = 0;
+            dp->disp[i].state = egl_display_t::TERMINATED;
+
             res = EGL_TRUE;
         }
     }
-    free((void*)dp->extensionsString);
-    dp->extensionsString = 0;
+    
+    // TODO: all egl_object_t should be marked for termination
+    
     dp->numTotalConfigs = 0;
     clearTLS();
     return res;
@@ -761,8 +789,8 @@
         return EGL_TRUE;
     }
     GLint n = 0;
-    for (int j=0 ; j<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; j++) {
-        for (int i=0 ; i<dp->numConfigs[j] && config_size ; i++) {
+    for (int j=0 ; j<IMPL_NUM_IMPLEMENTATIONS ; j++) {
+        for (int i=0 ; i<dp->disp[j].numConfigs && config_size ; i++) {
             *configs++ = MAKE_CONFIG(j, i);
             config_size--;
             n++;
@@ -818,8 +846,8 @@
         
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso) {
-            cnx->hooks->egl.eglGetConfigAttrib(
-                    dp->dpys[i], dp->configs[i][index], 
+            cnx->egl.eglGetConfigAttrib(
+                    dp->disp[i].dpy, dp->disp[i].config[index], 
                     EGL_CONFIG_ID, &configId);
 
             // and switch to the new list
@@ -828,13 +856,13 @@
             // At this point, the only configuration that can match is
             // dp->configs[i][index], however, we don't know if it would be
             // rejected because of the other attributes, so we do have to call
-            // cnx->hooks->egl.eglChooseConfig() -- but we don't have to loop
+            // cnx->egl.eglChooseConfig() -- but we don't have to loop
             // through all the EGLimpl[].
             // We also know we can only get a single config back, and we know
             // which one.
 
-            res = cnx->hooks->egl.eglChooseConfig(
-                    dp->dpys[i], attrib_list, configs, config_size, &n);
+            res = cnx->egl.eglChooseConfig(
+                    dp->disp[i].dpy, attrib_list, configs, config_size, &n);
             if (res && n>0) {
                 // n has to be 0 or 1, by construction, and we already know
                 // which config it will return (since there can be only one).
@@ -849,17 +877,18 @@
         return res;
     }
 
-    for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
+    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso) {
-            if (cnx->hooks->egl.eglChooseConfig(
-                    dp->dpys[i], attrib_list, configs, config_size, &n)) {
+            if (cnx->egl.eglChooseConfig(
+                    dp->disp[i].dpy, attrib_list, configs, config_size, &n)) {
                 if (configs) {
                     // now we need to convert these client EGLConfig to our
                     // internal EGLConfig format. This is done in O(n log n).
                     for (int j=0 ; j<n ; j++) {
                         int index = binarySearch<EGLConfig>(
-                                dp->configs[i], 0, dp->numConfigs[i]-1, configs[j]);
+                                dp->disp[i].config, 0,
+                                dp->disp[i].numConfigs-1, configs[j]);
                         if (index >= 0) {
                             if (configs) {
                                 configs[j] = MAKE_CONFIG(i, index);
@@ -893,8 +922,8 @@
         *value = configToUniqueId(dp, i, index);
         return EGL_TRUE;
     }
-    return cnx->hooks->egl.eglGetConfigAttrib(
-            dp->dpys[i], dp->configs[i][index], attribute, value);
+    return cnx->egl.eglGetConfigAttrib(
+            dp->disp[i].dpy, dp->disp[i].config[index], attribute, value);
 }
 
 // ----------------------------------------------------------------------------
@@ -909,26 +938,12 @@
     int i=0, index=0;
     egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index);
     if (cnx) {
-        // window must be connected upon calling underlying
-        // eglCreateWindowSurface
-        if (window) {
-            window->incRef(window);
-            if (window->connect)
-                window->connect(window);
-        }
-
-        EGLSurface surface = cnx->hooks->egl.eglCreateWindowSurface(
-                dp->dpys[i], dp->configs[i][index], window, attrib_list);       
+        EGLSurface surface = cnx->egl.eglCreateWindowSurface(
+                dp->disp[i].dpy, dp->disp[i].config[index], window, attrib_list);       
         if (surface != EGL_NO_SURFACE) {
-            egl_surface_t* s = new egl_surface_t(dpy, surface, window, i, cnx);
+            egl_surface_t* s = new egl_surface_t(dpy, surface, i, cnx);
             return s;
         }
-        
-        // something went wrong, disconnect and free window
-        // (will disconnect() automatically)
-        if (window) {
-            window->decRef(window);
-        }        
     }
     return EGL_NO_SURFACE;
 }
@@ -941,10 +956,10 @@
     int i=0, index=0;
     egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index);
     if (cnx) {
-        EGLSurface surface = cnx->hooks->egl.eglCreatePixmapSurface(
-                dp->dpys[i], dp->configs[i][index], pixmap, attrib_list);
+        EGLSurface surface = cnx->egl.eglCreatePixmapSurface(
+                dp->disp[i].dpy, dp->disp[i].config[index], pixmap, attrib_list);
         if (surface != EGL_NO_SURFACE) {
-            egl_surface_t* s = new egl_surface_t(dpy, surface, NULL, i, cnx);
+            egl_surface_t* s = new egl_surface_t(dpy, surface, i, cnx);
             return s;
         }
     }
@@ -958,10 +973,10 @@
     int i=0, index=0;
     egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index);
     if (cnx) {
-        EGLSurface surface = cnx->hooks->egl.eglCreatePbufferSurface(
-                dp->dpys[i], dp->configs[i][index], attrib_list);
+        EGLSurface surface = cnx->egl.eglCreatePbufferSurface(
+                dp->disp[i].dpy, dp->disp[i].config[index], attrib_list);
         if (surface != EGL_NO_SURFACE) {
-            egl_surface_t* s = new egl_surface_t(dpy, surface, NULL, i, cnx);
+            egl_surface_t* s = new egl_surface_t(dpy, surface, i, cnx);
             return s;
         }
     }
@@ -970,28 +985,35 @@
                                     
 EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
 {
+    SurfaceRef _s(surface);
+    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
+
     if (!validate_display_surface(dpy, surface))
         return EGL_FALSE;    
     egl_display_t const * const dp = get_display(dpy);
-    egl_surface_t const * const s = get_surface(surface);
 
-    EGLBoolean result = s->cnx->hooks->egl.eglDestroySurface(
-            dp->dpys[s->impl], s->surface);
-    
-    delete s;
+    egl_surface_t * const s = get_surface(surface);
+    EGLBoolean result = s->cnx->egl.eglDestroySurface(
+            dp->disp[s->impl].dpy, s->surface);
+    if (result == EGL_TRUE) {
+        _s.terminate();
+    }
     return result;
 }
 
 EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface,
                             EGLint attribute, EGLint *value)
 {
+    SurfaceRef _s(surface);
+    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
+
     if (!validate_display_surface(dpy, surface))
         return EGL_FALSE;    
     egl_display_t const * const dp = get_display(dpy);
     egl_surface_t const * const s = get_surface(surface);
 
-    return s->cnx->hooks->egl.eglQuerySurface(
-            dp->dpys[s->impl], s->surface, attribute, value);
+    return s->cnx->egl.eglQuerySurface(
+            dp->disp[s->impl].dpy, s->surface, attribute, value);
 }
 
 // ----------------------------------------------------------------------------
@@ -1005,10 +1027,26 @@
     int i=0, index=0;
     egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index);
     if (cnx) {
-        EGLContext context = cnx->hooks->egl.eglCreateContext(
-                dp->dpys[i], dp->configs[i][index], share_list, attrib_list);
+        EGLContext context = cnx->egl.eglCreateContext(
+                dp->disp[i].dpy, dp->disp[i].config[index],
+                share_list, attrib_list);
         if (context != EGL_NO_CONTEXT) {
-            egl_context_t* c = new egl_context_t(dpy, context, i, cnx);
+            // figure out if it's a GLESv1 or GLESv2
+            int version = 0;
+            if (attrib_list) {
+                while (*attrib_list != EGL_NONE) {
+                    GLint attr = *attrib_list++;
+                    GLint value = *attrib_list++;
+                    if (attr == EGL_CONTEXT_CLIENT_VERSION) {
+                        if (value == 1) {
+                            version = GLESv1_INDEX;
+                        } else if (value == 2) {
+                            version = GLESv2_INDEX;
+                        }
+                    }
+                };
+            }
+            egl_context_t* c = new egl_context_t(dpy, context, i, cnx, version);
             return c;
         }
     }
@@ -1017,66 +1055,125 @@
 
 EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
 {
+    ContextRef _c(ctx);
+    if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
+    
     if (!validate_display_context(dpy, ctx))
         return EGL_FALSE;
     egl_display_t const * const dp = get_display(dpy);
     egl_context_t * const c = get_context(ctx);
-    EGLBoolean result = c->cnx->hooks->egl.eglDestroyContext(
-            dp->dpys[c->impl], c->context);
-    delete c;
+    EGLBoolean result = c->cnx->egl.eglDestroyContext(
+            dp->disp[c->impl].dpy, c->context);
+    if (result == EGL_TRUE) {
+        _c.terminate();
+    }
     return result;
 }
 
 EGLBoolean eglMakeCurrent(  EGLDisplay dpy, EGLSurface draw,
                             EGLSurface read, EGLContext ctx)
 {
+    // get a reference to the object passed in
+    ContextRef _c(ctx);
+    SurfaceRef _d(draw);
+    SurfaceRef _r(read);
+
+    // validate the display and the context (if not EGL_NO_CONTEXT)
     egl_display_t const * const dp = get_display(dpy);
     if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
-
-    if (read == EGL_NO_SURFACE && draw  == EGL_NO_SURFACE &&
-            ctx == EGL_NO_CONTEXT) 
-    {
-        EGLBoolean result = EGL_TRUE;
-        ctx = getContext();
-        if (ctx) {
-            egl_context_t * const c = get_context(ctx);
-            result = c->cnx->hooks->egl.eglMakeCurrent(dp->dpys[c->impl], 0, 0, 0);
-            if (result == EGL_TRUE) {
-                setGlThreadSpecific(&gHooks[IMPL_NO_CONTEXT]);
-                setContext(EGL_NO_CONTEXT);
-            }
-        }
-        return result;
+    if ((ctx != EGL_NO_CONTEXT) && (!validate_display_context(dpy, ctx))) {
+        // EGL_NO_CONTEXT is valid
+        return EGL_FALSE;
     }
 
-    if (!validate_display_context(dpy, ctx))
-        return EGL_FALSE;    
-    
+    // these are the underlying implementation's object
+    EGLContext impl_ctx  = EGL_NO_CONTEXT;
     EGLSurface impl_draw = EGL_NO_SURFACE;
     EGLSurface impl_read = EGL_NO_SURFACE;
-    egl_context_t * const c = get_context(ctx);
+
+    // these are our objects structs passed in
+    egl_context_t       * c = NULL;
+    egl_surface_t const * d = NULL;
+    egl_surface_t const * r = NULL;
+
+    // these are the current objects structs
+    egl_context_t * cur_c = get_context(getContext());
+    egl_surface_t * cur_r = NULL;
+    egl_surface_t * cur_d = NULL;
+    
+    if (ctx != EGL_NO_CONTEXT) {
+        c = get_context(ctx);
+        cur_r = get_surface(c->read);
+        cur_d = get_surface(c->draw);
+        impl_ctx = c->context;
+    } else {
+        // no context given, use the implementation of the current context
+        if (cur_c == NULL) {
+            // no current context
+            if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) {
+                // calling eglMakeCurrent( ..., EGL_NO_CONTEXT, !=0, !=0);
+                return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+            }
+            // not an error, there is just not current context.
+            return EGL_TRUE;
+        }
+    }
+
+    // retrieve the underlying implementation's draw EGLSurface
     if (draw != EGL_NO_SURFACE) {
-        egl_surface_t const * d = get_surface(draw);
-        if (!d) return setError(EGL_BAD_SURFACE, EGL_FALSE);
-        if (d->impl != c->impl)
+        d = get_surface(draw);
+        // make sure the EGLContext and EGLSurface passed in are for
+        // the same driver
+        if (c && d->impl != c->impl)
             return setError(EGL_BAD_MATCH, EGL_FALSE);
         impl_draw = d->surface;
     }
+
+    // retrieve the underlying implementation's read EGLSurface
     if (read != EGL_NO_SURFACE) {
-        egl_surface_t const * r = get_surface(read);
-        if (!r) return setError(EGL_BAD_SURFACE, EGL_FALSE);
-        if (r->impl != c->impl)
+        r = get_surface(read);
+        // make sure the EGLContext and EGLSurface passed in are for
+        // the same driver
+        if (c && r->impl != c->impl)
             return setError(EGL_BAD_MATCH, EGL_FALSE);
         impl_read = r->surface;
     }
-    EGLBoolean result = c->cnx->hooks->egl.eglMakeCurrent(
-            dp->dpys[c->impl], impl_draw, impl_read, c->context);
+
+    EGLBoolean result;
+
+    if (c) {
+        result = c->cnx->egl.eglMakeCurrent(
+                dp->disp[c->impl].dpy, impl_draw, impl_read, impl_ctx);
+    } else {
+        result = cur_c->cnx->egl.eglMakeCurrent(
+                dp->disp[cur_c->impl].dpy, impl_draw, impl_read, impl_ctx);
+    }
 
     if (result == EGL_TRUE) {
-        setGlThreadSpecific(c->cnx->hooks);
-        setContext(ctx);
-        c->read = read;
-        c->draw = draw;
+        // by construction, these are either 0 or valid (possibly terminated)
+        // it should be impossible for these to be invalid
+        ContextRef _cur_c(cur_c);
+        SurfaceRef _cur_r(cur_r);
+        SurfaceRef _cur_d(cur_d);
+
+        // cur_c has to be valid here (but could be terminated)
+        if (ctx != EGL_NO_CONTEXT) {
+            setGlThreadSpecific(c->cnx->hooks[c->version]);
+            setContext(ctx);
+            _c.acquire();
+        } else {
+            setGlThreadSpecific(&gHooksNoContext);
+            setContext(EGL_NO_CONTEXT);
+        }
+        _cur_c.release();
+
+        _r.acquire();
+        _cur_r.release();
+        if (c) c->read = read;
+
+        _d.acquire();
+        _cur_d.release();
+        if (c) c->draw = draw;
     }
     return result;
 }
@@ -1085,24 +1182,33 @@
 EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
                             EGLint attribute, EGLint *value)
 {
+    ContextRef _c(ctx);
+    if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
+
     if (!validate_display_context(dpy, ctx))
         return EGL_FALSE;    
     
     egl_display_t const * const dp = get_display(dpy);
     egl_context_t * const c = get_context(ctx);
 
-    return c->cnx->hooks->egl.eglQueryContext(
-            dp->dpys[c->impl], c->context, attribute, value);
+    return c->cnx->egl.eglQueryContext(
+            dp->disp[c->impl].dpy, c->context, attribute, value);
 }
 
 EGLContext eglGetCurrentContext(void)
 {
+    // could be called before eglInitialize(), but we wouldn't have a context
+    // then, and this function would correctly return EGL_NO_CONTEXT.
+
     EGLContext ctx = getContext();
     return ctx;
 }
 
 EGLSurface eglGetCurrentSurface(EGLint readdraw)
 {
+    // could be called before eglInitialize(), but we wouldn't have a context
+    // then, and this function would correctly return EGL_NO_SURFACE.
+
     EGLContext ctx = getContext();
     if (ctx) {
         egl_context_t const * const c = get_context(ctx);
@@ -1118,6 +1224,9 @@
 
 EGLDisplay eglGetCurrentDisplay(void)
 {
+    // could be called before eglInitialize(), but we wouldn't have a context
+    // then, and this function would correctly return EGL_NO_DISPLAY.
+
     EGLContext ctx = getContext();
     if (ctx) {
         egl_context_t const * const c = get_context(ctx);
@@ -1129,6 +1238,9 @@
 
 EGLBoolean eglWaitGL(void)
 {
+    // could be called before eglInitialize(), but we wouldn't have a context
+    // then, and this function would return GL_TRUE, which isn't wrong.
+
     EGLBoolean res = EGL_TRUE;
     EGLContext ctx = getContext();
     if (ctx) {
@@ -1139,13 +1251,16 @@
         egl_connection_t* const cnx = &gEGLImpl[c->impl];
         if (!cnx->dso) 
             return setError(EGL_BAD_CONTEXT, EGL_FALSE);
-        res = cnx->hooks->egl.eglWaitGL();
+        res = cnx->egl.eglWaitGL();
     }
     return res;
 }
 
 EGLBoolean eglWaitNative(EGLint engine)
 {
+    // could be called before eglInitialize(), but we wouldn't have a context
+    // then, and this function would return GL_TRUE, which isn't wrong.
+    
     EGLBoolean res = EGL_TRUE;
     EGLContext ctx = getContext();
     if (ctx) {
@@ -1156,7 +1271,7 @@
         egl_connection_t* const cnx = &gEGLImpl[c->impl];
         if (!cnx->dso) 
             return setError(EGL_BAD_CONTEXT, EGL_FALSE);
-        res = cnx->hooks->egl.eglWaitNative(engine);
+        res = cnx->egl.eglWaitNative(engine);
     }
     return res;
 }
@@ -1164,11 +1279,11 @@
 EGLint eglGetError(void)
 {
     EGLint result = EGL_SUCCESS;
-    for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
+    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
         EGLint err = EGL_SUCCESS;
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso)
-            err = cnx->hooks->egl.eglGetError();
+            err = cnx->egl.eglGetError();
         if (err!=EGL_SUCCESS && result==EGL_SUCCESS)
             result = err;
     }
@@ -1182,9 +1297,11 @@
     // eglGetProcAddress() could be the very first function called
     // in which case we must make sure we've initialized ourselves, this
     // happens the first time egl_get_display() is called.
-    
-    if (egl_init_displays(EGL_DEFAULT_DISPLAY) == EGL_NO_DISPLAY)
-        return NULL;
+
+    if (egl_init_drivers() == EGL_FALSE) {
+        setError(EGL_BAD_PARAMETER, NULL);
+        return  NULL;
+    }
 
     __eglMustCastToProperFunctionPointerType addr;
     addr = findProcAddress(procname, gExtentionMap, NELEM(gExtentionMap));
@@ -1197,11 +1314,11 @@
     
     addr = 0;
     int slot = -1;
-    for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
+    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso) {
-            if (cnx->hooks->egl.eglGetProcAddress) {
-                addr = cnx->hooks->egl.eglGetProcAddress(procname);
+            if (cnx->egl.eglGetProcAddress) {
+                addr = cnx->egl.eglGetProcAddress(procname);
                 if (addr) {
                     if (slot == -1) {
                         slot = 0; // XXX: find free slot
@@ -1210,7 +1327,7 @@
                             break;
                         }
                     }
-                    cnx->hooks->ext.extensions[slot] = addr;
+                    //cnx->hooks->ext.extensions[slot] = addr;
                 }
             }
         }
@@ -1243,22 +1360,28 @@
 
 EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
 {
+    SurfaceRef _s(draw);
+    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
+
     if (!validate_display_surface(dpy, draw))
         return EGL_FALSE;    
     egl_display_t const * const dp = get_display(dpy);
     egl_surface_t const * const s = get_surface(draw);
-    return s->cnx->hooks->egl.eglSwapBuffers(dp->dpys[s->impl], s->surface);
+    return s->cnx->egl.eglSwapBuffers(dp->disp[s->impl].dpy, s->surface);
 }
 
 EGLBoolean eglCopyBuffers(  EGLDisplay dpy, EGLSurface surface,
                             NativePixmapType target)
 {
+    SurfaceRef _s(surface);
+    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
+
     if (!validate_display_surface(dpy, surface))
         return EGL_FALSE;    
     egl_display_t const * const dp = get_display(dpy);
     egl_surface_t const * const s = get_surface(surface);
-    return s->cnx->hooks->egl.eglCopyBuffers(
-            dp->dpys[s->impl], s->surface, target);
+    return s->cnx->egl.eglCopyBuffers(
+            dp->disp[s->impl].dpy, s->surface, target);
 }
 
 const char* eglQueryString(EGLDisplay dpy, EGLint name)
@@ -1285,13 +1408,16 @@
 EGLBoolean eglSurfaceAttrib(
         EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
 {
+    SurfaceRef _s(surface);
+    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
+
     if (!validate_display_surface(dpy, surface))
         return EGL_FALSE;    
     egl_display_t const * const dp = get_display(dpy);
     egl_surface_t const * const s = get_surface(surface);
-    if (s->cnx->hooks->egl.eglSurfaceAttrib) {
-        return s->cnx->hooks->egl.eglSurfaceAttrib(
-                dp->dpys[s->impl], s->surface, attribute, value);
+    if (s->cnx->egl.eglSurfaceAttrib) {
+        return s->cnx->egl.eglSurfaceAttrib(
+                dp->disp[s->impl].dpy, s->surface, attribute, value);
     }
     return setError(EGL_BAD_SURFACE, EGL_FALSE);
 }
@@ -1299,13 +1425,16 @@
 EGLBoolean eglBindTexImage(
         EGLDisplay dpy, EGLSurface surface, EGLint buffer)
 {
+    SurfaceRef _s(surface);
+    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
+
     if (!validate_display_surface(dpy, surface))
         return EGL_FALSE;    
     egl_display_t const * const dp = get_display(dpy);
     egl_surface_t const * const s = get_surface(surface);
-    if (s->cnx->hooks->egl.eglBindTexImage) {
-        return s->cnx->hooks->egl.eglBindTexImage(
-                dp->dpys[s->impl], s->surface, buffer);
+    if (s->cnx->egl.eglBindTexImage) {
+        return s->cnx->egl.eglBindTexImage(
+                dp->disp[s->impl].dpy, s->surface, buffer);
     }
     return setError(EGL_BAD_SURFACE, EGL_FALSE);
 }
@@ -1313,13 +1442,16 @@
 EGLBoolean eglReleaseTexImage(
         EGLDisplay dpy, EGLSurface surface, EGLint buffer)
 {
+    SurfaceRef _s(surface);
+    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
+
     if (!validate_display_surface(dpy, surface))
         return EGL_FALSE;    
     egl_display_t const * const dp = get_display(dpy);
     egl_surface_t const * const s = get_surface(surface);
-    if (s->cnx->hooks->egl.eglReleaseTexImage) {
-        return s->cnx->hooks->egl.eglReleaseTexImage(
-                dp->dpys[s->impl], s->surface, buffer);
+    if (s->cnx->egl.eglReleaseTexImage) {
+        return s->cnx->egl.eglReleaseTexImage(
+                dp->disp[s->impl].dpy, s->surface, buffer);
     }
     return setError(EGL_BAD_SURFACE, EGL_FALSE);
 }
@@ -1330,11 +1462,12 @@
     if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
 
     EGLBoolean res = EGL_TRUE;
-    for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
+    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso) {
-            if (cnx->hooks->egl.eglSwapInterval) {
-                if (cnx->hooks->egl.eglSwapInterval(dp->dpys[i], interval) == EGL_FALSE) {
+            if (cnx->egl.eglSwapInterval) {
+                if (cnx->egl.eglSwapInterval(
+                        dp->disp[i].dpy, interval) == EGL_FALSE) {
                     res = EGL_FALSE;
                 }
             }
@@ -1350,6 +1483,8 @@
 
 EGLBoolean eglWaitClient(void)
 {
+    // could be called before eglInitialize(), but we wouldn't have a context
+    // then, and this function would return GL_TRUE, which isn't wrong.
     EGLBoolean res = EGL_TRUE;
     EGLContext ctx = getContext();
     if (ctx) {
@@ -1360,10 +1495,10 @@
         egl_connection_t* const cnx = &gEGLImpl[c->impl];
         if (!cnx->dso) 
             return setError(EGL_BAD_CONTEXT, EGL_FALSE);
-        if (cnx->hooks->egl.eglWaitClient) {
-            res = cnx->hooks->egl.eglWaitClient();
+        if (cnx->egl.eglWaitClient) {
+            res = cnx->egl.eglWaitClient();
         } else {
-            res = cnx->hooks->egl.eglWaitGL();
+            res = cnx->egl.eglWaitGL();
         }
     }
     return res;
@@ -1371,13 +1506,17 @@
 
 EGLBoolean eglBindAPI(EGLenum api)
 {
+    if (egl_init_drivers() == EGL_FALSE) {
+        return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+    }
+
     // bind this API on all EGLs
     EGLBoolean res = EGL_TRUE;
-    for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
+    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso) {
-            if (cnx->hooks->egl.eglBindAPI) {
-                if (cnx->hooks->egl.eglBindAPI(api) == EGL_FALSE) {
+            if (cnx->egl.eglBindAPI) {
+                if (cnx->egl.eglBindAPI(api) == EGL_FALSE) {
                     res = EGL_FALSE;
                 }
             }
@@ -1388,13 +1527,17 @@
 
 EGLenum eglQueryAPI(void)
 {
-    for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
+    if (egl_init_drivers() == EGL_FALSE) {
+        return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+    }
+
+    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso) {
-            if (cnx->hooks->egl.eglQueryAPI) {
+            if (cnx->egl.eglQueryAPI) {
                 // the first one we find is okay, because they all
                 // should be the same
-                return cnx->hooks->egl.eglQueryAPI();
+                return cnx->egl.eglQueryAPI();
             }
         }
     }
@@ -1404,11 +1547,11 @@
 
 EGLBoolean eglReleaseThread(void)
 {
-    for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
+    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso) {
-            if (cnx->hooks->egl.eglReleaseThread) {
-                cnx->hooks->egl.eglReleaseThread();
+            if (cnx->egl.eglReleaseThread) {
+                cnx->egl.eglReleaseThread();
             }
         }
     }
@@ -1424,9 +1567,194 @@
     int i=0, index=0;
     egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index);
     if (!cnx) return EGL_FALSE;
-    if (cnx->hooks->egl.eglCreatePbufferFromClientBuffer) {
-        return cnx->hooks->egl.eglCreatePbufferFromClientBuffer(
-                dp->dpys[i], buftype, buffer, dp->configs[i][index], attrib_list);
+    if (cnx->egl.eglCreatePbufferFromClientBuffer) {
+        return cnx->egl.eglCreatePbufferFromClientBuffer(
+                dp->disp[i].dpy, buftype, buffer, 
+                dp->disp[i].config[index], attrib_list);
     }
     return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
 }
+
+// ----------------------------------------------------------------------------
+// EGL_EGLEXT_VERSION 3
+// ----------------------------------------------------------------------------
+
+EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
+        const EGLint *attrib_list)
+{
+    SurfaceRef _s(surface);
+    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
+
+    if (!validate_display_surface(dpy, surface))
+        return EGL_FALSE;
+
+    egl_display_t const * const dp = get_display(dpy);
+    egl_surface_t const * const s = get_surface(surface);
+
+    if (s->cnx->egl.eglLockSurfaceKHR) {
+        return s->cnx->egl.eglLockSurfaceKHR(
+                dp->disp[s->impl].dpy, s->surface, attrib_list);
+    }
+    return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+}
+
+EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
+{
+    SurfaceRef _s(surface);
+    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
+
+    if (!validate_display_surface(dpy, surface))
+        return EGL_FALSE;
+
+    egl_display_t const * const dp = get_display(dpy);
+    egl_surface_t const * const s = get_surface(surface);
+
+    if (s->cnx->egl.eglUnlockSurfaceKHR) {
+        return s->cnx->egl.eglUnlockSurfaceKHR(
+                dp->disp[s->impl].dpy, s->surface);
+    }
+    return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+}
+
+EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
+        EGLClientBuffer buffer, const EGLint *attrib_list)
+{
+    if (ctx != EGL_NO_CONTEXT) {
+        ContextRef _c(ctx);
+        if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
+        if (!validate_display_context(dpy, ctx))
+            return EGL_NO_IMAGE_KHR;
+        egl_display_t const * const dp = get_display(dpy);
+        egl_context_t * const c = get_context(ctx);
+        // since we have an EGLContext, we know which implementation to use
+        EGLImageKHR image = c->cnx->egl.eglCreateImageKHR(
+                dp->disp[c->impl].dpy, c->context, target, buffer, attrib_list);
+        if (image == EGL_NO_IMAGE_KHR)
+            return image;
+            
+        egl_image_t* result = new egl_image_t(dpy, ctx);
+        result->images[c->impl] = image;
+        return (EGLImageKHR)result;
+    } else {
+        // EGL_NO_CONTEXT is a valid parameter
+        egl_display_t const * const dp = get_display(dpy);
+        if (dp == 0) {
+            return setError(EGL_BAD_DISPLAY, EGL_NO_IMAGE_KHR);
+        }
+
+        /* Since we don't have a way to know which implementation to call,
+         * we're calling all of them. If at least one of the implementation
+         * succeeded, this is a success.
+         */
+
+        EGLint currentError = eglGetError();
+
+        EGLImageKHR implImages[IMPL_NUM_IMPLEMENTATIONS];
+        bool success = false;
+        for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
+            egl_connection_t* const cnx = &gEGLImpl[i];
+            implImages[i] = EGL_NO_IMAGE_KHR;
+            if (cnx->dso) {
+                if (cnx->egl.eglCreateImageKHR) {
+                    implImages[i] = cnx->egl.eglCreateImageKHR(
+                            dp->disp[i].dpy, ctx, target, buffer, attrib_list);
+                    if (implImages[i] != EGL_NO_IMAGE_KHR) {
+                        success = true;
+                    }
+                }
+            }
+        }
+
+        if (!success) {
+            // failure, if there was an error when we entered this function,
+            // the error flag must not be updated.
+            // Otherwise, the error is whatever happened in the implementation
+            // that faulted.
+            if (currentError != EGL_SUCCESS) {
+                setError(currentError, EGL_NO_IMAGE_KHR);
+            }
+            return EGL_NO_IMAGE_KHR;
+        } else {
+            // In case of success, we need to clear all error flags
+            // (especially those caused by the implementation that didn't
+            // succeed). TODO: we could avoid this if we knew this was
+            // a "full" success (all implementation succeeded).
+            eglGetError();
+        }
+
+        egl_image_t* result = new egl_image_t(dpy, ctx);
+        memcpy(result->images, implImages, sizeof(implImages));
+        return (EGLImageKHR)result;
+    }
+}
+
+EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
+{
+    egl_display_t const * const dp = get_display(dpy);
+     if (dp == 0) {
+         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+     }
+
+     ImageRef _i(img);
+     if (!_i.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+
+     egl_image_t* image = get_image(img);
+     bool success = false;
+     for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
+         egl_connection_t* const cnx = &gEGLImpl[i];
+         if (image->images[i] != EGL_NO_IMAGE_KHR) {
+             if (cnx->dso) {
+                 if (cnx->egl.eglCreateImageKHR) {
+                     if (cnx->egl.eglDestroyImageKHR(
+                             dp->disp[i].dpy, image->images[i])) {
+                         success = true;
+                     }
+                 }
+             }
+         }
+     }
+     if (!success)
+         return EGL_FALSE;
+
+     _i.terminate();
+
+     return EGL_TRUE;
+}
+
+
+// ----------------------------------------------------------------------------
+// ANDROID extensions
+// ----------------------------------------------------------------------------
+
+EGLBoolean eglSetSwapRectangleANDROID(EGLDisplay dpy, EGLSurface draw,
+        EGLint left, EGLint top, EGLint width, EGLint height)
+{
+    SurfaceRef _s(draw);
+    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
+
+    if (!validate_display_surface(dpy, draw))
+        return EGL_FALSE;    
+    egl_display_t const * const dp = get_display(dpy);
+    egl_surface_t const * const s = get_surface(draw);
+    if (s->cnx->egl.eglSetSwapRectangleANDROID) {
+        return s->cnx->egl.eglSetSwapRectangleANDROID(
+                dp->disp[s->impl].dpy, s->surface, left, top, width, height);
+    }
+    return setError(EGL_BAD_DISPLAY, NULL);
+}
+
+EGLClientBuffer eglGetRenderBufferANDROID(EGLDisplay dpy, EGLSurface draw)
+{
+    SurfaceRef _s(draw);
+    if (!_s.get()) return setError(EGL_BAD_SURFACE, (EGLClientBuffer*)0);
+
+    if (!validate_display_surface(dpy, draw))
+        return 0;    
+    egl_display_t const * const dp = get_display(dpy);
+    egl_surface_t const * const s = get_surface(draw);
+    if (s->cnx->egl.eglGetRenderBufferANDROID) {
+        return s->cnx->egl.eglGetRenderBufferANDROID(
+                dp->disp[s->impl].dpy, s->surface);
+    }
+    return setError(EGL_BAD_DISPLAY, (EGLClientBuffer*)0);
+}
diff --git a/opengl/libs/egl_entries.in b/opengl/libs/EGL/egl_entries.in
similarity index 92%
rename from opengl/libs/egl_entries.in
rename to opengl/libs/EGL/egl_entries.in
index 3b4551b..5d89287 100644
--- a/opengl/libs/egl_entries.in
+++ b/opengl/libs/EGL/egl_entries.in
@@ -50,3 +50,8 @@
 EGL_ENTRY(EGLBoolean,  eglUnlockSurfaceKHR, EGLDisplay, EGLSurface)
 EGL_ENTRY(EGLImageKHR, eglCreateImageKHR,   EGLDisplay, EGLContext, EGLenum, EGLClientBuffer, const EGLint *)
 EGL_ENTRY(EGLBoolean,  eglDestroyImageKHR,  EGLDisplay, EGLImageKHR)
+
+/* ANDROID extensions */
+
+EGL_ENTRY(EGLBoolean, eglSetSwapRectangleANDROID, EGLDisplay, EGLSurface, EGLint, EGLint, EGLint, EGLint)
+EGL_ENTRY(EGLClientBuffer, eglGetRenderBufferANDROID, EGLDisplay, EGLSurface)
diff --git a/opengl/libs/EGL/gpu.cpp b/opengl/libs/EGL/gpu.cpp
deleted file mode 100644
index 4c902c8..0000000
--- a/opengl/libs/EGL/gpu.cpp
+++ /dev/null
@@ -1,217 +0,0 @@
-/* 
- ** 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 "EGL"
-
-#include <ctype.h>
-#include <string.h>
-#include <errno.h>
-
-#include <sys/ioctl.h>
-
-#if HAVE_ANDROID_OS
-#include <linux/android_pmem.h>
-#endif
-
-#include <cutils/log.h>
-#include <cutils/properties.h>
-
-#include <utils/IMemory.h>
-#include <utils/threads.h>
-#include <utils/IServiceManager.h>
-#include <utils/IPCThreadState.h>
-#include <utils/Parcel.h>
-
-#include <ui/EGLDisplaySurface.h>
-#include <ui/ISurfaceComposer.h>
-
-#include "hooks.h"
-#include "egl_impl.h"
-
-// ----------------------------------------------------------------------------
-namespace android {
-// ----------------------------------------------------------------------------
-
-/*
- * we provide our own allocators for the GPU regions, these
- * allocators go through surfaceflinger 
- */
-
-static Mutex                            gRegionsLock;
-static request_gpu_t                    gRegions;
-static sp<ISurfaceComposer>             gSurfaceManager;
-GL_API ISurfaceComposer*                GLES_localSurfaceManager = 0;
-
-extern egl_connection_t gEGLImpl[2];
-
-const sp<ISurfaceComposer>& getSurfaceFlinger()
-{
-    Mutex::Autolock _l(gRegionsLock);
-
-    /*
-     * There is a little bit of voodoo magic here. We want to access
-     * surfaceflinger for allocating GPU regions, however, when we are
-     * running as part of surfaceflinger, we want to bypass the
-     * service manager because surfaceflinger might not be registered yet.
-     * SurfaceFlinger will populate "GLES_localSurfaceManager" with its
-     * own address, so we can just use that.
-     */
-    if (gSurfaceManager == 0) {
-        if (GLES_localSurfaceManager) {
-            // we're running in SurfaceFlinger's context
-            gSurfaceManager =  GLES_localSurfaceManager;
-        } else {
-            // we're a remote process or not part of surfaceflinger,
-            // go through the service manager
-            sp<IServiceManager> sm = defaultServiceManager();
-            if (sm != NULL) {
-                sp<IBinder> binder = sm->getService(String16("SurfaceFlinger"));
-                gSurfaceManager = interface_cast<ISurfaceComposer>(binder);
-            }
-        }
-    }
-    return gSurfaceManager;
-}
-
-class GPURevokeRequester : public BnGPUCallback
-{
-public:
-    virtual void gpuLost() {
-        LOGD("CONTEXT_LOST: Releasing GPU upon request from SurfaceFlinger.");
-        gEGLImpl[IMPL_HARDWARE].hooks = &gHooks[IMPL_CONTEXT_LOST];
-    }
-};
-
-static sp<GPURevokeRequester> gRevokerCallback;
-
-
-request_gpu_t* gpu_acquire(void* user)
-{
-    sp<ISurfaceComposer> server( getSurfaceFlinger() );
-
-    Mutex::Autolock _l(gRegionsLock);
-    if (server == NULL) {
-        return 0;
-    }
-    
-    ISurfaceComposer::gpu_info_t info;
-    
-    if (gRevokerCallback == 0)
-        gRevokerCallback = new GPURevokeRequester();
-
-    status_t err = server->requestGPU(gRevokerCallback, &info);
-    if (err != NO_ERROR) {
-        LOGD("requestGPU returned %d", err);
-        return 0;
-    }
-
-    if (info.regs == 0) {
-        LOGD("requestGPU() failed");
-        return 0;
-    }
-
-    bool failed = false;
-    request_gpu_t* gpu = &gRegions;
-    memset(gpu, 0, sizeof(*gpu));
-    
-    if (info.regs != 0) {
-        sp<IMemoryHeap> heap(info.regs->getMemory());
-        if (heap != 0) {
-            int fd = heap->heapID();
-            gpu->regs.fd = fd;
-            gpu->regs.base = info.regs->pointer(); 
-            gpu->regs.size = info.regs->size(); 
-            gpu->regs.user = info.regs.get();
-#if HAVE_ANDROID_OS
-            struct pmem_region region;
-            if (ioctl(fd, PMEM_GET_PHYS, &region) >= 0)
-                gpu->regs.phys = (void*)region.offset;
-#endif
-            info.regs->incStrong(gpu);
-        } else {
-            LOGE("GPU register handle %p is invalid!", info.regs.get());
-            failed = true;
-        }
-    }
-
-    for (size_t i=0 ; i<info.count && !failed ; i++) {
-        sp<IMemory>& region(info.regions[i].region);
-        if (region != 0) {
-            sp<IMemoryHeap> heap(region->getMemory());
-            if (heap != 0) {
-                const int fd = heap->heapID();
-                gpu->gpu[i].fd = fd;
-                gpu->gpu[i].base = region->pointer(); 
-                gpu->gpu[i].size = region->size(); 
-                gpu->gpu[i].user = region.get();
-                gpu->gpu[i].offset = info.regions[i].reserved;
-#if HAVE_ANDROID_OS
-                struct pmem_region reg;
-                if (ioctl(fd, PMEM_GET_PHYS, &reg) >= 0)
-                    gpu->gpu[i].phys = (void*)reg.offset;
-#endif
-                region->incStrong(gpu);
-            } else {
-                LOGE("GPU region handle [%d, %p] is invalid!", i, region.get());
-                failed = true;
-            }
-        }
-    }
-    
-    if (failed) {
-        // something went wrong, clean up everything!
-        if (gpu->regs.user) {
-            static_cast<IMemory*>(gpu->regs.user)->decStrong(gpu);
-            for (size_t i=0 ; i<info.count ; i++) {
-                if (gpu->gpu[i].user) {
-                    static_cast<IMemory*>(gpu->gpu[i].user)->decStrong(gpu);
-                }
-            }
-        }
-    }
-    
-    gpu->count = info.count;
-    return gpu;
-}
-
-int gpu_release(void*, request_gpu_t* gpu)
-{
-    sp<IMemory> regs;
-
-    { // scope for lock
-        Mutex::Autolock _l(gRegionsLock);
-        regs = static_cast<IMemory*>(gpu->regs.user);   
-        gpu->regs.user = 0;
-        if (regs != 0) regs->decStrong(gpu);
-        
-        for (int i=0 ; i<gpu->count ; i++) {
-            sp<IMemory> r(static_cast<IMemory*>(gpu->gpu[i].user));
-            gpu->gpu[i].user = 0;
-            if (r != 0) r->decStrong(gpu);
-        }
-    }
-    
-    // there is a special transaction to relinquish the GPU
-    // (it will happen automatically anyway if we don't do this)
-    Parcel data, reply;
-    // NOTE: this transaction does not require an interface token
-    regs->asBinder()->transact(1000, data, &reply);
-    return 1;
-}
-
-// ----------------------------------------------------------------------------
-}; // namespace android
-// ----------------------------------------------------------------------------
diff --git a/opengl/libs/EGL/hooks.cpp b/opengl/libs/EGL/hooks.cpp
new file mode 100644
index 0000000..72ad6b3
--- /dev/null
+++ b/opengl/libs/EGL/hooks.cpp
@@ -0,0 +1,60 @@
+/* 
+ ** Copyright 2009, 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 <ctype.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include <cutils/log.h>
+
+#include "hooks.h"
+
+// ----------------------------------------------------------------------------
+namespace android {
+// ----------------------------------------------------------------------------
+
+void gl_unimplemented() {
+    LOGE("called unimplemented OpenGL ES API");
+}
+
+
+// ----------------------------------------------------------------------------
+// GL / EGL hooks
+// ----------------------------------------------------------------------------
+
+#undef GL_ENTRY
+#undef EGL_ENTRY
+#define GL_ENTRY(_r, _api, ...) #_api,
+#define EGL_ENTRY(_r, _api, ...) #_api,
+
+char const * const gl_names[] = {
+    #include "entries.in"
+    NULL
+};
+
+char const * const egl_names[] = {
+    #include "egl_entries.in"
+    NULL
+};
+
+#undef GL_ENTRY
+#undef EGL_ENTRY
+
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+// ----------------------------------------------------------------------------
+
diff --git a/opengl/libs/GLES2/gl2.cpp b/opengl/libs/GLES2/gl2.cpp
new file mode 100644
index 0000000..b8e3283
--- /dev/null
+++ b/opengl/libs/GLES2/gl2.cpp
@@ -0,0 +1,119 @@
+/* 
+ ** 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.
+ */
+
+#include <ctype.h>
+#include <string.h>
+#include <errno.h>
+
+#include <sys/ioctl.h>
+
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+#include <cutils/log.h>
+#include <cutils/properties.h>
+
+#include "hooks.h"
+#include "egl_impl.h"
+
+using namespace android;
+
+// ----------------------------------------------------------------------------
+// Actual GL entry-points
+// ----------------------------------------------------------------------------
+
+#undef API_ENTRY
+#undef CALL_GL_API
+#undef CALL_GL_API_RETURN
+
+#if USE_FAST_TLS_KEY
+
+    #ifdef HAVE_ARM_TLS_REGISTER
+        #define GET_TLS(reg) \
+            "mrc p15, 0, " #reg ", c13, c0, 3 \n"
+    #else
+        #define GET_TLS(reg) \
+            "mov   " #reg ", #0xFFFF0FFF      \n"  \
+            "ldr   " #reg ", [" #reg ", #-15] \n"
+    #endif
+
+    #define API_ENTRY(_api) __attribute__((naked)) _api
+
+    #define CALL_GL_API(_api, ...)                              \
+         asm volatile(                                          \
+            GET_TLS(r12)                                        \
+            "ldr   r12, [r12, %[tls]] \n"                       \
+            "cmp   r12, #0            \n"                       \
+            "ldrne pc,  [r12, %[api]] \n"                       \
+            "bx    lr                 \n"                       \
+            :                                                   \
+            : [tls] "J"(TLS_SLOT_OPENGL_API*4),                 \
+              [api] "J"(__builtin_offsetof(gl_hooks_t, gl._api))    \
+            :                                                   \
+            );
+
+    #define CALL_GL_API_RETURN(_api, ...) \
+        CALL_GL_API(_api, __VA_ARGS__) \
+        return 0; // placate gcc's warnings. never reached.
+
+#else
+
+    #define API_ENTRY(_api) _api
+
+    #define CALL_GL_API(_api, ...)                                       \
+        gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;  \
+        _c->_api(__VA_ARGS__)
+    
+    #define CALL_GL_API_RETURN(_api, ...)                                \
+        gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;  \
+        return _c->_api(__VA_ARGS__)
+
+#endif
+
+
+extern "C" {
+#include "gl2_api.in"
+#include "gl2ext_api.in"
+}
+
+#undef API_ENTRY
+#undef CALL_GL_API
+#undef CALL_GL_API_RETURN
+
+
+/*
+ * These GL calls are special because they need to EGL to retrieve some
+ * informations before they can execute.
+ */
+
+extern "C" void __glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image);
+extern "C" void __glEGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image);
+
+
+void glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image)
+{
+    GLeglImageOES implImage = 
+        (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image);
+    __glEGLImageTargetTexture2DOES(target, implImage);
+}
+
+void glEGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
+{
+    GLeglImageOES implImage = 
+        (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image);
+    __glEGLImageTargetRenderbufferStorageOES(target, image);
+}
+
diff --git a/opengl/libs/GLES2/gl2_api.in b/opengl/libs/GLES2/gl2_api.in
new file mode 100644
index 0000000..9c2e69a
--- /dev/null
+++ b/opengl/libs/GLES2/gl2_api.in
@@ -0,0 +1,426 @@
+void API_ENTRY(glActiveTexture)(GLenum texture) {
+    CALL_GL_API(glActiveTexture, texture);
+}
+void API_ENTRY(glAttachShader)(GLuint program, GLuint shader) {
+    CALL_GL_API(glAttachShader, program, shader);
+}
+void API_ENTRY(glBindAttribLocation)(GLuint program, GLuint index, const char* name) {
+    CALL_GL_API(glBindAttribLocation, program, index, name);
+}
+void API_ENTRY(glBindBuffer)(GLenum target, GLuint buffer) {
+    CALL_GL_API(glBindBuffer, target, buffer);
+}
+void API_ENTRY(glBindFramebuffer)(GLenum target, GLuint framebuffer) {
+    CALL_GL_API(glBindFramebuffer, target, framebuffer);
+}
+void API_ENTRY(glBindRenderbuffer)(GLenum target, GLuint renderbuffer) {
+    CALL_GL_API(glBindRenderbuffer, target, renderbuffer);
+}
+void API_ENTRY(glBindTexture)(GLenum target, GLuint texture) {
+    CALL_GL_API(glBindTexture, target, texture);
+}
+void API_ENTRY(glBlendColor)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {
+    CALL_GL_API(glBlendColor, red, green, blue, alpha);
+}
+void API_ENTRY(glBlendEquation)( GLenum mode ) {
+    CALL_GL_API(glBlendEquation, mode);
+}
+void API_ENTRY(glBlendEquationSeparate)(GLenum modeRGB, GLenum modeAlpha) {
+    CALL_GL_API(glBlendEquationSeparate, modeRGB, modeAlpha);
+}
+void API_ENTRY(glBlendFunc)(GLenum sfactor, GLenum dfactor) {
+    CALL_GL_API(glBlendFunc, sfactor, dfactor);
+}
+void API_ENTRY(glBlendFuncSeparate)(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) {
+    CALL_GL_API(glBlendFuncSeparate, srcRGB, dstRGB, srcAlpha, dstAlpha);
+}
+void API_ENTRY(glBufferData)(GLenum target, GLsizeiptr size, const void* data, GLenum usage) {
+    CALL_GL_API(glBufferData, target, size, data, usage);
+}
+void API_ENTRY(glBufferSubData)(GLenum target, GLintptr offset, GLsizeiptr size, const void* data) {
+    CALL_GL_API(glBufferSubData, target, offset, size, data);
+}
+GLenum API_ENTRY(glCheckFramebufferStatus)(GLenum target) {
+    CALL_GL_API_RETURN(glCheckFramebufferStatus, target);
+}
+void API_ENTRY(glClear)(GLbitfield mask) {
+    CALL_GL_API(glClear, mask);
+}
+void API_ENTRY(glClearColor)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {
+    CALL_GL_API(glClearColor, red, green, blue, alpha);
+}
+void API_ENTRY(glClearDepthf)(GLclampf depth) {
+    CALL_GL_API(glClearDepthf, depth);
+}
+void API_ENTRY(glClearStencil)(GLint s) {
+    CALL_GL_API(glClearStencil, s);
+}
+void API_ENTRY(glColorMask)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {
+    CALL_GL_API(glColorMask, red, green, blue, alpha);
+}
+void API_ENTRY(glCompileShader)(GLuint shader) {
+    CALL_GL_API(glCompileShader, shader);
+}
+void API_ENTRY(glCompressedTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data) {
+    CALL_GL_API(glCompressedTexImage2D, target, level, internalformat, width, height, border, imageSize, data);
+}
+void API_ENTRY(glCompressedTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data) {
+    CALL_GL_API(glCompressedTexSubImage2D, target, level, xoffset, yoffset, width, height, format, imageSize, data);
+}
+void API_ENTRY(glCopyTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) {
+    CALL_GL_API(glCopyTexImage2D, target, level, internalformat, x, y, width, height, border);
+}
+void API_ENTRY(glCopyTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) {
+    CALL_GL_API(glCopyTexSubImage2D, target, level, xoffset, yoffset, x, y, width, height);
+}
+GLuint API_ENTRY(glCreateProgram)(void) {
+    CALL_GL_API_RETURN(glCreateProgram);
+}
+GLuint API_ENTRY(glCreateShader)(GLenum type) {
+    CALL_GL_API_RETURN(glCreateShader, type);
+}
+void API_ENTRY(glCullFace)(GLenum mode) {
+    CALL_GL_API(glCullFace, mode);
+}
+void API_ENTRY(glDeleteBuffers)(GLsizei n, const GLuint* buffers) {
+    CALL_GL_API(glDeleteBuffers, n, buffers);
+}
+void API_ENTRY(glDeleteFramebuffers)(GLsizei n, const GLuint* framebuffers) {
+    CALL_GL_API(glDeleteFramebuffers, n, framebuffers);
+}
+void API_ENTRY(glDeleteProgram)(GLuint program) {
+    CALL_GL_API(glDeleteProgram, program);
+}
+void API_ENTRY(glDeleteRenderbuffers)(GLsizei n, const GLuint* renderbuffers) {
+    CALL_GL_API(glDeleteRenderbuffers, n, renderbuffers);
+}
+void API_ENTRY(glDeleteShader)(GLuint shader) {
+    CALL_GL_API(glDeleteShader, shader);
+}
+void API_ENTRY(glDeleteTextures)(GLsizei n, const GLuint* textures) {
+    CALL_GL_API(glDeleteTextures, n, textures);
+}
+void API_ENTRY(glDepthFunc)(GLenum func) {
+    CALL_GL_API(glDepthFunc, func);
+}
+void API_ENTRY(glDepthMask)(GLboolean flag) {
+    CALL_GL_API(glDepthMask, flag);
+}
+void API_ENTRY(glDepthRangef)(GLclampf zNear, GLclampf zFar) {
+    CALL_GL_API(glDepthRangef, zNear, zFar);
+}
+void API_ENTRY(glDetachShader)(GLuint program, GLuint shader) {
+    CALL_GL_API(glDetachShader, program, shader);
+}
+void API_ENTRY(glDisable)(GLenum cap) {
+    CALL_GL_API(glDisable, cap);
+}
+void API_ENTRY(glDisableVertexAttribArray)(GLuint index) {
+    CALL_GL_API(glDisableVertexAttribArray, index);
+}
+void API_ENTRY(glDrawArrays)(GLenum mode, GLint first, GLsizei count) {
+    CALL_GL_API(glDrawArrays, mode, first, count);
+}
+void API_ENTRY(glDrawElements)(GLenum mode, GLsizei count, GLenum type, const void* indices) {
+    CALL_GL_API(glDrawElements, mode, count, type, indices);
+}
+void API_ENTRY(glEnable)(GLenum cap) {
+    CALL_GL_API(glEnable, cap);
+}
+void API_ENTRY(glEnableVertexAttribArray)(GLuint index) {
+    CALL_GL_API(glEnableVertexAttribArray, index);
+}
+void API_ENTRY(glFinish)(void) {
+    CALL_GL_API(glFinish);
+}
+void API_ENTRY(glFlush)(void) {
+    CALL_GL_API(glFlush);
+}
+void API_ENTRY(glFramebufferRenderbuffer)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) {
+    CALL_GL_API(glFramebufferRenderbuffer, target, attachment, renderbuffertarget, renderbuffer);
+}
+void API_ENTRY(glFramebufferTexture2D)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) {
+    CALL_GL_API(glFramebufferTexture2D, target, attachment, textarget, texture, level);
+}
+void API_ENTRY(glFrontFace)(GLenum mode) {
+    CALL_GL_API(glFrontFace, mode);
+}
+void API_ENTRY(glGenBuffers)(GLsizei n, GLuint* buffers) {
+    CALL_GL_API(glGenBuffers, n, buffers);
+}
+void API_ENTRY(glGenerateMipmap)(GLenum target) {
+    CALL_GL_API(glGenerateMipmap, target);
+}
+void API_ENTRY(glGenFramebuffers)(GLsizei n, GLuint* framebuffers) {
+    CALL_GL_API(glGenFramebuffers, n, framebuffers);
+}
+void API_ENTRY(glGenRenderbuffers)(GLsizei n, GLuint* renderbuffers) {
+    CALL_GL_API(glGenRenderbuffers, n, renderbuffers);
+}
+void API_ENTRY(glGenTextures)(GLsizei n, GLuint* textures) {
+    CALL_GL_API(glGenTextures, n, textures);
+}
+void API_ENTRY(glGetActiveAttrib)(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name) {
+    CALL_GL_API(glGetActiveAttrib, program, index, bufsize, length, size, type, name);
+}
+void API_ENTRY(glGetActiveUniform)(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name) {
+    CALL_GL_API(glGetActiveUniform, program, index, bufsize, length, size, type, name);
+}
+void API_ENTRY(glGetAttachedShaders)(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders) {
+    CALL_GL_API(glGetAttachedShaders, program, maxcount, count, shaders);
+}
+int API_ENTRY(glGetAttribLocation)(GLuint program, const char* name) {
+    CALL_GL_API_RETURN(glGetAttribLocation, program, name);
+}
+void API_ENTRY(glGetBooleanv)(GLenum pname, GLboolean* params) {
+    CALL_GL_API(glGetBooleanv, pname, params);
+}
+void API_ENTRY(glGetBufferParameteriv)(GLenum target, GLenum pname, GLint* params) {
+    CALL_GL_API(glGetBufferParameteriv, target, pname, params);
+}
+GLenum API_ENTRY(glGetError)(void) {
+    CALL_GL_API_RETURN(glGetError);
+}
+void API_ENTRY(glGetFloatv)(GLenum pname, GLfloat* params) {
+    CALL_GL_API(glGetFloatv, pname, params);
+}
+void API_ENTRY(glGetFramebufferAttachmentParameteriv)(GLenum target, GLenum attachment, GLenum pname, GLint* params) {
+    CALL_GL_API(glGetFramebufferAttachmentParameteriv, target, attachment, pname, params);
+}
+void API_ENTRY(glGetIntegerv)(GLenum pname, GLint* params) {
+    CALL_GL_API(glGetIntegerv, pname, params);
+}
+void API_ENTRY(glGetProgramiv)(GLuint program, GLenum pname, GLint* params) {
+    CALL_GL_API(glGetProgramiv, program, pname, params);
+}
+void API_ENTRY(glGetProgramInfoLog)(GLuint program, GLsizei bufsize, GLsizei* length, char* infolog) {
+    CALL_GL_API(glGetProgramInfoLog, program, bufsize, length, infolog);
+}
+void API_ENTRY(glGetRenderbufferParameteriv)(GLenum target, GLenum pname, GLint* params) {
+    CALL_GL_API(glGetRenderbufferParameteriv, target, pname, params);
+}
+void API_ENTRY(glGetShaderiv)(GLuint shader, GLenum pname, GLint* params) {
+    CALL_GL_API(glGetShaderiv, shader, pname, params);
+}
+void API_ENTRY(glGetShaderInfoLog)(GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog) {
+    CALL_GL_API(glGetShaderInfoLog, shader, bufsize, length, infolog);
+}
+void API_ENTRY(glGetShaderPrecisionFormat)(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) {
+    CALL_GL_API(glGetShaderPrecisionFormat, shadertype, precisiontype, range, precision);
+}
+void API_ENTRY(glGetShaderSource)(GLuint shader, GLsizei bufsize, GLsizei* length, char* source) {
+    CALL_GL_API(glGetShaderSource, shader, bufsize, length, source);
+}
+const GLubyte* API_ENTRY(glGetString)(GLenum name) {
+    CALL_GL_API_RETURN(glGetString, name);
+}
+void API_ENTRY(glGetTexParameterfv)(GLenum target, GLenum pname, GLfloat* params) {
+    CALL_GL_API(glGetTexParameterfv, target, pname, params);
+}
+void API_ENTRY(glGetTexParameteriv)(GLenum target, GLenum pname, GLint* params) {
+    CALL_GL_API(glGetTexParameteriv, target, pname, params);
+}
+void API_ENTRY(glGetUniformfv)(GLuint program, GLint location, GLfloat* params) {
+    CALL_GL_API(glGetUniformfv, program, location, params);
+}
+void API_ENTRY(glGetUniformiv)(GLuint program, GLint location, GLint* params) {
+    CALL_GL_API(glGetUniformiv, program, location, params);
+}
+int API_ENTRY(glGetUniformLocation)(GLuint program, const char* name) {
+    CALL_GL_API_RETURN(glGetUniformLocation, program, name);
+}
+void API_ENTRY(glGetVertexAttribfv)(GLuint index, GLenum pname, GLfloat* params) {
+    CALL_GL_API(glGetVertexAttribfv, index, pname, params);
+}
+void API_ENTRY(glGetVertexAttribiv)(GLuint index, GLenum pname, GLint* params) {
+    CALL_GL_API(glGetVertexAttribiv, index, pname, params);
+}
+void API_ENTRY(glGetVertexAttribPointerv)(GLuint index, GLenum pname, void** pointer) {
+    CALL_GL_API(glGetVertexAttribPointerv, index, pname, pointer);
+}
+void API_ENTRY(glHint)(GLenum target, GLenum mode) {
+    CALL_GL_API(glHint, target, mode);
+}
+GLboolean API_ENTRY(glIsBuffer)(GLuint buffer) {
+    CALL_GL_API_RETURN(glIsBuffer, buffer);
+}
+GLboolean API_ENTRY(glIsEnabled)(GLenum cap) {
+    CALL_GL_API_RETURN(glIsEnabled, cap);
+}
+GLboolean API_ENTRY(glIsFramebuffer)(GLuint framebuffer) {
+    CALL_GL_API_RETURN(glIsFramebuffer, framebuffer);
+}
+GLboolean API_ENTRY(glIsProgram)(GLuint program) {
+    CALL_GL_API_RETURN(glIsProgram, program);
+}
+GLboolean API_ENTRY(glIsRenderbuffer)(GLuint renderbuffer) {
+    CALL_GL_API_RETURN(glIsRenderbuffer, renderbuffer);
+}
+GLboolean API_ENTRY(glIsShader)(GLuint shader) {
+    CALL_GL_API_RETURN(glIsShader, shader);
+}
+GLboolean API_ENTRY(glIsTexture)(GLuint texture) {
+    CALL_GL_API_RETURN(glIsTexture, texture);
+}
+void API_ENTRY(glLineWidth)(GLfloat width) {
+    CALL_GL_API(glLineWidth, width);
+}
+void API_ENTRY(glLinkProgram)(GLuint program) {
+    CALL_GL_API(glLinkProgram, program);
+}
+void API_ENTRY(glPixelStorei)(GLenum pname, GLint param) {
+    CALL_GL_API(glPixelStorei, pname, param);
+}
+void API_ENTRY(glPolygonOffset)(GLfloat factor, GLfloat units) {
+    CALL_GL_API(glPolygonOffset, factor, units);
+}
+void API_ENTRY(glReadPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels) {
+    CALL_GL_API(glReadPixels, x, y, width, height, format, type, pixels);
+}
+void API_ENTRY(glReleaseShaderCompiler)(void) {
+    CALL_GL_API(glReleaseShaderCompiler);
+}
+void API_ENTRY(glRenderbufferStorage)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
+    CALL_GL_API(glRenderbufferStorage, target, internalformat, width, height);
+}
+void API_ENTRY(glSampleCoverage)(GLclampf value, GLboolean invert) {
+    CALL_GL_API(glSampleCoverage, value, invert);
+}
+void API_ENTRY(glScissor)(GLint x, GLint y, GLsizei width, GLsizei height) {
+    CALL_GL_API(glScissor, x, y, width, height);
+}
+void API_ENTRY(glShaderBinary)(GLsizei n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLsizei length) {
+    CALL_GL_API(glShaderBinary, n, shaders, binaryformat, binary, length);
+}
+void API_ENTRY(glShaderSource)(GLuint shader, GLsizei count, const char** string, const GLint* length) {
+    CALL_GL_API(glShaderSource, shader, count, string, length);
+}
+void API_ENTRY(glStencilFunc)(GLenum func, GLint ref, GLuint mask) {
+    CALL_GL_API(glStencilFunc, func, ref, mask);
+}
+void API_ENTRY(glStencilFuncSeparate)(GLenum face, GLenum func, GLint ref, GLuint mask) {
+    CALL_GL_API(glStencilFuncSeparate, face, func, ref, mask);
+}
+void API_ENTRY(glStencilMask)(GLuint mask) {
+    CALL_GL_API(glStencilMask, mask);
+}
+void API_ENTRY(glStencilMaskSeparate)(GLenum face, GLuint mask) {
+    CALL_GL_API(glStencilMaskSeparate, face, mask);
+}
+void API_ENTRY(glStencilOp)(GLenum fail, GLenum zfail, GLenum zpass) {
+    CALL_GL_API(glStencilOp, fail, zfail, zpass);
+}
+void API_ENTRY(glStencilOpSeparate)(GLenum face, GLenum fail, GLenum zfail, GLenum zpass) {
+    CALL_GL_API(glStencilOpSeparate, face, fail, zfail, zpass);
+}
+void API_ENTRY(glTexImage2D)(GLenum target, GLint level, GLint internalformat,  GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels) {
+    CALL_GL_API(glTexImage2D, target, level, internalformat, width, height, border, format, type, pixels);
+}
+void API_ENTRY(glTexParameterf)(GLenum target, GLenum pname, GLfloat param) {
+    CALL_GL_API(glTexParameterf, target, pname, param);
+}
+void API_ENTRY(glTexParameterfv)(GLenum target, GLenum pname, const GLfloat* params) {
+    CALL_GL_API(glTexParameterfv, target, pname, params);
+}
+void API_ENTRY(glTexParameteri)(GLenum target, GLenum pname, GLint param) {
+    CALL_GL_API(glTexParameteri, target, pname, param);
+}
+void API_ENTRY(glTexParameteriv)(GLenum target, GLenum pname, const GLint* params) {
+    CALL_GL_API(glTexParameteriv, target, pname, params);
+}
+void API_ENTRY(glTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels) {
+    CALL_GL_API(glTexSubImage2D, target, level, xoffset, yoffset, width, height, format, type, pixels);
+}
+void API_ENTRY(glUniform1f)(GLint location, GLfloat x) {
+    CALL_GL_API(glUniform1f, location, x);
+}
+void API_ENTRY(glUniform1fv)(GLint location, GLsizei count, const GLfloat* v) {
+    CALL_GL_API(glUniform1fv, location, count, v);
+}
+void API_ENTRY(glUniform1i)(GLint location, GLint x) {
+    CALL_GL_API(glUniform1i, location, x);
+}
+void API_ENTRY(glUniform1iv)(GLint location, GLsizei count, const GLint* v) {
+    CALL_GL_API(glUniform1iv, location, count, v);
+}
+void API_ENTRY(glUniform2f)(GLint location, GLfloat x, GLfloat y) {
+    CALL_GL_API(glUniform2f, location, x, y);
+}
+void API_ENTRY(glUniform2fv)(GLint location, GLsizei count, const GLfloat* v) {
+    CALL_GL_API(glUniform2fv, location, count, v);
+}
+void API_ENTRY(glUniform2i)(GLint location, GLint x, GLint y) {
+    CALL_GL_API(glUniform2i, location, x, y);
+}
+void API_ENTRY(glUniform2iv)(GLint location, GLsizei count, const GLint* v) {
+    CALL_GL_API(glUniform2iv, location, count, v);
+}
+void API_ENTRY(glUniform3f)(GLint location, GLfloat x, GLfloat y, GLfloat z) {
+    CALL_GL_API(glUniform3f, location, x, y, z);
+}
+void API_ENTRY(glUniform3fv)(GLint location, GLsizei count, const GLfloat* v) {
+    CALL_GL_API(glUniform3fv, location, count, v);
+}
+void API_ENTRY(glUniform3i)(GLint location, GLint x, GLint y, GLint z) {
+    CALL_GL_API(glUniform3i, location, x, y, z);
+}
+void API_ENTRY(glUniform3iv)(GLint location, GLsizei count, const GLint* v) {
+    CALL_GL_API(glUniform3iv, location, count, v);
+}
+void API_ENTRY(glUniform4f)(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) {
+    CALL_GL_API(glUniform4f, location, x, y, z, w);
+}
+void API_ENTRY(glUniform4fv)(GLint location, GLsizei count, const GLfloat* v) {
+    CALL_GL_API(glUniform4fv, location, count, v);
+}
+void API_ENTRY(glUniform4i)(GLint location, GLint x, GLint y, GLint z, GLint w) {
+    CALL_GL_API(glUniform4i, location, x, y, z, w);
+}
+void API_ENTRY(glUniform4iv)(GLint location, GLsizei count, const GLint* v) {
+    CALL_GL_API(glUniform4iv, location, count, v);
+}
+void API_ENTRY(glUniformMatrix2fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
+    CALL_GL_API(glUniformMatrix2fv, location, count, transpose, value);
+}
+void API_ENTRY(glUniformMatrix3fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
+    CALL_GL_API(glUniformMatrix3fv, location, count, transpose, value);
+}
+void API_ENTRY(glUniformMatrix4fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
+    CALL_GL_API(glUniformMatrix4fv, location, count, transpose, value);
+}
+void API_ENTRY(glUseProgram)(GLuint program) {
+    CALL_GL_API(glUseProgram, program);
+}
+void API_ENTRY(glValidateProgram)(GLuint program) {
+    CALL_GL_API(glValidateProgram, program);
+}
+void API_ENTRY(glVertexAttrib1f)(GLuint indx, GLfloat x) {
+    CALL_GL_API(glVertexAttrib1f, indx, x);
+}
+void API_ENTRY(glVertexAttrib1fv)(GLuint indx, const GLfloat* values) {
+    CALL_GL_API(glVertexAttrib1fv, indx, values);
+}
+void API_ENTRY(glVertexAttrib2f)(GLuint indx, GLfloat x, GLfloat y) {
+    CALL_GL_API(glVertexAttrib2f, indx, x, y);
+}
+void API_ENTRY(glVertexAttrib2fv)(GLuint indx, const GLfloat* values) {
+    CALL_GL_API(glVertexAttrib2fv, indx, values);
+}
+void API_ENTRY(glVertexAttrib3f)(GLuint indx, GLfloat x, GLfloat y, GLfloat z) {
+    CALL_GL_API(glVertexAttrib3f, indx, x, y, z);
+}
+void API_ENTRY(glVertexAttrib3fv)(GLuint indx, const GLfloat* values) {
+    CALL_GL_API(glVertexAttrib3fv, indx, values);
+}
+void API_ENTRY(glVertexAttrib4f)(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w) {
+    CALL_GL_API(glVertexAttrib4f, indx, x, y, z, w);
+}
+void API_ENTRY(glVertexAttrib4fv)(GLuint indx, const GLfloat* values) {
+    CALL_GL_API(glVertexAttrib4fv, indx, values);
+}
+void API_ENTRY(glVertexAttribPointer)(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr) {
+    CALL_GL_API(glVertexAttribPointer, indx, size, type, normalized, stride, ptr);
+}
+void API_ENTRY(glViewport)(GLint x, GLint y, GLsizei width, GLsizei height) {
+    CALL_GL_API(glViewport, x, y, width, height);
+}
diff --git a/opengl/libs/GLES2/gl2ext_api.in b/opengl/libs/GLES2/gl2ext_api.in
new file mode 100644
index 0000000..6eeecb3
--- /dev/null
+++ b/opengl/libs/GLES2/gl2ext_api.in
@@ -0,0 +1,105 @@
+void API_ENTRY(__glEGLImageTargetTexture2DOES)(GLenum target, GLeglImageOES image) {
+    CALL_GL_API(glEGLImageTargetTexture2DOES, target, image);
+}
+void API_ENTRY(__glEGLImageTargetRenderbufferStorageOES)(GLenum target, GLeglImageOES image) {
+    CALL_GL_API(glEGLImageTargetRenderbufferStorageOES, target, image);
+}
+void API_ENTRY(glGetProgramBinaryOES)(GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary) {
+    CALL_GL_API(glGetProgramBinaryOES, program, bufSize, length, binaryFormat, binary);
+}
+void API_ENTRY(glProgramBinaryOES)(GLuint program, GLenum binaryFormat, const void *binary, GLint length) {
+    CALL_GL_API(glProgramBinaryOES, program, binaryFormat, binary, length);
+}
+void* API_ENTRY(glMapBufferOES)(GLenum target, GLenum access) {
+    CALL_GL_API_RETURN(glMapBufferOES, target, access);
+}
+GLboolean API_ENTRY(glUnmapBufferOES)(GLenum target) {
+    CALL_GL_API_RETURN(glUnmapBufferOES, target);
+}
+void API_ENTRY(glGetBufferPointervOES)(GLenum target, GLenum pname, void** params) {
+    CALL_GL_API(glGetBufferPointervOES, target, pname, params);
+}
+void API_ENTRY(glTexImage3DOES)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels) {
+    CALL_GL_API(glTexImage3DOES, target, level, internalformat, width, height, depth, border, format, type, pixels);
+}
+void API_ENTRY(glTexSubImage3DOES)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels) {
+    CALL_GL_API(glTexSubImage3DOES, target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels);
+}
+void API_ENTRY(glCopyTexSubImage3DOES)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height) {
+    CALL_GL_API(glCopyTexSubImage3DOES, target, level, xoffset, yoffset, zoffset, x, y, width, height);
+}
+void API_ENTRY(glCompressedTexImage3DOES)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void* data) {
+    CALL_GL_API(glCompressedTexImage3DOES, target, level, internalformat, width, height, depth, border, imageSize, data);
+}
+void API_ENTRY(glCompressedTexSubImage3DOES)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data) {
+    CALL_GL_API(glCompressedTexSubImage3DOES, target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
+}
+void API_ENTRY(glFramebufferTexture3DOES)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset) {
+    CALL_GL_API(glFramebufferTexture3DOES, target, attachment, textarget, texture, level, zoffset);
+}
+void API_ENTRY(glGetPerfMonitorGroupsAMD)(GLint *numGroups, GLsizei groupsSize, GLuint *groups) {
+    CALL_GL_API(glGetPerfMonitorGroupsAMD, numGroups, groupsSize, groups);
+}
+void API_ENTRY(glGetPerfMonitorCountersAMD)(GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters) {
+    CALL_GL_API(glGetPerfMonitorCountersAMD, group, numCounters, maxActiveCounters, counterSize, counters);
+}
+void API_ENTRY(glGetPerfMonitorGroupStringAMD)(GLuint group, GLsizei bufSize, GLsizei *length, char *groupString) {
+    CALL_GL_API(glGetPerfMonitorGroupStringAMD, group, bufSize, length, groupString);
+}
+void API_ENTRY(glGetPerfMonitorCounterStringAMD)(GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, char *counterString) {
+    CALL_GL_API(glGetPerfMonitorCounterStringAMD, group, counter, bufSize, length, counterString);
+}
+void API_ENTRY(glGetPerfMonitorCounterInfoAMD)(GLuint group, GLuint counter, GLenum pname, void *data) {
+    CALL_GL_API(glGetPerfMonitorCounterInfoAMD, group, counter, pname, data);
+}
+void API_ENTRY(glGenPerfMonitorsAMD)(GLsizei n, GLuint *monitors) {
+    CALL_GL_API(glGenPerfMonitorsAMD, n, monitors);
+}
+void API_ENTRY(glDeletePerfMonitorsAMD)(GLsizei n, GLuint *monitors) {
+    CALL_GL_API(glDeletePerfMonitorsAMD, n, monitors);
+}
+void API_ENTRY(glSelectPerfMonitorCountersAMD)(GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *countersList) {
+    CALL_GL_API(glSelectPerfMonitorCountersAMD, monitor, enable, group, numCounters, countersList);
+}
+void API_ENTRY(glBeginPerfMonitorAMD)(GLuint monitor) {
+    CALL_GL_API(glBeginPerfMonitorAMD, monitor);
+}
+void API_ENTRY(glEndPerfMonitorAMD)(GLuint monitor) {
+    CALL_GL_API(glEndPerfMonitorAMD, monitor);
+}
+void API_ENTRY(glGetPerfMonitorCounterDataAMD)(GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten) {
+    CALL_GL_API(glGetPerfMonitorCounterDataAMD, monitor, pname, dataSize, data, bytesWritten);
+}
+void API_ENTRY(glDeleteFencesNV)(GLsizei n, const GLuint *fences) {
+    CALL_GL_API(glDeleteFencesNV, n, fences);
+}
+void API_ENTRY(glGenFencesNV)(GLsizei n, GLuint *fences) {
+    CALL_GL_API(glGenFencesNV, n, fences);
+}
+GLboolean API_ENTRY(glIsFenceNV)(GLuint fence) {
+    CALL_GL_API_RETURN(glIsFenceNV, fence);
+}
+GLboolean API_ENTRY(glTestFenceNV)(GLuint fence) {
+    CALL_GL_API_RETURN(glTestFenceNV, fence);
+}
+void API_ENTRY(glGetFenceivNV)(GLuint fence, GLenum pname, GLint *params) {
+    CALL_GL_API(glGetFenceivNV, fence, pname, params);
+}
+void API_ENTRY(glFinishFenceNV)(GLuint fence) {
+    CALL_GL_API(glFinishFenceNV, fence);
+}
+void API_ENTRY(glSetFenceNV)(GLuint fence, GLenum condition) {
+    CALL_GL_API(glSetFenceNV, fence, condition);
+}
+void API_ENTRY(glGetDriverControlsQCOM)(GLint *num, GLsizei size, GLuint *driverControls) {
+    CALL_GL_API(glGetDriverControlsQCOM, num, size, driverControls);
+}
+void API_ENTRY(glGetDriverControlStringQCOM)(GLuint driverControl, GLsizei bufSize, GLsizei *length, char *driverControlString) {
+    CALL_GL_API(glGetDriverControlStringQCOM, driverControl, bufSize, length, driverControlString);
+}
+void API_ENTRY(glEnableDriverControlQCOM)(GLuint driverControl) {
+    CALL_GL_API(glEnableDriverControlQCOM, driverControl);
+}
+void API_ENTRY(glDisableDriverControlQCOM)(GLuint driverControl) {
+    CALL_GL_API(glDisableDriverControlQCOM, driverControl);
+}
diff --git a/opengl/libs/GLES_CM/gl.cpp b/opengl/libs/GLES_CM/gl.cpp
index 384b59a..0c9352e 100644
--- a/opengl/libs/GLES_CM/gl.cpp
+++ b/opengl/libs/GLES_CM/gl.cpp
@@ -14,8 +14,6 @@
  ** limitations under the License.
  */
 
-#define LOG_TAG "GLES_CM"
-
 #include <ctype.h>
 #include <string.h>
 #include <errno.h>
@@ -33,6 +31,9 @@
 
 using namespace android;
 
+// set this to 1 for crude GL debugging
+#define CHECK_FOR_GL_ERRORS     0
+
 // ----------------------------------------------------------------------------
 // extensions for the framework
 // ----------------------------------------------------------------------------
@@ -73,14 +74,22 @@
 #undef CALL_GL_API
 #undef CALL_GL_API_RETURN
 
-#if USE_FAST_TLS_KEY
+#if USE_FAST_TLS_KEY && !CHECK_FOR_GL_ERRORS
+
+    #ifdef HAVE_ARM_TLS_REGISTER
+        #define GET_TLS(reg) \
+            "mrc p15, 0, " #reg ", c13, c0, 3 \n"
+    #else
+        #define GET_TLS(reg) \
+            "mov   " #reg ", #0xFFFF0FFF      \n"  \
+            "ldr   " #reg ", [" #reg ", #-15] \n"
+    #endif
 
     #define API_ENTRY(_api) __attribute__((naked)) _api
 
     #define CALL_GL_API(_api, ...)                              \
          asm volatile(                                          \
-            "mov   r12, #0xFFFF0FFF   \n"                       \
-            "ldr   r12, [r12, #-15]   \n"                       \
+            GET_TLS(r12)                                        \
             "ldr   r12, [r12, %[tls]] \n"                       \
             "cmp   r12, #0            \n"                       \
             "ldrne pc,  [r12, %[api]] \n"                       \
@@ -90,19 +99,34 @@
               [api] "J"(__builtin_offsetof(gl_hooks_t, gl._api))    \
             :                                                   \
             );
-    
+
     #define CALL_GL_API_RETURN(_api, ...) \
         CALL_GL_API(_api, __VA_ARGS__) \
         return 0; // placate gcc's warnings. never reached.
 
 #else
 
+    #if CHECK_FOR_GL_ERRORS
+    
+        #define CHECK_GL_ERRORS(_api) \
+            do { GLint err = glGetError(); \
+                LOGE_IF(err != GL_NO_ERROR, "%s failed (0x%04X)", #_api, err); \
+            } while(false);
+
+    #else
+
+        #define CHECK_GL_ERRORS(_api) do { } while(false);
+
+    #endif
+
+
     #define API_ENTRY(_api) _api
 
     #define CALL_GL_API(_api, ...)                                      \
         gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl; \
-        _c->_api(__VA_ARGS__)
-    
+        _c->_api(__VA_ARGS__);                                          \
+        CHECK_GL_ERRORS(_api)
+
     #define CALL_GL_API_RETURN(_api, ...)                               \
         gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl; \
         return _c->_api(__VA_ARGS__)
@@ -121,16 +145,25 @@
 
 
 /*
- * These GL calls are special because they need to call into EGL to retrieve
- * some informations before they can execute.
+ * These GL calls are special because they need to EGL to retrieve some
+ * informations before they can execute.
  */
 
+extern "C" void __glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image);
+extern "C" void __glEGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image);
+
 
 void glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image)
 {
+    GLeglImageOES implImage = 
+        (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image);
+    __glEGLImageTargetTexture2DOES(target, implImage);
 }
 
 void glEGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
 {
+    GLeglImageOES implImage = 
+        (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image);
+    __glEGLImageTargetRenderbufferStorageOES(target, image);
 }
 
diff --git a/opengl/libs/egl_impl.h b/opengl/libs/egl_impl.h
index 312b176..1fba209 100644
--- a/opengl/libs/egl_impl.h
+++ b/opengl/libs/egl_impl.h
@@ -23,21 +23,23 @@
 #include <EGL/eglext.h>
 #include <EGL/eglplatform.h>
 
+#include "hooks.h"
+
 // ----------------------------------------------------------------------------
 namespace android {
 // ----------------------------------------------------------------------------
 
-struct gl_hooks_t;
-
 struct egl_connection_t
 {
-    void volatile *     dso;
-    gl_hooks_t *        hooks;
+    void *              dso;
+    gl_hooks_t *        hooks[2];
     EGLint              major;
     EGLint              minor;
-    int                 unavailable;
+    egl_t               egl;
 };
 
+EGLAPI EGLImageKHR egl_get_image_for_current_context(EGLImageKHR image);
+
 // ----------------------------------------------------------------------------
 }; // namespace android
 // ----------------------------------------------------------------------------
diff --git a/opengl/libs/entries.in b/opengl/libs/entries.in
new file mode 100644
index 0000000..bbe3e23
--- /dev/null
+++ b/opengl/libs/entries.in
@@ -0,0 +1,349 @@
+GL_ENTRY(void, glActiveTexture, GLenum texture)
+GL_ENTRY(void, glAlphaFunc, GLenum func, GLclampf ref)
+GL_ENTRY(void, glAlphaFuncx, GLenum func, GLclampx ref)
+GL_ENTRY(void, glAlphaFuncxOES, GLenum func, GLclampx ref)
+GL_ENTRY(void, glAttachShader, GLuint program, GLuint shader)
+GL_ENTRY(void, glBeginPerfMonitorAMD, GLuint monitor)
+GL_ENTRY(void, glBindAttribLocation, GLuint program, GLuint index, const char* name)
+GL_ENTRY(void, glBindBuffer, GLenum target, GLuint buffer)
+GL_ENTRY(void, glBindFramebuffer, GLenum target, GLuint framebuffer)
+GL_ENTRY(void, glBindFramebufferOES, GLenum target, GLuint framebuffer)
+GL_ENTRY(void, glBindRenderbuffer, GLenum target, GLuint renderbuffer)
+GL_ENTRY(void, glBindRenderbufferOES, GLenum target, GLuint renderbuffer)
+GL_ENTRY(void, glBindTexture, GLenum target, GLuint texture)
+GL_ENTRY(void, glBlendColor, GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
+GL_ENTRY(void, glBlendEquation,  GLenum mode )
+GL_ENTRY(void, glBlendEquationOES, GLenum mode)
+GL_ENTRY(void, glBlendEquationSeparate, GLenum modeRGB, GLenum modeAlpha)
+GL_ENTRY(void, glBlendEquationSeparateOES, GLenum modeRGB, GLenum modeAlpha)
+GL_ENTRY(void, glBlendFunc, GLenum sfactor, GLenum dfactor)
+GL_ENTRY(void, glBlendFuncSeparate, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
+GL_ENTRY(void, glBlendFuncSeparateOES, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
+GL_ENTRY(void, glBufferData, GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage)
+GL_ENTRY(void, glBufferSubData, GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data)
+GL_ENTRY(GLenum, glCheckFramebufferStatus, GLenum target)
+GL_ENTRY(GLenum, glCheckFramebufferStatusOES, GLenum target)
+GL_ENTRY(void, glClear, GLbitfield mask)
+GL_ENTRY(void, glClearColor, GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
+GL_ENTRY(void, glClearColorx, GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha)
+GL_ENTRY(void, glClearColorxOES, GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha)
+GL_ENTRY(void, glClearDepthf, GLclampf depth)
+GL_ENTRY(void, glClearDepthfOES, GLclampf depth)
+GL_ENTRY(void, glClearDepthx, GLclampx depth)
+GL_ENTRY(void, glClearDepthxOES, GLclampx depth)
+GL_ENTRY(void, glClearStencil, GLint s)
+GL_ENTRY(void, glClientActiveTexture, GLenum texture)
+GL_ENTRY(void, glClipPlanef, GLenum plane, const GLfloat *equation)
+GL_ENTRY(void, glClipPlanefOES, GLenum plane, const GLfloat *equation)
+GL_ENTRY(void, glClipPlanex, GLenum plane, const GLfixed *equation)
+GL_ENTRY(void, glClipPlanexOES, GLenum plane, const GLfixed *equation)
+GL_ENTRY(void, glColor4f, GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
+GL_ENTRY(void, glColor4ub, GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha)
+GL_ENTRY(void, glColor4x, GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha)
+GL_ENTRY(void, glColor4xOES, GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha)
+GL_ENTRY(void, glColorMask, GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
+GL_ENTRY(void, glColorPointer, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
+GL_ENTRY(void, glCompileShader, GLuint shader)
+GL_ENTRY(void, glCompressedTexImage2D, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data)
+GL_ENTRY(void, glCompressedTexImage3DOES, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void* data)
+GL_ENTRY(void, glCompressedTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data)
+GL_ENTRY(void, glCompressedTexSubImage3DOES, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data)
+GL_ENTRY(void, glCopyTexImage2D, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
+GL_ENTRY(void, glCopyTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
+GL_ENTRY(void, glCopyTexSubImage3DOES, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height)
+GL_ENTRY(GLuint, glCreateProgram, void)
+GL_ENTRY(GLuint, glCreateShader, GLenum type)
+GL_ENTRY(void, glCullFace, GLenum mode)
+GL_ENTRY(void, glCurrentPaletteMatrixOES, GLuint matrixpaletteindex)
+GL_ENTRY(void, glDeleteBuffers, GLsizei n, const GLuint *buffers)
+GL_ENTRY(void, glDeleteFencesNV, GLsizei n, const GLuint *fences)
+GL_ENTRY(void, glDeleteFramebuffers, GLsizei n, const GLuint* framebuffers)
+GL_ENTRY(void, glDeleteFramebuffersOES, GLsizei n, const GLuint* framebuffers)
+GL_ENTRY(void, glDeletePerfMonitorsAMD, GLsizei n, GLuint *monitors)
+GL_ENTRY(void, glDeleteProgram, GLuint program)
+GL_ENTRY(void, glDeleteRenderbuffers, GLsizei n, const GLuint* renderbuffers)
+GL_ENTRY(void, glDeleteRenderbuffersOES, GLsizei n, const GLuint* renderbuffers)
+GL_ENTRY(void, glDeleteShader, GLuint shader)
+GL_ENTRY(void, glDeleteTextures, GLsizei n, const GLuint *textures)
+GL_ENTRY(void, glDepthFunc, GLenum func)
+GL_ENTRY(void, glDepthMask, GLboolean flag)
+GL_ENTRY(void, glDepthRangef, GLclampf zNear, GLclampf zFar)
+GL_ENTRY(void, glDepthRangefOES, GLclampf zNear, GLclampf zFar)
+GL_ENTRY(void, glDepthRangex, GLclampx zNear, GLclampx zFar)
+GL_ENTRY(void, glDepthRangexOES, GLclampx zNear, GLclampx zFar)
+GL_ENTRY(void, glDetachShader, GLuint program, GLuint shader)
+GL_ENTRY(void, glDisable, GLenum cap)
+GL_ENTRY(void, glDisableClientState, GLenum array)
+GL_ENTRY(void, glDisableDriverControlQCOM, GLuint driverControl)
+GL_ENTRY(void, glDisableVertexAttribArray, GLuint index)
+GL_ENTRY(void, glDrawArrays, GLenum mode, GLint first, GLsizei count)
+GL_ENTRY(void, glDrawElements, GLenum mode, GLsizei count, GLenum type, const GLvoid *indices)
+GL_ENTRY(void, glDrawTexfOES, GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height)
+GL_ENTRY(void, glDrawTexfvOES, const GLfloat *coords)
+GL_ENTRY(void, glDrawTexiOES, GLint x, GLint y, GLint z, GLint width, GLint height)
+GL_ENTRY(void, glDrawTexivOES, const GLint *coords)
+GL_ENTRY(void, glDrawTexsOES, GLshort x, GLshort y, GLshort z, GLshort width, GLshort height)
+GL_ENTRY(void, glDrawTexsvOES, const GLshort *coords)
+GL_ENTRY(void, glDrawTexxOES, GLfixed x, GLfixed y, GLfixed z, GLfixed width, GLfixed height)
+GL_ENTRY(void, glDrawTexxvOES, const GLfixed *coords)
+GL_ENTRY(void, glEGLImageTargetRenderbufferStorageOES, GLenum target, GLeglImageOES image)
+GL_ENTRY(void, glEGLImageTargetTexture2DOES, GLenum target, GLeglImageOES image)
+GL_ENTRY(void, glEnable, GLenum cap)
+GL_ENTRY(void, glEnableClientState, GLenum array)
+GL_ENTRY(void, glEnableDriverControlQCOM, GLuint driverControl)
+GL_ENTRY(void, glEnableVertexAttribArray, GLuint index)
+GL_ENTRY(void, glEndPerfMonitorAMD, GLuint monitor)
+GL_ENTRY(void, glFinish, void)
+GL_ENTRY(void, glFinishFenceNV, GLuint fence)
+GL_ENTRY(void, glFlush, void)
+GL_ENTRY(void, glFogf, GLenum pname, GLfloat param)
+GL_ENTRY(void, glFogfv, GLenum pname, const GLfloat *params)
+GL_ENTRY(void, glFogx, GLenum pname, GLfixed param)
+GL_ENTRY(void, glFogxOES, GLenum pname, GLfixed param)
+GL_ENTRY(void, glFogxv, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glFogxvOES, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glFramebufferRenderbuffer, GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
+GL_ENTRY(void, glFramebufferRenderbufferOES, GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
+GL_ENTRY(void, glFramebufferTexture2D, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
+GL_ENTRY(void, glFramebufferTexture2DOES, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
+GL_ENTRY(void, glFramebufferTexture3DOES, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset)
+GL_ENTRY(void, glFrontFace, GLenum mode)
+GL_ENTRY(void, glFrustumf, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar)
+GL_ENTRY(void, glFrustumfOES, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar)
+GL_ENTRY(void, glFrustumx, GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar)
+GL_ENTRY(void, glFrustumxOES, GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar)
+GL_ENTRY(void, glGenBuffers, GLsizei n, GLuint *buffers)
+GL_ENTRY(void, glGenFencesNV, GLsizei n, GLuint *fences)
+GL_ENTRY(void, glGenFramebuffers, GLsizei n, GLuint* framebuffers)
+GL_ENTRY(void, glGenFramebuffersOES, GLsizei n, GLuint* framebuffers)
+GL_ENTRY(void, glGenPerfMonitorsAMD, GLsizei n, GLuint *monitors)
+GL_ENTRY(void, glGenRenderbuffers, GLsizei n, GLuint* renderbuffers)
+GL_ENTRY(void, glGenRenderbuffersOES, GLsizei n, GLuint* renderbuffers)
+GL_ENTRY(void, glGenTextures, GLsizei n, GLuint *textures)
+GL_ENTRY(void, glGenerateMipmap, GLenum target)
+GL_ENTRY(void, glGenerateMipmapOES, GLenum target)
+GL_ENTRY(void, glGetActiveAttrib, GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name)
+GL_ENTRY(void, glGetActiveUniform, GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name)
+GL_ENTRY(void, glGetAttachedShaders, GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders)
+GL_ENTRY(int, glGetAttribLocation, GLuint program, const char* name)
+GL_ENTRY(void, glGetBooleanv, GLenum pname, GLboolean *params)
+GL_ENTRY(void, glGetBufferParameteriv, GLenum target, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetBufferPointervOES, GLenum target, GLenum pname, void** params)
+GL_ENTRY(void, glGetClipPlanef, GLenum pname, GLfloat eqn[4])
+GL_ENTRY(void, glGetClipPlanefOES, GLenum pname, GLfloat eqn[4])
+GL_ENTRY(void, glGetClipPlanex, GLenum pname, GLfixed eqn[4])
+GL_ENTRY(void, glGetClipPlanexOES, GLenum pname, GLfixed eqn[4])
+GL_ENTRY(void, glGetDriverControlStringQCOM, GLuint driverControl, GLsizei bufSize, GLsizei *length, char *driverControlString)
+GL_ENTRY(void, glGetDriverControlsQCOM, GLint *num, GLsizei size, GLuint *driverControls)
+GL_ENTRY(GLenum, glGetError, void)
+GL_ENTRY(void, glGetFenceivNV, GLuint fence, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetFixedv, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetFixedvOES, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetFloatv, GLenum pname, GLfloat *params)
+GL_ENTRY(void, glGetFramebufferAttachmentParameteriv, GLenum target, GLenum attachment, GLenum pname, GLint* params)
+GL_ENTRY(void, glGetFramebufferAttachmentParameterivOES, GLenum target, GLenum attachment, GLenum pname, GLint* params)
+GL_ENTRY(void, glGetIntegerv, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetLightfv, GLenum light, GLenum pname, GLfloat *params)
+GL_ENTRY(void, glGetLightxv, GLenum light, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetLightxvOES, GLenum light, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetMaterialfv, GLenum face, GLenum pname, GLfloat *params)
+GL_ENTRY(void, glGetMaterialxv, GLenum face, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetMaterialxvOES, GLenum face, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetPerfMonitorCounterDataAMD, GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten)
+GL_ENTRY(void, glGetPerfMonitorCounterInfoAMD, GLuint group, GLuint counter, GLenum pname, void *data)
+GL_ENTRY(void, glGetPerfMonitorCounterStringAMD, GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, char *counterString)
+GL_ENTRY(void, glGetPerfMonitorCountersAMD, GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters)
+GL_ENTRY(void, glGetPerfMonitorGroupStringAMD, GLuint group, GLsizei bufSize, GLsizei *length, char *groupString)
+GL_ENTRY(void, glGetPerfMonitorGroupsAMD, GLint *numGroups, GLsizei groupsSize, GLuint *groups)
+GL_ENTRY(void, glGetPointerv, GLenum pname, void **params)
+GL_ENTRY(void, glGetProgramBinaryOES, GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary)
+GL_ENTRY(void, glGetProgramInfoLog, GLuint program, GLsizei bufsize, GLsizei* length, char* infolog)
+GL_ENTRY(void, glGetProgramiv, GLuint program, GLenum pname, GLint* params)
+GL_ENTRY(void, glGetRenderbufferParameteriv, GLenum target, GLenum pname, GLint* params)
+GL_ENTRY(void, glGetRenderbufferParameterivOES, GLenum target, GLenum pname, GLint* params)
+GL_ENTRY(void, glGetShaderInfoLog, GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog)
+GL_ENTRY(void, glGetShaderPrecisionFormat, GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision)
+GL_ENTRY(void, glGetShaderSource, GLuint shader, GLsizei bufsize, GLsizei* length, char* source)
+GL_ENTRY(void, glGetShaderiv, GLuint shader, GLenum pname, GLint* params)
+GL_ENTRY(const GLubyte *, glGetString, GLenum name)
+GL_ENTRY(void, glGetTexEnvfv, GLenum env, GLenum pname, GLfloat *params)
+GL_ENTRY(void, glGetTexEnviv, GLenum env, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetTexEnvxv, GLenum env, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetTexEnvxvOES, GLenum env, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetTexGenfvOES, GLenum coord, GLenum pname, GLfloat *params)
+GL_ENTRY(void, glGetTexGenivOES, GLenum coord, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetTexGenxvOES, GLenum coord, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetTexParameterfv, GLenum target, GLenum pname, GLfloat *params)
+GL_ENTRY(void, glGetTexParameteriv, GLenum target, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetTexParameterxv, GLenum target, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetTexParameterxvOES, GLenum target, GLenum pname, GLfixed *params)
+GL_ENTRY(int, glGetUniformLocation, GLuint program, const char* name)
+GL_ENTRY(void, glGetUniformfv, GLuint program, GLint location, GLfloat* params)
+GL_ENTRY(void, glGetUniformiv, GLuint program, GLint location, GLint* params)
+GL_ENTRY(void, glGetVertexAttribPointerv, GLuint index, GLenum pname, void** pointer)
+GL_ENTRY(void, glGetVertexAttribfv, GLuint index, GLenum pname, GLfloat* params)
+GL_ENTRY(void, glGetVertexAttribiv, GLuint index, GLenum pname, GLint* params)
+GL_ENTRY(void, glHint, GLenum target, GLenum mode)
+GL_ENTRY(GLboolean, glIsBuffer, GLuint buffer)
+GL_ENTRY(GLboolean, glIsEnabled, GLenum cap)
+GL_ENTRY(GLboolean, glIsFenceNV, GLuint fence)
+GL_ENTRY(GLboolean, glIsFramebuffer, GLuint framebuffer)
+GL_ENTRY(GLboolean, glIsFramebufferOES, GLuint framebuffer)
+GL_ENTRY(GLboolean, glIsProgram, GLuint program)
+GL_ENTRY(GLboolean, glIsRenderbuffer, GLuint renderbuffer)
+GL_ENTRY(GLboolean, glIsRenderbufferOES, GLuint renderbuffer)
+GL_ENTRY(GLboolean, glIsShader, GLuint shader)
+GL_ENTRY(GLboolean, glIsTexture, GLuint texture)
+GL_ENTRY(void, glLightModelf, GLenum pname, GLfloat param)
+GL_ENTRY(void, glLightModelfv, GLenum pname, const GLfloat *params)
+GL_ENTRY(void, glLightModelx, GLenum pname, GLfixed param)
+GL_ENTRY(void, glLightModelxOES, GLenum pname, GLfixed param)
+GL_ENTRY(void, glLightModelxv, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glLightModelxvOES, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glLightf, GLenum light, GLenum pname, GLfloat param)
+GL_ENTRY(void, glLightfv, GLenum light, GLenum pname, const GLfloat *params)
+GL_ENTRY(void, glLightx, GLenum light, GLenum pname, GLfixed param)
+GL_ENTRY(void, glLightxOES, GLenum light, GLenum pname, GLfixed param)
+GL_ENTRY(void, glLightxv, GLenum light, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glLightxvOES, GLenum light, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glLineWidth, GLfloat width)
+GL_ENTRY(void, glLineWidthx, GLfixed width)
+GL_ENTRY(void, glLineWidthxOES, GLfixed width)
+GL_ENTRY(void, glLinkProgram, GLuint program)
+GL_ENTRY(void, glLoadIdentity, void)
+GL_ENTRY(void, glLoadMatrixf, const GLfloat *m)
+GL_ENTRY(void, glLoadMatrixx, const GLfixed *m)
+GL_ENTRY(void, glLoadMatrixxOES, const GLfixed *m)
+GL_ENTRY(void, glLoadPaletteFromModelViewMatrixOES, void)
+GL_ENTRY(void, glLogicOp, GLenum opcode)
+GL_ENTRY(void*, glMapBufferOES, GLenum target, GLenum access)
+GL_ENTRY(void, glMaterialf, GLenum face, GLenum pname, GLfloat param)
+GL_ENTRY(void, glMaterialfv, GLenum face, GLenum pname, const GLfloat *params)
+GL_ENTRY(void, glMaterialx, GLenum face, GLenum pname, GLfixed param)
+GL_ENTRY(void, glMaterialxOES, GLenum face, GLenum pname, GLfixed param)
+GL_ENTRY(void, glMaterialxv, GLenum face, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glMaterialxvOES, GLenum face, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glMatrixIndexPointerOES, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
+GL_ENTRY(void, glMatrixMode, GLenum mode)
+GL_ENTRY(void, glMultMatrixf, const GLfloat *m)
+GL_ENTRY(void, glMultMatrixx, const GLfixed *m)
+GL_ENTRY(void, glMultMatrixxOES, const GLfixed *m)
+GL_ENTRY(void, glMultiTexCoord4f, GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q)
+GL_ENTRY(void, glMultiTexCoord4x, GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q)
+GL_ENTRY(void, glMultiTexCoord4xOES, GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q)
+GL_ENTRY(void, glNormal3f, GLfloat nx, GLfloat ny, GLfloat nz)
+GL_ENTRY(void, glNormal3x, GLfixed nx, GLfixed ny, GLfixed nz)
+GL_ENTRY(void, glNormal3xOES, GLfixed nx, GLfixed ny, GLfixed nz)
+GL_ENTRY(void, glNormalPointer, GLenum type, GLsizei stride, const GLvoid *pointer)
+GL_ENTRY(void, glOrthof, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar)
+GL_ENTRY(void, glOrthofOES, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar)
+GL_ENTRY(void, glOrthox, GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar)
+GL_ENTRY(void, glOrthoxOES, GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar)
+GL_ENTRY(void, glPixelStorei, GLenum pname, GLint param)
+GL_ENTRY(void, glPointParameterf, GLenum pname, GLfloat param)
+GL_ENTRY(void, glPointParameterfv, GLenum pname, const GLfloat *params)
+GL_ENTRY(void, glPointParameterx, GLenum pname, GLfixed param)
+GL_ENTRY(void, glPointParameterxOES, GLenum pname, GLfixed param)
+GL_ENTRY(void, glPointParameterxv, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glPointParameterxvOES, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glPointSize, GLfloat size)
+GL_ENTRY(void, glPointSizePointerOES, GLenum type, GLsizei stride, const GLvoid *pointer)
+GL_ENTRY(void, glPointSizex, GLfixed size)
+GL_ENTRY(void, glPointSizexOES, GLfixed size)
+GL_ENTRY(void, glPolygonOffset, GLfloat factor, GLfloat units)
+GL_ENTRY(void, glPolygonOffsetx, GLfixed factor, GLfixed units)
+GL_ENTRY(void, glPolygonOffsetxOES, GLfixed factor, GLfixed units)
+GL_ENTRY(void, glPopMatrix, void)
+GL_ENTRY(void, glProgramBinaryOES, GLuint program, GLenum binaryFormat, const void *binary, GLint length)
+GL_ENTRY(void, glPushMatrix, void)
+GL_ENTRY(GLbitfield, glQueryMatrixxOES, GLfixed mantissa[16], GLint exponent[16])
+GL_ENTRY(void, glReadPixels, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels)
+GL_ENTRY(void, glReleaseShaderCompiler, void)
+GL_ENTRY(void, glRenderbufferStorage, GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
+GL_ENTRY(void, glRenderbufferStorageOES, GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
+GL_ENTRY(void, glRotatef, GLfloat angle, GLfloat x, GLfloat y, GLfloat z)
+GL_ENTRY(void, glRotatex, GLfixed angle, GLfixed x, GLfixed y, GLfixed z)
+GL_ENTRY(void, glRotatexOES, GLfixed angle, GLfixed x, GLfixed y, GLfixed z)
+GL_ENTRY(void, glSampleCoverage, GLclampf value, GLboolean invert)
+GL_ENTRY(void, glSampleCoveragex, GLclampx value, GLboolean invert)
+GL_ENTRY(void, glSampleCoveragexOES, GLclampx value, GLboolean invert)
+GL_ENTRY(void, glScalef, GLfloat x, GLfloat y, GLfloat z)
+GL_ENTRY(void, glScalex, GLfixed x, GLfixed y, GLfixed z)
+GL_ENTRY(void, glScalexOES, GLfixed x, GLfixed y, GLfixed z)
+GL_ENTRY(void, glScissor, GLint x, GLint y, GLsizei width, GLsizei height)
+GL_ENTRY(void, glSelectPerfMonitorCountersAMD, GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *countersList)
+GL_ENTRY(void, glSetFenceNV, GLuint fence, GLenum condition)
+GL_ENTRY(void, glShadeModel, GLenum mode)
+GL_ENTRY(void, glShaderBinary, GLsizei n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLsizei length)
+GL_ENTRY(void, glShaderSource, GLuint shader, GLsizei count, const char** string, const GLint* length)
+GL_ENTRY(void, glStencilFunc, GLenum func, GLint ref, GLuint mask)
+GL_ENTRY(void, glStencilFuncSeparate, GLenum face, GLenum func, GLint ref, GLuint mask)
+GL_ENTRY(void, glStencilMask, GLuint mask)
+GL_ENTRY(void, glStencilMaskSeparate, GLenum face, GLuint mask)
+GL_ENTRY(void, glStencilOp, GLenum fail, GLenum zfail, GLenum zpass)
+GL_ENTRY(void, glStencilOpSeparate, GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
+GL_ENTRY(GLboolean, glTestFenceNV, GLuint fence)
+GL_ENTRY(void, glTexCoordPointer, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
+GL_ENTRY(void, glTexEnvf, GLenum target, GLenum pname, GLfloat param)
+GL_ENTRY(void, glTexEnvfv, GLenum target, GLenum pname, const GLfloat *params)
+GL_ENTRY(void, glTexEnvi, GLenum target, GLenum pname, GLint param)
+GL_ENTRY(void, glTexEnviv, GLenum target, GLenum pname, const GLint *params)
+GL_ENTRY(void, glTexEnvx, GLenum target, GLenum pname, GLfixed param)
+GL_ENTRY(void, glTexEnvxOES, GLenum target, GLenum pname, GLfixed param)
+GL_ENTRY(void, glTexEnvxv, GLenum target, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glTexEnvxvOES, GLenum target, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glTexGenfOES, GLenum coord, GLenum pname, GLfloat param)
+GL_ENTRY(void, glTexGenfvOES, GLenum coord, GLenum pname, const GLfloat *params)
+GL_ENTRY(void, glTexGeniOES, GLenum coord, GLenum pname, GLint param)
+GL_ENTRY(void, glTexGenivOES, GLenum coord, GLenum pname, const GLint *params)
+GL_ENTRY(void, glTexGenxOES, GLenum coord, GLenum pname, GLfixed param)
+GL_ENTRY(void, glTexGenxvOES, GLenum coord, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glTexImage2D, GLenum target, GLint level, GLint internalformat,  GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels)
+GL_ENTRY(void, glTexImage3DOES, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels)
+GL_ENTRY(void, glTexParameterf, GLenum target, GLenum pname, GLfloat param)
+GL_ENTRY(void, glTexParameterfv, GLenum target, GLenum pname, const GLfloat *params)
+GL_ENTRY(void, glTexParameteri, GLenum target, GLenum pname, GLint param)
+GL_ENTRY(void, glTexParameteriv, GLenum target, GLenum pname, const GLint *params)
+GL_ENTRY(void, glTexParameterx, GLenum target, GLenum pname, GLfixed param)
+GL_ENTRY(void, glTexParameterxOES, GLenum target, GLenum pname, GLfixed param)
+GL_ENTRY(void, glTexParameterxv, GLenum target, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glTexParameterxvOES, GLenum target, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels)
+GL_ENTRY(void, glTexSubImage3DOES, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels)
+GL_ENTRY(void, glTranslatef, GLfloat x, GLfloat y, GLfloat z)
+GL_ENTRY(void, glTranslatex, GLfixed x, GLfixed y, GLfixed z)
+GL_ENTRY(void, glTranslatexOES, GLfixed x, GLfixed y, GLfixed z)
+GL_ENTRY(void, glUniform1f, GLint location, GLfloat x)
+GL_ENTRY(void, glUniform1fv, GLint location, GLsizei count, const GLfloat* v)
+GL_ENTRY(void, glUniform1i, GLint location, GLint x)
+GL_ENTRY(void, glUniform1iv, GLint location, GLsizei count, const GLint* v)
+GL_ENTRY(void, glUniform2f, GLint location, GLfloat x, GLfloat y)
+GL_ENTRY(void, glUniform2fv, GLint location, GLsizei count, const GLfloat* v)
+GL_ENTRY(void, glUniform2i, GLint location, GLint x, GLint y)
+GL_ENTRY(void, glUniform2iv, GLint location, GLsizei count, const GLint* v)
+GL_ENTRY(void, glUniform3f, GLint location, GLfloat x, GLfloat y, GLfloat z)
+GL_ENTRY(void, glUniform3fv, GLint location, GLsizei count, const GLfloat* v)
+GL_ENTRY(void, glUniform3i, GLint location, GLint x, GLint y, GLint z)
+GL_ENTRY(void, glUniform3iv, GLint location, GLsizei count, const GLint* v)
+GL_ENTRY(void, glUniform4f, GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+GL_ENTRY(void, glUniform4fv, GLint location, GLsizei count, const GLfloat* v)
+GL_ENTRY(void, glUniform4i, GLint location, GLint x, GLint y, GLint z, GLint w)
+GL_ENTRY(void, glUniform4iv, GLint location, GLsizei count, const GLint* v)
+GL_ENTRY(void, glUniformMatrix2fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+GL_ENTRY(void, glUniformMatrix3fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+GL_ENTRY(void, glUniformMatrix4fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+GL_ENTRY(GLboolean, glUnmapBufferOES, GLenum target)
+GL_ENTRY(void, glUseProgram, GLuint program)
+GL_ENTRY(void, glValidateProgram, GLuint program)
+GL_ENTRY(void, glVertexAttrib1f, GLuint indx, GLfloat x)
+GL_ENTRY(void, glVertexAttrib1fv, GLuint indx, const GLfloat* values)
+GL_ENTRY(void, glVertexAttrib2f, GLuint indx, GLfloat x, GLfloat y)
+GL_ENTRY(void, glVertexAttrib2fv, GLuint indx, const GLfloat* values)
+GL_ENTRY(void, glVertexAttrib3f, GLuint indx, GLfloat x, GLfloat y, GLfloat z)
+GL_ENTRY(void, glVertexAttrib3fv, GLuint indx, const GLfloat* values)
+GL_ENTRY(void, glVertexAttrib4f, GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+GL_ENTRY(void, glVertexAttrib4fv, GLuint indx, const GLfloat* values)
+GL_ENTRY(void, glVertexAttribPointer, GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr)
+GL_ENTRY(void, glVertexPointer, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
+GL_ENTRY(void, glViewport, GLint x, GLint y, GLsizei width, GLsizei height)
+GL_ENTRY(void, glWeightPointerOES, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
diff --git a/opengl/libs/gl_entries.in b/opengl/libs/gl_entries.in
deleted file mode 100644
index d7cc5da..0000000
--- a/opengl/libs/gl_entries.in
+++ /dev/null
@@ -1,145 +0,0 @@
-GL_ENTRY(void, glAlphaFunc, GLenum func, GLclampf ref)
-GL_ENTRY(void, glClearColor, GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
-GL_ENTRY(void, glClearDepthf, GLclampf depth)
-GL_ENTRY(void, glClipPlanef, GLenum plane, const GLfloat *equation)
-GL_ENTRY(void, glColor4f, GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
-GL_ENTRY(void, glDepthRangef, GLclampf zNear, GLclampf zFar)
-GL_ENTRY(void, glFogf, GLenum pname, GLfloat param)
-GL_ENTRY(void, glFogfv, GLenum pname, const GLfloat *params)
-GL_ENTRY(void, glFrustumf, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar)
-GL_ENTRY(void, glGetClipPlanef, GLenum pname, GLfloat eqn[4])
-GL_ENTRY(void, glGetFloatv, GLenum pname, GLfloat *params)
-GL_ENTRY(void, glGetLightfv, GLenum light, GLenum pname, GLfloat *params)
-GL_ENTRY(void, glGetMaterialfv, GLenum face, GLenum pname, GLfloat *params)
-GL_ENTRY(void, glGetTexEnvfv, GLenum env, GLenum pname, GLfloat *params)
-GL_ENTRY(void, glGetTexParameterfv, GLenum target, GLenum pname, GLfloat *params)
-GL_ENTRY(void, glLightModelf, GLenum pname, GLfloat param)
-GL_ENTRY(void, glLightModelfv, GLenum pname, const GLfloat *params)
-GL_ENTRY(void, glLightf, GLenum light, GLenum pname, GLfloat param)
-GL_ENTRY(void, glLightfv, GLenum light, GLenum pname, const GLfloat *params)
-GL_ENTRY(void, glLineWidth, GLfloat width)
-GL_ENTRY(void, glLoadMatrixf, const GLfloat *m)
-GL_ENTRY(void, glMaterialf, GLenum face, GLenum pname, GLfloat param)
-GL_ENTRY(void, glMaterialfv, GLenum face, GLenum pname, const GLfloat *params)
-GL_ENTRY(void, glMultMatrixf, const GLfloat *m)
-GL_ENTRY(void, glMultiTexCoord4f, GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q)
-GL_ENTRY(void, glNormal3f, GLfloat nx, GLfloat ny, GLfloat nz)
-GL_ENTRY(void, glOrthof, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar)
-GL_ENTRY(void, glPointParameterf, GLenum pname, GLfloat param)
-GL_ENTRY(void, glPointParameterfv, GLenum pname, const GLfloat *params)
-GL_ENTRY(void, glPointSize, GLfloat size)
-GL_ENTRY(void, glPolygonOffset, GLfloat factor, GLfloat units)
-GL_ENTRY(void, glRotatef, GLfloat angle, GLfloat x, GLfloat y, GLfloat z)
-GL_ENTRY(void, glScalef, GLfloat x, GLfloat y, GLfloat z)
-GL_ENTRY(void, glTexEnvf, GLenum target, GLenum pname, GLfloat param)
-GL_ENTRY(void, glTexEnvfv, GLenum target, GLenum pname, const GLfloat *params)
-GL_ENTRY(void, glTexParameterf, GLenum target, GLenum pname, GLfloat param)
-GL_ENTRY(void, glTexParameterfv, GLenum target, GLenum pname, const GLfloat *params)
-GL_ENTRY(void, glTranslatef, GLfloat x, GLfloat y, GLfloat z)
-GL_ENTRY(void, glActiveTexture, GLenum texture)
-GL_ENTRY(void, glAlphaFuncx, GLenum func, GLclampx ref)
-GL_ENTRY(void, glBindBuffer, GLenum target, GLuint buffer)
-GL_ENTRY(void, glBindTexture, GLenum target, GLuint texture)
-GL_ENTRY(void, glBlendFunc, GLenum sfactor, GLenum dfactor)
-GL_ENTRY(void, glBufferData, GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage)
-GL_ENTRY(void, glBufferSubData, GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data)
-GL_ENTRY(void, glClear, GLbitfield mask)
-GL_ENTRY(void, glClearColorx, GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha)
-GL_ENTRY(void, glClearDepthx, GLclampx depth)
-GL_ENTRY(void, glClearStencil, GLint s)
-GL_ENTRY(void, glClientActiveTexture, GLenum texture)
-GL_ENTRY(void, glClipPlanex, GLenum plane, const GLfixed *equation)
-GL_ENTRY(void, glColor4ub, GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha)
-GL_ENTRY(void, glColor4x, GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha)
-GL_ENTRY(void, glColorMask, GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
-GL_ENTRY(void, glColorPointer, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
-GL_ENTRY(void, glCompressedTexImage2D, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data)
-GL_ENTRY(void, glCompressedTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data)
-GL_ENTRY(void, glCopyTexImage2D, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
-GL_ENTRY(void, glCopyTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
-GL_ENTRY(void, glCullFace, GLenum mode)
-GL_ENTRY(void, glDeleteBuffers, GLsizei n, const GLuint *buffers)
-GL_ENTRY(void, glDeleteTextures, GLsizei n, const GLuint *textures)
-GL_ENTRY(void, glDepthFunc, GLenum func)
-GL_ENTRY(void, glDepthMask, GLboolean flag)
-GL_ENTRY(void, glDepthRangex, GLclampx zNear, GLclampx zFar)
-GL_ENTRY(void, glDisable, GLenum cap)
-GL_ENTRY(void, glDisableClientState, GLenum array)
-GL_ENTRY(void, glDrawArrays, GLenum mode, GLint first, GLsizei count)
-GL_ENTRY(void, glDrawElements, GLenum mode, GLsizei count, GLenum type, const GLvoid *indices)
-GL_ENTRY(void, glEnable, GLenum cap)
-GL_ENTRY(void, glEnableClientState, GLenum array)
-GL_ENTRY(void, glFinish, void)
-GL_ENTRY(void, glFlush, void)
-GL_ENTRY(void, glFogx, GLenum pname, GLfixed param)
-GL_ENTRY(void, glFogxv, GLenum pname, const GLfixed *params)
-GL_ENTRY(void, glFrontFace, GLenum mode)
-GL_ENTRY(void, glFrustumx, GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar)
-GL_ENTRY(void, glGetBooleanv, GLenum pname, GLboolean *params)
-GL_ENTRY(void, glGetBufferParameteriv, GLenum target, GLenum pname, GLint *params)
-GL_ENTRY(void, glGetClipPlanex, GLenum pname, GLfixed eqn[4])
-GL_ENTRY(void, glGenBuffers, GLsizei n, GLuint *buffers)
-GL_ENTRY(void, glGenTextures, GLsizei n, GLuint *textures)
-GL_ENTRY(GLenum, glGetError, void)
-GL_ENTRY(void, glGetFixedv, GLenum pname, GLfixed *params)
-GL_ENTRY(void, glGetIntegerv, GLenum pname, GLint *params)
-GL_ENTRY(void, glGetLightxv, GLenum light, GLenum pname, GLfixed *params)
-GL_ENTRY(void, glGetMaterialxv, GLenum face, GLenum pname, GLfixed *params)
-GL_ENTRY(void, glGetPointerv, GLenum pname, void **params)
-GL_ENTRY(const GLubyte *, glGetString, GLenum name)
-GL_ENTRY(void, glGetTexEnviv, GLenum env, GLenum pname, GLint *params)
-GL_ENTRY(void, glGetTexEnvxv, GLenum env, GLenum pname, GLfixed *params)
-GL_ENTRY(void, glGetTexParameteriv, GLenum target, GLenum pname, GLint *params)
-GL_ENTRY(void, glGetTexParameterxv, GLenum target, GLenum pname, GLfixed *params)
-GL_ENTRY(void, glHint, GLenum target, GLenum mode)
-GL_ENTRY(GLboolean, glIsBuffer, GLuint buffer)
-GL_ENTRY(GLboolean, glIsEnabled, GLenum cap)
-GL_ENTRY(GLboolean, glIsTexture, GLuint texture)
-GL_ENTRY(void, glLightModelx, GLenum pname, GLfixed param)
-GL_ENTRY(void, glLightModelxv, GLenum pname, const GLfixed *params)
-GL_ENTRY(void, glLightx, GLenum light, GLenum pname, GLfixed param)
-GL_ENTRY(void, glLightxv, GLenum light, GLenum pname, const GLfixed *params)
-GL_ENTRY(void, glLineWidthx, GLfixed width)
-GL_ENTRY(void, glLoadIdentity, void)
-GL_ENTRY(void, glLoadMatrixx, const GLfixed *m)
-GL_ENTRY(void, glLogicOp, GLenum opcode)
-GL_ENTRY(void, glMaterialx, GLenum face, GLenum pname, GLfixed param)
-GL_ENTRY(void, glMaterialxv, GLenum face, GLenum pname, const GLfixed *params)
-GL_ENTRY(void, glMatrixMode, GLenum mode)
-GL_ENTRY(void, glMultMatrixx, const GLfixed *m)
-GL_ENTRY(void, glMultiTexCoord4x, GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q)
-GL_ENTRY(void, glNormal3x, GLfixed nx, GLfixed ny, GLfixed nz)
-GL_ENTRY(void, glNormalPointer, GLenum type, GLsizei stride, const GLvoid *pointer)
-GL_ENTRY(void, glOrthox, GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar)
-GL_ENTRY(void, glPixelStorei, GLenum pname, GLint param)
-GL_ENTRY(void, glPointParameterx, GLenum pname, GLfixed param)
-GL_ENTRY(void, glPointParameterxv, GLenum pname, const GLfixed *params)
-GL_ENTRY(void, glPointSizex, GLfixed size)
-GL_ENTRY(void, glPolygonOffsetx, GLfixed factor, GLfixed units)
-GL_ENTRY(void, glPopMatrix, void)
-GL_ENTRY(void, glPushMatrix, void)
-GL_ENTRY(void, glReadPixels, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels)
-GL_ENTRY(void, glRotatex, GLfixed angle, GLfixed x, GLfixed y, GLfixed z)
-GL_ENTRY(void, glSampleCoverage, GLclampf value, GLboolean invert)
-GL_ENTRY(void, glSampleCoveragex, GLclampx value, GLboolean invert)
-GL_ENTRY(void, glScalex, GLfixed x, GLfixed y, GLfixed z)
-GL_ENTRY(void, glScissor, GLint x, GLint y, GLsizei width, GLsizei height)
-GL_ENTRY(void, glShadeModel, GLenum mode)
-GL_ENTRY(void, glStencilFunc, GLenum func, GLint ref, GLuint mask)
-GL_ENTRY(void, glStencilMask, GLuint mask)
-GL_ENTRY(void, glStencilOp, GLenum fail, GLenum zfail, GLenum zpass)
-GL_ENTRY(void, glTexCoordPointer, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
-GL_ENTRY(void, glTexEnvi, GLenum target, GLenum pname, GLint param)
-GL_ENTRY(void, glTexEnvx, GLenum target, GLenum pname, GLfixed param)
-GL_ENTRY(void, glTexEnviv, GLenum target, GLenum pname, const GLint *params)
-GL_ENTRY(void, glTexEnvxv, GLenum target, GLenum pname, const GLfixed *params)
-GL_ENTRY(void, glTexImage2D, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels)
-GL_ENTRY(void, glTexParameteri, GLenum target, GLenum pname, GLint param)
-GL_ENTRY(void, glTexParameterx, GLenum target, GLenum pname, GLfixed param)
-GL_ENTRY(void, glTexParameteriv, GLenum target, GLenum pname, const GLint *params)
-GL_ENTRY(void, glTexParameterxv, GLenum target, GLenum pname, const GLfixed *params)
-GL_ENTRY(void, glTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels)
-GL_ENTRY(void, glTranslatex, GLfixed x, GLfixed y, GLfixed z)
-GL_ENTRY(void, glVertexPointer, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
-GL_ENTRY(void, glViewport, GLint x, GLint y, GLsizei width, GLsizei height)
-GL_ENTRY(void, glPointSizePointerOES, GLenum type, GLsizei stride, const GLvoid *pointer)
diff --git a/opengl/libs/gl_enums.in b/opengl/libs/gl_enums.in
deleted file mode 100644
index ffc2fad..0000000
--- a/opengl/libs/gl_enums.in
+++ /dev/null
@@ -1,261 +0,0 @@
-GLENUM(GL_POINTS, 0x0000)
-GLENUM(GL_LINES, 0x0001)
-GLENUM(GL_LINE_LOOP, 0x0002)
-GLENUM(GL_LINE_STRIP, 0x0003)
-GLENUM(GL_TRIANGLES, 0x0004)
-GLENUM(GL_TRIANGLE_STRIP, 0x0005)
-GLENUM(GL_TRIANGLE_FAN, 0x0006)
-GLENUM(GL_ADD, 0x0104)
-GLENUM(GL_NEVER, 0x0200)
-GLENUM(GL_LESS, 0x0201)
-GLENUM(GL_EQUAL, 0x0202)
-GLENUM(GL_LEQUAL, 0x0203)
-GLENUM(GL_GREATER, 0x0204)
-GLENUM(GL_NOTEQUAL, 0x0205)
-GLENUM(GL_GEQUAL, 0x0206)
-GLENUM(GL_ALWAYS, 0x0207)
-GLENUM(GL_SRC_COLOR, 0x0300)
-GLENUM(GL_ONE_MINUS_SRC_COLOR, 0x0301)
-GLENUM(GL_SRC_ALPHA, 0x0302)
-GLENUM(GL_ONE_MINUS_SRC_ALPHA, 0x0303)
-GLENUM(GL_DST_ALPHA, 0x0304)
-GLENUM(GL_ONE_MINUS_DST_ALPHA, 0x0305)
-GLENUM(GL_DST_COLOR, 0x0306)
-GLENUM(GL_ONE_MINUS_DST_COLOR, 0x0307)
-GLENUM(GL_SRC_ALPHA_SATURATE, 0x0308)
-GLENUM(GL_FRONT, 0x0404)
-GLENUM(GL_BACK, 0x0405)
-GLENUM(GL_FRONT_AND_BACK, 0x0408)
-GLENUM(GL_INVALID_ENUM, 0x0500)
-GLENUM(GL_INVALID_VALUE, 0x0501)
-GLENUM(GL_INVALID_OPERATION, 0x0502)
-GLENUM(GL_STACK_OVERFLOW, 0x0503)
-GLENUM(GL_STACK_UNDERFLOW, 0x0504)
-GLENUM(GL_OUT_OF_MEMORY, 0x0505)
-GLENUM(GL_EXP, 0x0800)
-GLENUM(GL_EXP2, 0x0801)
-GLENUM(GL_CW, 0x0900)
-GLENUM(GL_CCW, 0x0901)
-GLENUM(GL_POINT_SMOOTH, 0x0B10)
-GLENUM(GL_SMOOTH_POINT_SIZE_RANGE, 0x0B12)
-GLENUM(GL_LINE_SMOOTH, 0x0B20)
-GLENUM(GL_SMOOTH_LINE_WIDTH_RANGE, 0x0B22)
-GLENUM(GL_CULL_FACE, 0x0B44)
-GLENUM(GL_LIGHTING, 0x0B50)
-GLENUM(GL_LIGHT_MODEL_TWO_SIDE, 0x0B52)
-GLENUM(GL_LIGHT_MODEL_AMBIENT, 0x0B53)
-GLENUM(GL_COLOR_MATERIAL, 0x0B57)
-GLENUM(GL_FOG, 0x0B60)
-GLENUM(GL_FOG_DENSITY, 0x0B62)
-GLENUM(GL_FOG_START, 0x0B63)
-GLENUM(GL_FOG_END, 0x0B64)
-GLENUM(GL_FOG_MODE, 0x0B65)
-GLENUM(GL_FOG_COLOR, 0x0B66)
-GLENUM(GL_DEPTH_TEST, 0x0B71)
-GLENUM(GL_STENCIL_TEST, 0x0B90)
-GLENUM(GL_NORMALIZE, 0x0BA1)
-GLENUM(GL_ALPHA_TEST, 0x0BC0)
-GLENUM(GL_DITHER, 0x0BD0)
-GLENUM(GL_BLEND, 0x0BE2)
-GLENUM(GL_COLOR_LOGIC_OP, 0x0BF2)
-GLENUM(GL_SCISSOR_TEST, 0x0C11)
-GLENUM(GL_PERSPECTIVE_CORRECTION_HINT, 0x0C50)
-GLENUM(GL_POINT_SMOOTH_HINT, 0x0C51)
-GLENUM(GL_LINE_SMOOTH_HINT, 0x0C52)
-GLENUM(GL_POLYGON_SMOOTH_HINT, 0x0C53)
-GLENUM(GL_FOG_HINT, 0x0C54)
-GLENUM(GL_UNPACK_ALIGNMENT, 0x0CF5)
-GLENUM(GL_PACK_ALIGNMENT, 0x0D05)
-GLENUM(GL_MAX_LIGHTS, 0x0D31)
-GLENUM(GL_MAX_CLIP_PLANES, 0x0D32)
-GLENUM(GL_MAX_TEXTURE_SIZE, 0x0D33)
-GLENUM(GL_MAX_MODELVIEW_STACK_DEPTH, 0x0D36)
-GLENUM(GL_MAX_PROJECTION_STACK_DEPTH, 0x0D38)
-GLENUM(GL_MAX_TEXTURE_STACK_DEPTH, 0x0D39)
-GLENUM(GL_MAX_VIEWPORT_DIMS, 0x0D3A)
-GLENUM(GL_RED_BITS, 0x0D52)
-GLENUM(GL_GREEN_BITS, 0x0D53)
-GLENUM(GL_BLUE_BITS, 0x0D54)
-GLENUM(GL_ALPHA_BITS, 0x0D55)
-GLENUM(GL_DEPTH_BITS, 0x0D56)
-GLENUM(GL_STENCIL_BITS, 0x0D57)
-GLENUM(GL_TEXTURE_2D, 0x0DE1)
-GLENUM(GL_DONT_CARE, 0x1100)
-GLENUM(GL_FASTEST, 0x1101)
-GLENUM(GL_NICEST, 0x1102)
-GLENUM(GL_AMBIENT, 0x1200)
-GLENUM(GL_DIFFUSE, 0x1201)
-GLENUM(GL_SPECULAR, 0x1202)
-GLENUM(GL_POSITION, 0x1203)
-GLENUM(GL_SPOT_DIRECTION, 0x1204)
-GLENUM(GL_SPOT_EXPONENT, 0x1205)
-GLENUM(GL_SPOT_CUTOFF, 0x1206)
-GLENUM(GL_CONSTANT_ATTENUATION, 0x1207)
-GLENUM(GL_LINEAR_ATTENUATION, 0x1208)
-GLENUM(GL_QUADRATIC_ATTENUATION, 0x1209)
-GLENUM(GL_BYTE, 0x1400)
-GLENUM(GL_UNSIGNED_BYTE, 0x1401)
-GLENUM(GL_SHORT, 0x1402)
-GLENUM(GL_UNSIGNED_SHORT, 0x1403)
-GLENUM(GL_FLOAT, 0x1406)
-GLENUM(GL_FIXED, 0x140C)
-GLENUM(GL_CLEAR, 0x1500)
-GLENUM(GL_AND, 0x1501)
-GLENUM(GL_AND_REVERSE, 0x1502)
-GLENUM(GL_COPY, 0x1503)
-GLENUM(GL_AND_INVERTED, 0x1504)
-GLENUM(GL_NOOP, 0x1505)
-GLENUM(GL_XOR, 0x1506)
-GLENUM(GL_OR, 0x1507)
-GLENUM(GL_NOR, 0x1508)
-GLENUM(GL_EQUIV, 0x1509)
-GLENUM(GL_INVERT, 0x150A)
-GLENUM(GL_OR_REVERSE, 0x150B)
-GLENUM(GL_COPY_INVERTED, 0x150C)
-GLENUM(GL_OR_INVERTED, 0x150D)
-GLENUM(GL_NAND, 0x150E)
-GLENUM(GL_SET, 0x150F)
-GLENUM(GL_EMISSION, 0x1600)
-GLENUM(GL_SHININESS, 0x1601)
-GLENUM(GL_AMBIENT_AND_DIFFUSE, 0x1602)
-GLENUM(GL_MODELVIEW, 0x1700)
-GLENUM(GL_PROJECTION, 0x1701)
-GLENUM(GL_TEXTURE, 0x1702)
-GLENUM(GL_ALPHA, 0x1906)
-GLENUM(GL_RGB, 0x1907)
-GLENUM(GL_RGBA, 0x1908)
-GLENUM(GL_LUMINANCE, 0x1909)
-GLENUM(GL_LUMINANCE_ALPHA, 0x190A)
-GLENUM(GL_FLAT, 0x1D00)
-GLENUM(GL_SMOOTH, 0x1D01)
-GLENUM(GL_KEEP, 0x1E00)
-GLENUM(GL_REPLACE, 0x1E01)
-GLENUM(GL_REPLACE, 0x1E01)
-GLENUM(GL_INCR, 0x1E02)
-GLENUM(GL_DECR, 0x1E03)
-GLENUM(GL_VENDOR, 0x1F00)
-GLENUM(GL_RENDERER, 0x1F01)
-GLENUM(GL_VERSION, 0x1F02)
-GLENUM(GL_EXTENSIONS, 0x1F03)
-GLENUM(GL_MODULATE, 0x2100)
-GLENUM(GL_DECAL, 0x2101)
-GLENUM(GL_TEXTURE_ENV_MODE, 0x2200)
-GLENUM(GL_TEXTURE_ENV_COLOR, 0x2201)
-GLENUM(GL_TEXTURE_ENV, 0x2300)
-GLENUM(GL_NEAREST, 0x2600)
-GLENUM(GL_LINEAR, 0x2601)
-GLENUM(GL_NEAREST_MIPMAP_NEAREST, 0x2700)
-GLENUM(GL_LINEAR_MIPMAP_NEAREST, 0x2701)
-GLENUM(GL_NEAREST_MIPMAP_LINEAR, 0x2702)
-GLENUM(GL_LINEAR_MIPMAP_LINEAR, 0x2703)
-GLENUM(GL_TEXTURE_MAG_FILTER, 0x2800)
-GLENUM(GL_TEXTURE_MIN_FILTER, 0x2801)
-GLENUM(GL_TEXTURE_WRAP_S, 0x2802)
-GLENUM(GL_TEXTURE_WRAP_T, 0x2803)
-GLENUM(GL_CLAMP, 0x2900)
-GLENUM(GL_REPEAT, 0x2901)
-GLENUM(GL_CLIP_PLANE0, 0x3000)
-GLENUM(GL_CLIP_PLANE1, 0x3001)
-GLENUM(GL_CLIP_PLANE2, 0x3002)
-GLENUM(GL_CLIP_PLANE3, 0x3003)
-GLENUM(GL_CLIP_PLANE4, 0x3004)
-GLENUM(GL_CLIP_PLANE5, 0x3005)
-GLENUM(GL_LIGHT0, 0x4000)
-GLENUM(GL_LIGHT1, 0x4001)
-GLENUM(GL_LIGHT2, 0x4002)
-GLENUM(GL_LIGHT3, 0x4003)
-GLENUM(GL_LIGHT4, 0x4004)
-GLENUM(GL_LIGHT5, 0x4005)
-GLENUM(GL_LIGHT6, 0x4006)
-GLENUM(GL_LIGHT7, 0x4007)
-GLENUM(GL_DIRECT_TEXTURE_2D_QUALCOMM, 0x7E80)
-GLENUM(GL_UNSIGNED_SHORT_4_4_4_4, 0x8033)
-GLENUM(GL_UNSIGNED_SHORT_5_5_5_1, 0x8034)
-GLENUM(GL_POLYGON_OFFSET_FILL, 0x8037)
-GLENUM(GL_RESCALE_NORMAL, 0x803A)
-GLENUM(GL_VERTEX_ARRAY, 0x8074)
-GLENUM(GL_NORMAL_ARRAY, 0x8075)
-GLENUM(GL_COLOR_ARRAY, 0x8076)
-GLENUM(GL_TEXTURE_COORD_ARRAY, 0x8078)
-GLENUM(GL_MULTISAMPLE, 0x809D)
-GLENUM(GL_SAMPLE_ALPHA_TO_COVERAGE, 0x809E)
-GLENUM(GL_SAMPLE_ALPHA_TO_ONE, 0x809F)
-GLENUM(GL_SAMPLE_COVERAGE, 0x80A0)
-GLENUM(GL_MAX_ELEMENTS_VERTICES, 0x80E8)
-GLENUM(GL_MAX_ELEMENTS_INDICES, 0x80E9)
-GLENUM(GL_CLAMP_TO_EDGE, 0x812F)
-GLENUM(GL_GENERATE_MIPMAP, 0x8191)
-GLENUM(GL_GENERATE_MIPMAP_HINT, 0x8192)
-GLENUM(GL_UNSIGNED_SHORT_5_6_5, 0x8363)
-GLENUM(GL_ALIASED_POINT_SIZE_RANGE, 0x846D)
-GLENUM(GL_ALIASED_LINE_WIDTH_RANGE, 0x846E)
-GLENUM(GL_TEXTURE0, 0x84C0)
-GLENUM(GL_TEXTURE1, 0x84C1)
-GLENUM(GL_TEXTURE2, 0x84C2)
-GLENUM(GL_TEXTURE3, 0x84C3)
-GLENUM(GL_TEXTURE4, 0x84C4)
-GLENUM(GL_TEXTURE5, 0x84C5)
-GLENUM(GL_TEXTURE6, 0x84C6)
-GLENUM(GL_TEXTURE7, 0x84C7)
-GLENUM(GL_TEXTURE8, 0x84C8)
-GLENUM(GL_TEXTURE9, 0x84C9)
-GLENUM(GL_TEXTURE10, 0x84CA)
-GLENUM(GL_TEXTURE11, 0x84CB)
-GLENUM(GL_TEXTURE12, 0x84CC)
-GLENUM(GL_TEXTURE13, 0x84CD)
-GLENUM(GL_TEXTURE14, 0x84CE)
-GLENUM(GL_TEXTURE15, 0x84CF)
-GLENUM(GL_TEXTURE16, 0x84D0)
-GLENUM(GL_TEXTURE17, 0x84D1)
-GLENUM(GL_TEXTURE18, 0x84D2)
-GLENUM(GL_TEXTURE19, 0x84D3)
-GLENUM(GL_TEXTURE20, 0x84D4)
-GLENUM(GL_TEXTURE21, 0x84D5)
-GLENUM(GL_TEXTURE22, 0x84D6)
-GLENUM(GL_TEXTURE23, 0x84D7)
-GLENUM(GL_TEXTURE24, 0x84D8)
-GLENUM(GL_TEXTURE25, 0x84D9)
-GLENUM(GL_TEXTURE26, 0x84DA)
-GLENUM(GL_TEXTURE27, 0x84DB)
-GLENUM(GL_TEXTURE28, 0x84DC)
-GLENUM(GL_TEXTURE29, 0x84DD)
-GLENUM(GL_TEXTURE30, 0x84DE)
-GLENUM(GL_TEXTURE31, 0x84DF)
-GLENUM(GL_MAX_TEXTURE_UNITS, 0x84E2)
-GLENUM(GL_NUM_COMPRESSED_TEXTURE_FORMATS, 0x86A2)
-GLENUM(GL_COMPRESSED_TEXTURE_FORMATS, 0x86A3)
-GLENUM(GL_BUFFER_SIZE, 0x8764)
-GLENUM(GL_BUFFER_USAGE, 0x8765)
-GLENUM(GL_POINT_SPRITE_OES, 0x8861)
-GLENUM(GL_COORD_REPLACE_OES, 0x8862)
-GLENUM(GL_ARRAY_BUFFER, 0x8892)
-GLENUM(GL_ELEMENT_ARRAY_BUFFER, 0x8893)
-GLENUM(GL_ARRAY_BUFFER_BINDING, 0x8894)
-GLENUM(GL_ELEMENT_ARRAY_BUFFER_BINDING, 0x8895)
-GLENUM(GL_VERTEX_ARRAY_BUFFER_BINDING, 0x8896)
-GLENUM(GL_NORMAL_ARRAY_BUFFER_BINDING, 0x8897)
-GLENUM(GL_COLOR_ARRAY_BUFFER_BINDING, 0x8898)
-GLENUM(GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING, 0x889A)
-GLENUM(GL_STATIC_DRAW, 0x88E4)
-GLENUM(GL_DYNAMIC_DRAW, 0x88E8)
-GLENUM(GL_POINT_SIZE_ARRAY_TYPE_OES, 0x898A)
-GLENUM(GL_POINT_SIZE_ARRAY_STRIDE_OES, 0x898B)
-GLENUM(GL_POINT_SIZE_ARRAY_POINTER_OES, 0x898C)
-GLENUM(GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES, 0x898D)
-GLENUM(GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES, 0x898E)
-GLENUM(GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES, 0x898F)
-GLENUM(GL_PALETTE4_RGB8_OES, 0x8B90)
-GLENUM(GL_PALETTE4_RGBA8_OES, 0x8B91)
-GLENUM(GL_PALETTE4_R5_G6_B5_OES, 0x8B92)
-GLENUM(GL_PALETTE4_RGBA4_OES, 0x8B93)
-GLENUM(GL_PALETTE4_RGB5_A1_OES, 0x8B94)
-GLENUM(GL_PALETTE8_RGB8_OES, 0x8B95)
-GLENUM(GL_PALETTE8_RGBA8_OES, 0x8B96)
-GLENUM(GL_PALETTE8_R5_G6_B5_OES, 0x8B97)
-GLENUM(GL_PALETTE8_RGBA4_OES, 0x8B98)
-GLENUM(GL_PALETTE8_RGB5_A1_OES, 0x8B99)
-GLENUM(GL_IMPLEMENTATION_COLOR_READ_TYPE_OES, 0x8B9A)
-GLENUM(GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES, 0x8B9B)
-GLENUM(GL_POINT_SIZE_ARRAY_OES, 0x8B9C)
-GLENUM(GL_TEXTURE_CROP_RECT_OES, 0x8B9D)
-GLENUM(GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES, 0x8B9F)
diff --git a/opengl/libs/glext_entries.in b/opengl/libs/glext_entries.in
deleted file mode 100644
index dd09c71..0000000
--- a/opengl/libs/glext_entries.in
+++ /dev/null
@@ -1,90 +0,0 @@
-GL_ENTRY(void, glBlendEquationSeparateOES, GLenum modeRGB, GLenum modeAlpha)
-GL_ENTRY(void, glBlendFuncSeparateOES, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
-GL_ENTRY(void, glBlendEquationOES, GLenum mode)
-GL_ENTRY(void, glDrawTexsOES, GLshort x, GLshort y, GLshort z, GLshort width, GLshort height)
-GL_ENTRY(void, glDrawTexiOES, GLint x, GLint y, GLint z, GLint width, GLint height)
-GL_ENTRY(void, glDrawTexxOES, GLfixed x, GLfixed y, GLfixed z, GLfixed width, GLfixed height)
-GL_ENTRY(void, glDrawTexsvOES, const GLshort *coords)
-GL_ENTRY(void, glDrawTexivOES, const GLint *coords)
-GL_ENTRY(void, glDrawTexxvOES, const GLfixed *coords)
-GL_ENTRY(void, glDrawTexfOES, GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height)
-GL_ENTRY(void, glDrawTexfvOES, const GLfloat *coords)
-GL_ENTRY(void, glEGLImageTargetTexture2DOES, GLenum target, GLeglImageOES image)
-GL_ENTRY(void, glEGLImageTargetRenderbufferStorageOES, GLenum target, GLeglImageOES image)
-GL_ENTRY(void, glAlphaFuncxOES, GLenum func, GLclampx ref)
-GL_ENTRY(void, glClearColorxOES, GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha)
-GL_ENTRY(void, glClearDepthxOES, GLclampx depth)
-GL_ENTRY(void, glClipPlanexOES, GLenum plane, const GLfixed *equation)
-GL_ENTRY(void, glColor4xOES, GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha)
-GL_ENTRY(void, glDepthRangexOES, GLclampx zNear, GLclampx zFar)
-GL_ENTRY(void, glFogxOES, GLenum pname, GLfixed param)
-GL_ENTRY(void, glFogxvOES, GLenum pname, const GLfixed *params)
-GL_ENTRY(void, glFrustumxOES, GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar)
-GL_ENTRY(void, glGetClipPlanexOES, GLenum pname, GLfixed eqn[4])
-GL_ENTRY(void, glGetFixedvOES, GLenum pname, GLfixed *params)
-GL_ENTRY(void, glGetLightxvOES, GLenum light, GLenum pname, GLfixed *params)
-GL_ENTRY(void, glGetMaterialxvOES, GLenum face, GLenum pname, GLfixed *params)
-GL_ENTRY(void, glGetTexEnvxvOES, GLenum env, GLenum pname, GLfixed *params)
-GL_ENTRY(void, glGetTexParameterxvOES, GLenum target, GLenum pname, GLfixed *params)
-GL_ENTRY(void, glLightModelxOES, GLenum pname, GLfixed param)
-GL_ENTRY(void, glLightModelxvOES, GLenum pname, const GLfixed *params)
-GL_ENTRY(void, glLightxOES, GLenum light, GLenum pname, GLfixed param)
-GL_ENTRY(void, glLightxvOES, GLenum light, GLenum pname, const GLfixed *params)
-GL_ENTRY(void, glLineWidthxOES, GLfixed width)
-GL_ENTRY(void, glLoadMatrixxOES, const GLfixed *m)
-GL_ENTRY(void, glMaterialxOES, GLenum face, GLenum pname, GLfixed param)
-GL_ENTRY(void, glMaterialxvOES, GLenum face, GLenum pname, const GLfixed *params)
-GL_ENTRY(void, glMultMatrixxOES, const GLfixed *m)
-GL_ENTRY(void, glMultiTexCoord4xOES, GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q)
-GL_ENTRY(void, glNormal3xOES, GLfixed nx, GLfixed ny, GLfixed nz)
-GL_ENTRY(void, glOrthoxOES, GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar)
-GL_ENTRY(void, glPointParameterxOES, GLenum pname, GLfixed param)
-GL_ENTRY(void, glPointParameterxvOES, GLenum pname, const GLfixed *params)
-GL_ENTRY(void, glPointSizexOES, GLfixed size)
-GL_ENTRY(void, glPolygonOffsetxOES, GLfixed factor, GLfixed units)
-GL_ENTRY(void, glRotatexOES, GLfixed angle, GLfixed x, GLfixed y, GLfixed z)
-GL_ENTRY(void, glSampleCoveragexOES, GLclampx value, GLboolean invert)
-GL_ENTRY(void, glScalexOES, GLfixed x, GLfixed y, GLfixed z)
-GL_ENTRY(void, glTexEnvxOES, GLenum target, GLenum pname, GLfixed param)
-GL_ENTRY(void, glTexEnvxvOES, GLenum target, GLenum pname, const GLfixed *params)
-GL_ENTRY(void, glTexParameterxOES, GLenum target, GLenum pname, GLfixed param)
-GL_ENTRY(void, glTexParameterxvOES, GLenum target, GLenum pname, const GLfixed *params)
-GL_ENTRY(void, glTranslatexOES, GLfixed x, GLfixed y, GLfixed z)
-GL_ENTRY(GLboolean, glIsRenderbufferOES, GLuint renderbuffer)
-GL_ENTRY(void, glBindRenderbufferOES, GLenum target, GLuint renderbuffer)
-GL_ENTRY(void, glDeleteRenderbuffersOES, GLsizei n, const GLuint* renderbuffers)
-GL_ENTRY(void, glGenRenderbuffersOES, GLsizei n, GLuint* renderbuffers)
-GL_ENTRY(void, glRenderbufferStorageOES, GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
-GL_ENTRY(void, glGetRenderbufferParameterivOES, GLenum target, GLenum pname, GLint* params)
-GL_ENTRY(GLboolean, glIsFramebufferOES, GLuint framebuffer)
-GL_ENTRY(void, glBindFramebufferOES, GLenum target, GLuint framebuffer)
-GL_ENTRY(void, glDeleteFramebuffersOES, GLsizei n, const GLuint* framebuffers)
-GL_ENTRY(void, glGenFramebuffersOES, GLsizei n, GLuint* framebuffers)
-GL_ENTRY(GLenum, glCheckFramebufferStatusOES, GLenum target)
-GL_ENTRY(void, glFramebufferRenderbufferOES, GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
-GL_ENTRY(void, glFramebufferTexture2DOES, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
-GL_ENTRY(void, glGetFramebufferAttachmentParameterivOES, GLenum target, GLenum attachment, GLenum pname, GLint* params)
-GL_ENTRY(void, glGenerateMipmapOES, GLenum target)
-GL_ENTRY(void*, glMapBufferOES, GLenum target, GLenum access)
-GL_ENTRY(GLboolean, glUnmapBufferOES, GLenum target)
-GL_ENTRY(void, glGetBufferPointervOES, GLenum target, GLenum pname, void** params)
-GL_ENTRY(void, glCurrentPaletteMatrixOES, GLuint matrixpaletteindex)
-GL_ENTRY(void, glLoadPaletteFromModelViewMatrixOES, void)
-GL_ENTRY(void, glMatrixIndexPointerOES, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
-GL_ENTRY(void, glWeightPointerOES, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
-GL_ENTRY(GLbitfield, glQueryMatrixxOES, GLfixed mantissa[16], GLint exponent[16])
-GL_ENTRY(void, glDepthRangefOES, GLclampf zNear, GLclampf zFar)
-GL_ENTRY(void, glFrustumfOES, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar)
-GL_ENTRY(void, glOrthofOES, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar)
-GL_ENTRY(void, glClipPlanefOES, GLenum plane, const GLfloat *equation)
-GL_ENTRY(void, glGetClipPlanefOES, GLenum pname, GLfloat eqn[4])
-GL_ENTRY(void, glClearDepthfOES, GLclampf depth)
-GL_ENTRY(void, glTexGenfOES, GLenum coord, GLenum pname, GLfloat param)
-GL_ENTRY(void, glTexGenfvOES, GLenum coord, GLenum pname, const GLfloat *params)
-GL_ENTRY(void, glTexGeniOES, GLenum coord, GLenum pname, GLint param)
-GL_ENTRY(void, glTexGenivOES, GLenum coord, GLenum pname, const GLint *params)
-GL_ENTRY(void, glTexGenxOES, GLenum coord, GLenum pname, GLfixed param)
-GL_ENTRY(void, glTexGenxvOES, GLenum coord, GLenum pname, const GLfixed *params)
-GL_ENTRY(void, glGetTexGenfvOES, GLenum coord, GLenum pname, GLfloat *params)
-GL_ENTRY(void, glGetTexGenivOES, GLenum coord, GLenum pname, GLint *params)
-GL_ENTRY(void, glGetTexGenxvOES, GLenum coord, GLenum pname, GLfixed *params)
diff --git a/opengl/libs/hooks.h b/opengl/libs/hooks.h
index fd97254..f47f093 100644
--- a/opengl/libs/hooks.h
+++ b/opengl/libs/hooks.h
@@ -21,10 +21,14 @@
 #include <string.h>
 #include <errno.h>
 
+#include <pthread.h>
+
 #include <EGL/egl.h>
 #include <EGL/eglext.h>
 #include <GLES/gl.h>
 #include <GLES/glext.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
 
 #if !defined(__arm__)
 #define USE_SLOW_BINDING            1
@@ -56,15 +60,14 @@
 enum {
     IMPL_HARDWARE = 0,
     IMPL_SOFTWARE,
-    
-    IMPL_NUM_DRIVERS_IMPLEMENTATIONS,
-
-    IMPL_CONTEXT_LOST = IMPL_NUM_DRIVERS_IMPLEMENTATIONS,
-    IMPL_NO_CONTEXT,
-    
     IMPL_NUM_IMPLEMENTATIONS
 };
 
+enum {
+    GLESv1_INDEX = 0,
+    GLESv2_INDEX = 1,
+};
+
 // ----------------------------------------------------------------------------
 
 // GL / EGL hooks
@@ -74,14 +77,14 @@
 #define GL_ENTRY(_r, _api, ...) _r (*_api)(__VA_ARGS__);
 #define EGL_ENTRY(_r, _api, ...) _r (*_api)(__VA_ARGS__);
 
+struct egl_t {
+    #include "EGL/egl_entries.in"
+};
+
 struct gl_hooks_t {
     struct gl_t {
-        #include "gl_entries.in"
-        #include "glext_entries.in"
+        #include "entries.in"
     } gl;
-    struct egl_t {
-        #include "egl_entries.in"
-    } egl;
     struct gl_ext_t {
         void (*extensions[MAX_NUMBER_OF_GL_EXTENSIONS])(void);
     } ext;
@@ -92,8 +95,15 @@
 
 // ----------------------------------------------------------------------------
 
-extern gl_hooks_t gHooks[IMPL_NUM_IMPLEMENTATIONS];
+extern gl_hooks_t gHooks[2][IMPL_NUM_IMPLEMENTATIONS];
+extern gl_hooks_t gHooksNoContext;
 extern pthread_key_t gGLWrapperKey;
+extern "C" void gl_unimplemented();
+
+extern char const * const gl_names[];
+extern char const * const egl_names[];
+
+// ----------------------------------------------------------------------------
 
 #if USE_FAST_TLS_KEY
 
@@ -114,7 +124,7 @@
     gl_hooks_t const * volatile * tls_hooks = get_tls_hooks();
     gl_hooks_t const* hooks = tls_hooks[TLS_SLOT_OPENGL_API];
     if (hooks) return hooks;
-    return &gHooks[IMPL_NO_CONTEXT];
+    return &gHooksNoContext;
 }
 
 #else
@@ -126,7 +136,7 @@
 static gl_hooks_t const* getGlThreadSpecific() {
     gl_hooks_t const* hooks =  static_cast<gl_hooks_t*>(pthread_getspecific(gGLWrapperKey));
     if (hooks) return hooks;
-    return &gHooks[IMPL_NO_CONTEXT];
+    return &gHooksNoContext;
 }
 
 #endif
diff --git a/opengl/libs/tools/enumextract.sh b/opengl/libs/tools/enumextract.sh
deleted file mode 100644
index 5707302..0000000
--- a/opengl/libs/tools/enumextract.sh
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/bin/sh
-
-awk '
-/^#define GL_/ {
-    names[count] = $2;
-    values[count] = $3;
-    sort[count] = $3 + 0;
-    count++;
-}
-END {
-    for (i = 1; i < count; i++) {
-        for (j = 0; j < i; j++) {
-            if (sort[i] < sort[j]) {
-                tn = names[i];
-                tv = values[i];
-                ts = sort[i];
-                names[i] = names[j];
-                values[i] = values[j];
-                sort[i] = sort[j];
-                names[j] = tn;
-                values[j] = tv;
-                sort[j] = ts;
-            }
-        }
-    }
- 
-    for (i = 0; i < count; i++) {
-        printf("GLENUM(%s, %s)\n", names[i], values[i]);
-    }
-}
-' < $1
-
diff --git a/opengl/libs/tools/genfiles b/opengl/libs/tools/genfiles
index 107768b..120cb4b 100755
--- a/opengl/libs/tools/genfiles
+++ b/opengl/libs/tools/genfiles
@@ -14,7 +14,20 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-./glapigen ../../include/GLES/gl.h > ../GLES_CM/gl_api.in 
-./glentrygen ../../include/GLES/gl.h > ../gl_entries.in 
-./glapigen ../../include/GLES/glext.h > ../GLES_CM/glext_api.in 
-./glentrygen ../../include/GLES/glext.h > ../glext_entries.in 
+./glapigen ../../include/GLES/gl.h      > ../GLES_CM/gl_api.in
+./glapigen ../../include/GLES/glext.h   > ../GLES_CM/glext_api.in
+./glapigen ../../include/GLES2/gl2.h    > ../GLES2/gl2_api.in
+./glapigen ../../include/GLES2/gl2ext.h > ../GLES2/gl2ext_api.in
+
+./glentrygen ../../include/GLES/gl.h      > /tmp/gl_entries.in
+./glentrygen ../../include/GLES/glext.h   > /tmp/glext_entries.in
+./glentrygen ../../include/GLES2/gl2.h    > /tmp/gl2_entries.in
+./glentrygen ../../include/GLES2/gl2ext.h > /tmp/gl2ext_entries.in
+
+cat /tmp/gl_entries.in \
+    /tmp/glext_entries.in \
+    /tmp/gl2_entries.in \
+    /tmp/gl2ext_entries.in \
+        | sort -t, -k2 \
+        | awk -F, '!_[$2]++' \
+            > ../entries.in
diff --git a/opengl/libs/tools/glapigen b/opengl/libs/tools/glapigen
index a2c3a7b..bd8dda3 100755
--- a/opengl/libs/tools/glapigen
+++ b/opengl/libs/tools/glapigen
@@ -16,16 +16,23 @@
 
 use strict;
 
+sub rtrim($)
+{
+    my $string = shift;
+    $string =~ s/\s+$//;
+    return $string;
+}
+
 while (my $line = <>) {
   next if $line =~ /^\//;
   next if $line =~ /^#/;
   next if $line =~ /^\s*$/;
-  if ($line !~ /^GL_API\s+(.+)\s+GL_APIENTRY\s+([\w]+)\s*\(([^\)]+)\);/) {
+  if ($line !~ /^GL_API(CALL)?\s+(.+)\s+GL_APIENTRY\s+([\w]+)\s*\(([^\)]+)\);/) {
     next;
   }
-  my $type = $1;
-  my $name = $2;
-  my $args = $3;
+  my $type = rtrim($2);
+  my $name = $3;
+  my $args = $4;
 
   #printf("%s", $line);
   
diff --git a/opengl/libs/tools/glentrygen b/opengl/libs/tools/glentrygen
index 5e0f7b6..170f041 100755
--- a/opengl/libs/tools/glentrygen
+++ b/opengl/libs/tools/glentrygen
@@ -16,16 +16,23 @@
 
 use strict;
 
+sub rtrim($)
+{
+    my $string = shift;
+    $string =~ s/\s+$//;
+    return $string;
+}
+
 while (my $line = <>) {
   next if $line =~ /^\//;
   next if $line =~ /^#/;
   next if $line =~ /^\s*$/;
-  if ($line !~ /^GL_API\s+(.+)\s+GL_APIENTRY\s+([\w]+)\s*\(([^\)]+)\);/) {
+  if ($line !~ /^GL_API(CALL)?\s+(.+)\s+GL_APIENTRY\s+([\w]+)\s*\(([^\)]+)\);/) {
     next;
   }
-  my $type = $1;
-  my $name = $2;
-  my $args = $3;
+  my $type = rtrim($2);
+  my $name = $3;
+  my $args = $4;
 
   printf("GL_ENTRY(%s, %s, %s)\n", $type, $name, $args);
 }
diff --git a/opengl/tests/angeles/Android.mk b/opengl/tests/angeles/Android.mk
index e193483..d0c3221 100644
--- a/opengl/tests/angeles/Android.mk
+++ b/opengl/tests/angeles/Android.mk
@@ -2,7 +2,7 @@
 
 LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
-LOCAL_SRC_FILES:= app-linux.c demo.c.arm
+LOCAL_SRC_FILES:= app-linux.cpp demo.c.arm
 LOCAL_SHARED_LIBRARIES := libEGL libGLESv1_CM libui
 LOCAL_MODULE:= angeles
 LOCAL_MODULE_TAGS := optional
diff --git a/opengl/tests/angeles/app-linux.c b/opengl/tests/angeles/app-linux.cpp
similarity index 86%
rename from opengl/tests/angeles/app-linux.c
rename to opengl/tests/angeles/app-linux.cpp
index 7d0d320..06fa0c2 100644
--- a/opengl/tests/angeles/app-linux.c
+++ b/opengl/tests/angeles/app-linux.cpp
@@ -52,6 +52,11 @@
 #include <EGL/egl.h>
 #include <GLES/gl.h>
 
+#include <ui/FramebufferNativeWindow.h>
+#include <ui/EGLUtils.h>
+
+using namespace android;
+
 #include "app.h"
 
 
@@ -115,48 +120,33 @@
 
 static int initGraphics()
 {
-    EGLint s_configAttribs[] = {
-         EGL_RED_SIZE,       5,
-         EGL_GREEN_SIZE,     6,
-         EGL_BLUE_SIZE,      5,
- #if 1
-         EGL_DEPTH_SIZE,     16,
-         EGL_STENCIL_SIZE,   0,
- #else
-         EGL_ALPHA_SIZE,     EGL_DONT_CARE,
-         EGL_DEPTH_SIZE,     EGL_DONT_CARE,
-         EGL_STENCIL_SIZE,   EGL_DONT_CARE,
-         EGL_SURFACE_TYPE,   EGL_DONT_CARE,
- #endif
+    EGLint configAttribs[] = {
+         EGL_DEPTH_SIZE, 16,
          EGL_NONE
      };
      
-     EGLint numConfigs = -1;
      EGLint majorVersion;
      EGLint minorVersion;
-     EGLConfig config;
      EGLContext context;
+     EGLConfig config;
      EGLSurface surface;
-     
+     EGLint w, h;
      EGLDisplay dpy;
 
+     EGLNativeWindowType window = android_createDisplaySurface();
+     
      dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
-     egl_error("eglGetDisplay");
-     fprintf(stderr,"dpy = 0x%08x\n", (unsigned) dpy);
-     
      eglInitialize(dpy, &majorVersion, &minorVersion);
-     egl_error("eglInitialize");
+          
+     status_t err = EGLUtils::selectConfigForNativeWindow(
+             dpy, configAttribs, window, &config);
+     if (err) {
+         fprintf(stderr, "couldn't find an EGLConfig matching the screen format\n");
+         return 0;
+     }
 
-     eglGetConfigs(dpy, NULL, 0, &numConfigs);
-     egl_error("eglGetConfigs");
-     fprintf(stderr,"num configs %d\n", numConfigs);
-     
-     eglChooseConfig(dpy, s_configAttribs, &config, 1, &numConfigs);
-     egl_error("eglChooseConfig");
-
-     surface = eglCreateWindowSurface(dpy, config,
-             android_createDisplaySurface(), NULL);
-     egl_error("eglMapWindowSurface");
+     surface = eglCreateWindowSurface(dpy, config, window, NULL);
+     egl_error("eglCreateWindowSurface");
 
      fprintf(stderr,"surface = %p\n", surface);
 
diff --git a/opengl/tests/fillrate/Android.mk b/opengl/tests/fillrate/Android.mk
new file mode 100644
index 0000000..a7d30c2
--- /dev/null
+++ b/opengl/tests/fillrate/Android.mk
@@ -0,0 +1,17 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+	fillrate.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+	libcutils \
+    libEGL \
+    libGLESv1_CM \
+    libui
+
+LOCAL_MODULE:= test-opengl-fillrate
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_EXECUTABLE)
diff --git a/opengl/tests/fillrate/fillrate.cpp b/opengl/tests/fillrate/fillrate.cpp
new file mode 100644
index 0000000..911d354
--- /dev/null
+++ b/opengl/tests/fillrate/fillrate.cpp
@@ -0,0 +1,161 @@
+/*
+**
+** Copyright 2006, 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 "fillrate"
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <EGL/egl.h>
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+
+#include <utils/StopWatch.h>
+#include <ui/FramebufferNativeWindow.h>
+#include <ui/EGLUtils.h>
+
+using namespace android;
+
+int main(int argc, char** argv)
+{
+    EGLint configAttribs[] = {
+         EGL_DEPTH_SIZE, 0,
+         EGL_NONE
+     };
+     
+     EGLint majorVersion;
+     EGLint minorVersion;
+     EGLContext context;
+     EGLConfig config;
+     EGLSurface surface;
+     EGLint w, h;
+     EGLDisplay dpy;
+
+     EGLNativeWindowType window = android_createDisplaySurface();
+     
+     dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+     eglInitialize(dpy, &majorVersion, &minorVersion);
+          
+     status_t err = EGLUtils::selectConfigForNativeWindow(
+             dpy, configAttribs, window, &config);
+     if (err) {
+         fprintf(stderr, "couldn't find an EGLConfig matching the screen format\n");
+         return 0;
+     }
+
+     surface = eglCreateWindowSurface(dpy, config, window, NULL);
+     context = eglCreateContext(dpy, config, NULL, NULL);
+     eglMakeCurrent(dpy, surface, surface, context);   
+     eglQuerySurface(dpy, surface, EGL_WIDTH, &w);
+     eglQuerySurface(dpy, surface, EGL_HEIGHT, &h);
+     
+     printf("w=%d, h=%d\n", w, h);
+     
+     glBindTexture(GL_TEXTURE_2D, 0);
+     glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+     glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+     glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+     glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+     glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+     glDisable(GL_DITHER);
+     glEnable(GL_BLEND);
+     glEnable(GL_TEXTURE_2D);
+     glColor4f(1,1,1,1);
+
+     uint32_t* t32 = (uint32_t*)malloc(512*512*4); 
+     for (int y=0 ; y<512 ; y++) {
+         for (int x=0 ; x<512 ; x++) {
+             int u = x-256;
+             int v = y-256;
+             if (u*u+v*v < 256*256) {
+                 t32[x+y*512] = 0x10FFFFFF;
+             } else {
+                 t32[x+y*512] = 0x20FF0000;
+             }
+         }
+     }
+
+     const GLfloat vertices[4][2] = {
+             { 0,  0 },
+             { 0,  h },
+             { w,  h },
+             { w,  0 }
+     };
+
+     const GLfloat texCoords[4][2] = {
+             { 0,  0 },
+             { 0,  1 },
+             { 1,  1 },
+             { 1,  0 }
+     };
+
+     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 512, 512, 0, GL_RGBA, GL_UNSIGNED_BYTE, t32);
+
+     glViewport(0, 0, w, h);
+     glMatrixMode(GL_PROJECTION);
+     glLoadIdentity();
+     glOrthof(0, w, 0, h, 0, 1);
+
+     glEnableClientState(GL_VERTEX_ARRAY);
+     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+     glVertexPointer(2, GL_FLOAT, 0, vertices);
+     glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
+
+     eglSwapInterval(dpy, 1);
+
+     glClearColor(1,0,0,0);
+     glClear(GL_COLOR_BUFFER_BIT);
+     glDrawArrays(GL_TRIANGLE_FAN, 0, 4); 
+     eglSwapBuffers(dpy, surface);
+     
+
+     nsecs_t times[32];
+
+     for (int c=1 ; c<32 ; c++) {
+         glClear(GL_COLOR_BUFFER_BIT);
+         for (int i=0 ; i<c ; i++) {
+             glDrawArrays(GL_TRIANGLE_FAN, 0, 4); 
+         }
+         eglSwapBuffers(dpy, surface);
+     }
+
+
+     //     for (int c=31 ; c>=1 ; c--) {
+     int j=0;
+     for (int c=1 ; c<32 ; c++) {
+         glClear(GL_COLOR_BUFFER_BIT);
+         nsecs_t now = systemTime();
+         for (int i=0 ; i<c ; i++) {
+             glDrawArrays(GL_TRIANGLE_FAN, 0, 4); 
+         }
+         eglSwapBuffers(dpy, surface);
+         nsecs_t t = systemTime() - now;
+         times[j++] = t;
+     }
+
+     for (int c=1, j=0 ; c<32 ; c++, j++) {
+         nsecs_t t = times[j];
+         printf("%lld\t%d\t%f\n", t, c, (double(t)/c)/1000000.0);
+     }
+
+
+       
+     eglTerminate(dpy);
+     
+     return 0;
+}
diff --git a/opengl/tests/filter/Android.mk b/opengl/tests/filter/Android.mk
index 31b7d9a..a254127 100644
--- a/opengl/tests/filter/Android.mk
+++ b/opengl/tests/filter/Android.mk
@@ -2,7 +2,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:= \
-	filter.c
+	filter.cpp
 
 LOCAL_SHARED_LIBRARIES := \
 	libcutils \
@@ -14,4 +14,6 @@
 
 LOCAL_MODULE_TAGS := optional
 
+LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES
+
 include $(BUILD_EXECUTABLE)
diff --git a/opengl/tests/filter/filter.c b/opengl/tests/filter/filter.cpp
similarity index 68%
rename from opengl/tests/filter/filter.c
rename to opengl/tests/filter/filter.cpp
index de97119..2351909 100644
--- a/opengl/tests/filter/filter.c
+++ b/opengl/tests/filter/filter.cpp
@@ -5,6 +5,13 @@
 #include <GLES/gl.h>
 #include <GLES/glext.h>
 
+#include <ui/FramebufferNativeWindow.h>
+#include <ui/EGLUtils.h>
+
+using namespace android;
+
+#define USE_DRAW_TEXTURE 1
+
 int main(int argc, char** argv)
 {
     if (argc!=2 && argc!=3) {
@@ -32,14 +39,20 @@
      
      EGLDisplay dpy;
 
+     EGLNativeWindowType window = 0;
+     if (!usePbuffer) {
+         window = android_createDisplaySurface();
+     }
+     
      dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
      eglInitialize(dpy, &majorVersion, &minorVersion);
-     eglChooseConfig(dpy, s_configAttribs, &config, 1, &numConfigs);
      if (!usePbuffer) {
-         surface = eglCreateWindowSurface(dpy, config,
-                 android_createDisplaySurface(), NULL);
+         EGLUtils::selectConfigForNativeWindow(
+                 dpy, s_configAttribs, window, &config);
+         surface = eglCreateWindowSurface(dpy, config, window, NULL);
      } else {
          printf("using pbuffer\n");
+         eglChooseConfig(dpy, s_configAttribs, &config, 1, &numConfigs);
          EGLint attribs[] = { EGL_WIDTH, 320, EGL_HEIGHT, 480, EGL_NONE };
          surface = eglCreatePbufferSurface(dpy, config, attribs);
          if (surface == EGL_NO_SURFACE) {
@@ -52,6 +65,12 @@
      eglQuerySurface(dpy, surface, EGL_HEIGHT, &h);
      GLint dim = w<h ? w : h;
 
+     glViewport(0, 0, w, h);
+     glMatrixMode(GL_PROJECTION);
+     glLoadIdentity();
+     glOrthof(0, w, 0, h, 0, 1);
+
+     glClearColor(0,0,0,0);
      glClear(GL_COLOR_BUFFER_BIT);
 
      GLint crop[4] = { 0, 4, 4, -4 };
@@ -117,14 +136,55 @@
          break;
      }
 
-     glDrawTexiOES(0, 0, 0, dim, dim);
+     //glDrawTexiOES(0, 0, 0, dim, dim);
+     
+     const GLfloat vertices[4][2] = {
+             { 0,    0   },
+             { 0,    dim },
+             { dim,  dim },
+             { dim,  0   }
+     };
 
+     const GLfloat texCoords[4][2] = {
+             { 0,  0 },
+             { 0,  1 },
+             { 1,  1 },
+             { 1,  0 }
+     };
+     
      if (!usePbuffer) {
          eglSwapBuffers(dpy, surface);
-     } else {
-         glFinish();
      }
      
+     glMatrixMode(GL_MODELVIEW);
+     glScissor(0,dim,dim,h-dim);
+     glDisable(GL_SCISSOR_TEST);
+     
+     for (int y=0 ; y<dim ; y++) {
+         //glDisable(GL_SCISSOR_TEST);
+         glClear(GL_COLOR_BUFFER_BIT);
+
+         //glEnable(GL_SCISSOR_TEST);
+
+#if USE_DRAW_TEXTURE && GL_OES_draw_texture
+         glDrawTexiOES(0, y, 1, dim, dim);
+#else
+         glLoadIdentity();
+         glTranslatef(0, y, 0);
+         glEnableClientState(GL_VERTEX_ARRAY);
+         glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+         glVertexPointer(2, GL_FLOAT, 0, vertices);
+         glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
+         glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+#endif
+
+         if (!usePbuffer) {
+             eglSwapBuffers(dpy, surface);
+         } else {
+             glFinish();
+         }
+     }
+
      eglTerminate(dpy);
      return 0;
 }
diff --git a/opengl/tests/finish/Android.mk b/opengl/tests/finish/Android.mk
index 8b46cd7..5620814 100644
--- a/opengl/tests/finish/Android.mk
+++ b/opengl/tests/finish/Android.mk
@@ -2,7 +2,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:= \
-	finish.c
+	finish.cpp
 
 LOCAL_SHARED_LIBRARIES := \
 	libcutils \
@@ -14,4 +14,6 @@
 
 LOCAL_MODULE_TAGS := optional
 
+LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES
+
 include $(BUILD_EXECUTABLE)
diff --git a/opengl/tests/finish/finish.c b/opengl/tests/finish/finish.cpp
similarity index 90%
rename from opengl/tests/finish/finish.c
rename to opengl/tests/finish/finish.cpp
index 45fc758..91f5c45 100644
--- a/opengl/tests/finish/finish.c
+++ b/opengl/tests/finish/finish.cpp
@@ -24,39 +24,41 @@
 #include <GLES/gl.h>
 #include <GLES/glext.h>
 
+#include <utils/Timers.h>
 
-long long systemTime()
-{
-    struct timespec t;
-    t.tv_sec = t.tv_nsec = 0;
-    clock_gettime(CLOCK_MONOTONIC, &t);
-    return (long long)(t.tv_sec)*1000000000LL + t.tv_nsec;
-}
+#include <ui/FramebufferNativeWindow.h>
+#include <ui/EGLUtils.h>
+
+using namespace android;
 
 int main(int argc, char** argv)
 {
-    EGLint s_configAttribs[] = {
-         EGL_RED_SIZE,       5,
-         EGL_GREEN_SIZE,     6,
-         EGL_BLUE_SIZE,      5,
+    EGLint configAttribs[] = {
+         EGL_DEPTH_SIZE, 0,
          EGL_NONE
      };
      
-     EGLint numConfigs = -1;
      EGLint majorVersion;
      EGLint minorVersion;
-     EGLConfig config;
      EGLContext context;
+     EGLConfig config;
      EGLSurface surface;
      EGLint w, h;
-     
      EGLDisplay dpy;
 
+     EGLNativeWindowType window = android_createDisplaySurface();
+     
      dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
      eglInitialize(dpy, &majorVersion, &minorVersion);
-     eglChooseConfig(dpy, s_configAttribs, &config, 1, &numConfigs);
-     surface = eglCreateWindowSurface(dpy, config, 
-             android_createDisplaySurface(), NULL);
+          
+     status_t err = EGLUtils::selectConfigForNativeWindow(
+             dpy, configAttribs, window, &config);
+     if (err) {
+         fprintf(stderr, "couldn't find an EGLConfig matching the screen format\n");
+         return 0;
+     }
+
+     surface = eglCreateWindowSurface(dpy, config, window, NULL);
      context = eglCreateContext(dpy, config, NULL, NULL);
      eglMakeCurrent(dpy, surface, surface, context);   
      eglQuerySurface(dpy, surface, EGL_WIDTH, &w);
@@ -75,13 +77,13 @@
      long long now, t;
      int i;
 
-     char* texels = malloc(512*512*2);
+     char* texels = (char*)malloc(512*512*2);
      memset(texels,0xFF,512*512*2);
      
      glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
              512, 512, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, texels);
 
-     char* dst = malloc(320*480*2);
+     char* dst = (char*)malloc(320*480*2);
      memset(dst, 0, 320*480*2);
      printf("307200 bytes memcpy\n");
      for (i=0 ; i<4 ; i++) {
diff --git a/opengl/tests/gl2_basic/Android.mk b/opengl/tests/gl2_basic/Android.mk
new file mode 100644
index 0000000..a642eaf
--- /dev/null
+++ b/opengl/tests/gl2_basic/Android.mk
@@ -0,0 +1,19 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+	gl2_basic.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+	libcutils \
+    libEGL \
+    libGLESv2 \
+    libui
+
+LOCAL_MODULE:= test-opengl-gl2_basic
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES
+
+include $(BUILD_EXECUTABLE)
diff --git a/opengl/tests/gl2_basic/gl2_basic.cpp b/opengl/tests/gl2_basic/gl2_basic.cpp
new file mode 100644
index 0000000..2361db5
--- /dev/null
+++ b/opengl/tests/gl2_basic/gl2_basic.cpp
@@ -0,0 +1,357 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+#include <sched.h>
+#include <sys/resource.h>
+
+#include <EGL/egl.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+#include <utils/Timers.h>
+
+#include <ui/FramebufferNativeWindow.h>
+#include <ui/EGLUtils.h>
+
+using namespace android;
+
+static void printGLString(const char *name, GLenum s) {
+    // fprintf(stderr, "printGLString %s, %d\n", name, s);
+    const char *v = (const char *) glGetString(s);
+    // int error = glGetError();
+    // fprintf(stderr, "glGetError() = %d, result of glGetString = %x\n", error,
+    //        (unsigned int) v);
+    // if ((v < (const char*) 0) || (v > (const char*) 0x10000))
+    //    fprintf(stderr, "GL %s = %s\n", name, v);
+    // else
+    //    fprintf(stderr, "GL %s = (null) 0x%08x\n", name, (unsigned int) v);
+    fprintf(stderr, "GL %s = %s\n", name, v);
+}
+
+static void checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE) {
+    if (returnVal != EGL_TRUE) {
+        fprintf(stderr, "%s() returned %d\n", op, returnVal);
+    }
+
+    for (EGLint error = eglGetError(); error != EGL_SUCCESS; error
+            = eglGetError()) {
+        fprintf(stderr, "after %s() eglError %s (0x%x)\n", op, EGLUtils::strerror(error),
+                error);
+    }
+}
+
+static void checkGlError(const char* op) {
+    for (GLint error = glGetError(); error; error
+            = glGetError()) {
+        fprintf(stderr, "after %s() glError (0x%x)\n", op, error);
+    }
+}
+
+static const char gVertexShader[] = "attribute vec4 vPosition;\n"
+    "void main() {\n"
+    "  gl_Position = vPosition;\n"
+    "}\n";
+
+static const char gFragmentShader[] = "precision mediump float;\n"
+    "void main() {\n"
+    "  gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
+    "}\n";
+
+GLuint loadShader(GLenum shaderType, const char* pSource) {
+    GLuint shader = glCreateShader(shaderType);
+    if (shader) {
+        glShaderSource(shader, 1, &pSource, NULL);
+        glCompileShader(shader);
+        GLint compiled = 0;
+        glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
+        if (!compiled) {
+            GLint infoLen = 0;
+            glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
+            if (infoLen) {
+                char* buf = (char*) malloc(infoLen);
+                if (buf) {
+                    glGetShaderInfoLog(shader, infoLen, NULL, buf);
+                    fprintf(stderr, "Could not compile shader %d:\n%s\n",
+                            shaderType, buf);
+                    free(buf);
+                }
+                glDeleteShader(shader);
+                shader = 0;
+            }
+        }
+    }
+    return shader;
+}
+
+GLuint createProgram(const char* pVertexSource, const char* pFragmentSource) {
+    GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource);
+    if (!vertexShader) {
+        return 0;
+    }
+
+    GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource);
+    if (!pixelShader) {
+        return 0;
+    }
+
+    GLuint program = glCreateProgram();
+    if (program) {
+        glAttachShader(program, vertexShader);
+        checkGlError("glAttachShader");
+        glAttachShader(program, pixelShader);
+        checkGlError("glAttachShader");
+        glLinkProgram(program);
+        GLint linkStatus = GL_FALSE;
+        glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
+        if (linkStatus != GL_TRUE) {
+            GLint bufLength = 0;
+            glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
+            if (bufLength) {
+                char* buf = (char*) malloc(bufLength);
+                if (buf) {
+                    glGetProgramInfoLog(program, bufLength, NULL, buf);
+                    fprintf(stderr, "Could not link program:\n%s\n", buf);
+                    free(buf);
+                }
+            }
+            glDeleteProgram(program);
+            program = 0;
+        }
+    }
+    return program;
+}
+
+GLuint gProgram;
+GLuint gvPositionHandle;
+
+bool setupGraphics(int w, int h) {
+    gProgram = createProgram(gVertexShader, gFragmentShader);
+    if (!gProgram) {
+        return false;
+    }
+    gvPositionHandle = glGetAttribLocation(gProgram, "vPosition");
+    checkGlError("glGetAttribLocation");
+    fprintf(stderr, "glGetAttribLocation(\"vPosition\") = %d\n",
+            gvPositionHandle);
+
+    glViewport(0, 0, w, h);
+    checkGlError("glViewport");
+    return true;
+}
+
+const GLfloat gTriangleVertices[] = { 0.0f, 0.5f, -0.5f, -0.5f,
+        0.5f, -0.5f };
+
+void renderFrame() {
+    glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
+    checkGlError("glClearColor");
+    glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
+    checkGlError("glClear");
+
+    glUseProgram(gProgram);
+    checkGlError("glUseProgram");
+
+    glVertexAttribPointer(gvPositionHandle, 2, GL_FLOAT, GL_FALSE, 0, gTriangleVertices);
+    checkGlError("glVertexAttribPointer");
+    glEnableVertexAttribArray(gvPositionHandle);
+    checkGlError("glEnableVertexAttribArray");
+    glDrawArrays(GL_TRIANGLES, 0, 3);
+    checkGlError("glDrawArrays");
+}
+
+void printEGLConfiguration(EGLDisplay dpy, EGLConfig config) {
+
+#define X(VAL) {VAL, #VAL}
+    struct {EGLint attribute; const char* name;} names[] = {
+    X(EGL_BUFFER_SIZE),
+    X(EGL_ALPHA_SIZE),
+    X(EGL_BLUE_SIZE),
+    X(EGL_GREEN_SIZE),
+    X(EGL_RED_SIZE),
+    X(EGL_DEPTH_SIZE),
+    X(EGL_STENCIL_SIZE),
+    X(EGL_CONFIG_CAVEAT),
+    X(EGL_CONFIG_ID),
+    X(EGL_LEVEL),
+    X(EGL_MAX_PBUFFER_HEIGHT),
+    X(EGL_MAX_PBUFFER_PIXELS),
+    X(EGL_MAX_PBUFFER_WIDTH),
+    X(EGL_NATIVE_RENDERABLE),
+    X(EGL_NATIVE_VISUAL_ID),
+    X(EGL_NATIVE_VISUAL_TYPE),
+    X(EGL_PRESERVED_RESOURCES),
+    X(EGL_SAMPLES),
+    X(EGL_SAMPLE_BUFFERS),
+    X(EGL_SURFACE_TYPE),
+    X(EGL_TRANSPARENT_TYPE),
+    X(EGL_TRANSPARENT_RED_VALUE),
+    X(EGL_TRANSPARENT_GREEN_VALUE),
+    X(EGL_TRANSPARENT_BLUE_VALUE),
+    X(EGL_BIND_TO_TEXTURE_RGB),
+    X(EGL_BIND_TO_TEXTURE_RGBA),
+    X(EGL_MIN_SWAP_INTERVAL),
+    X(EGL_MAX_SWAP_INTERVAL),
+    X(EGL_LUMINANCE_SIZE),
+    X(EGL_ALPHA_MASK_SIZE),
+    X(EGL_COLOR_BUFFER_TYPE),
+    X(EGL_RENDERABLE_TYPE),
+    X(EGL_CONFORMANT),
+   };
+#undef X
+
+    for (size_t j = 0; j < sizeof(names) / sizeof(names[0]); j++) {
+        EGLint value = -1;
+        EGLint returnVal = eglGetConfigAttrib(dpy, config, names[j].attribute, &value);
+        EGLint error = eglGetError();
+        if (returnVal && error == EGL_SUCCESS) {
+            printf(" %s: ", names[j].name);
+            printf("%d (0x%x)", value, value);
+        }
+    }
+    printf("\n");
+}
+
+int printEGLConfigurations(EGLDisplay dpy) {
+    EGLint numConfig = 0;
+    EGLint returnVal = eglGetConfigs(dpy, NULL, 0, &numConfig);
+    checkEglError("eglGetConfigs", returnVal);
+    if (!returnVal) {
+        return false;
+    }
+
+    printf("Number of EGL configuration: %d\n", numConfig);
+
+    EGLConfig* configs = (EGLConfig*) malloc(sizeof(EGLConfig) * numConfig);
+    if (! configs) {
+        printf("Could not allocate configs.\n");
+        return false;
+    }
+
+    returnVal = eglGetConfigs(dpy, configs, numConfig, &numConfig);
+    checkEglError("eglGetConfigs", returnVal);
+    if (!returnVal) {
+        free(configs);
+        return false;
+    }
+
+    for(int i = 0; i < numConfig; i++) {
+        printf("Configuration %d\n", i);
+        printEGLConfiguration(dpy, configs[i]);
+    }
+
+    free(configs);
+    return true;
+}
+
+int main(int argc, char** argv) {
+    EGLBoolean returnValue;
+    EGLConfig myConfig = {0};
+
+    EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
+    EGLint s_configAttribs[] = {
+            EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+            EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+            EGL_NONE };
+    EGLint majorVersion;
+    EGLint minorVersion;
+    EGLContext context;
+    EGLSurface surface;
+    EGLint w, h;
+
+    EGLDisplay dpy;
+
+    checkEglError("<init>");
+    dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+    checkEglError("eglGetDisplay");
+    if (dpy == EGL_NO_DISPLAY) {
+        printf("eglGetDisplay returned EGL_NO_DISPLAY.\n");
+        return 0;
+    }
+
+    returnValue = eglInitialize(dpy, &majorVersion, &minorVersion);
+    checkEglError("eglInitialize", returnValue);
+    fprintf(stderr, "EGL version %d.%d\n", majorVersion, minorVersion);
+    if (returnValue != EGL_TRUE) {
+        printf("eglInitialize failed\n");
+        return 0;
+    }
+
+    if (!printEGLConfigurations(dpy)) {
+        printf("printEGLConfigurations failed\n");
+        return 0;
+    }
+
+    checkEglError("printEGLConfigurations");
+
+    EGLNativeWindowType window = android_createDisplaySurface();

+    returnValue = EGLUtils::selectConfigForNativeWindow(dpy, s_configAttribs, window, &myConfig);
+    if (returnValue) {
+        printf("EGLUtils::selectConfigForNativeWindow() returned %d", returnValue);
+        return 0;
+    }
+
+    checkEglError("EGLUtils::selectConfigForNativeWindow");
+
+    printf("Chose this configuration:\n");
+    printEGLConfiguration(dpy, myConfig);
+
+    surface = eglCreateWindowSurface(dpy, myConfig, window, NULL);
+    checkEglError("eglCreateWindowSurface");
+    if (surface == EGL_NO_SURFACE) {
+        printf("gelCreateWindowSurface failed.\n");
+        return 0;
+    }
+
+    context = eglCreateContext(dpy, myConfig, EGL_NO_CONTEXT, context_attribs);
+    checkEglError("eglCreateContext");
+    if (context == EGL_NO_CONTEXT) {
+        printf("eglCreateContext failed\n");
+        return 0;
+    }
+    returnValue = eglMakeCurrent(dpy, surface, surface, context);
+    checkEglError("eglMakeCurrent", returnValue);
+    if (returnValue != EGL_TRUE) {
+        return 0;
+    }
+    eglQuerySurface(dpy, surface, EGL_WIDTH, &w);
+    checkEglError("eglQuerySurface");
+    eglQuerySurface(dpy, surface, EGL_HEIGHT, &h);
+    checkEglError("eglQuerySurface");
+    GLint dim = w < h ? w : h;
+
+    fprintf(stderr, "Window dimensions: %d x %d\n", w, h);
+
+    printGLString("Version", GL_VERSION);
+    printGLString("Vendor", GL_VENDOR);
+    printGLString("Renderer", GL_RENDERER);
+    printGLString("Extensions", GL_EXTENSIONS);
+
+    if(!setupGraphics(w, h)) {
+        fprintf(stderr, "Could not set up graphics.\n");
+        return 0;
+    }
+
+    for (;;) {
+        renderFrame();
+        eglSwapBuffers(dpy, surface);
+        checkEglError("eglSwapBuffers");
+    }
+
+    return 0;
+}
diff --git a/opengl/tests/gl2_jni/Android.mk b/opengl/tests/gl2_jni/Android.mk
new file mode 100644
index 0000000..81247df
--- /dev/null
+++ b/opengl/tests/gl2_jni/Android.mk
@@ -0,0 +1,51 @@
+#########################################################################
+# OpenGL ES JNI sample
+# This makefile builds both an activity and a shared library.
+#########################################################################
+ifneq ($(TARGET_SIMULATOR),true) # not 64 bit clean
+
+TOP_LOCAL_PATH:= $(call my-dir)
+
+# Build activity
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := user
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := GL2JNI
+
+LOCAL_JNI_SHARED_LIBRARIES := libgl2jni
+
+include $(BUILD_PACKAGE)
+
+#########################################################################
+# Build JNI Shared Library
+#########################################################################
+
+LOCAL_PATH:= $(LOCAL_PATH)/jni
+
+include $(CLEAR_VARS)
+
+# Optional tag would mean it doesn't get installed by default
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_CFLAGS := -Werror
+
+LOCAL_SRC_FILES:= \
+  gl_code.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+	libutils \
+	libEGL \
+	libGLESv2
+
+LOCAL_MODULE := libgl2jni
+
+LOCAL_PRELINK_MODULE := false
+
+include $(BUILD_SHARED_LIBRARY)
+
+endif # TARGET_SIMULATOR
diff --git a/opengl/tests/gl2_jni/AndroidManifest.xml b/opengl/tests/gl2_jni/AndroidManifest.xml
new file mode 100644
index 0000000..a72a6a5
--- /dev/null
+++ b/opengl/tests/gl2_jni/AndroidManifest.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2009, 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.
+*/
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.gl2jni">
+    <application
+            android:label="@string/gl2jni_activity">
+        <activity android:name="GL2JNIActivity"
+                android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
+            	android:launchMode="singleTask"
+            	android:configChanges="orientation|keyboardHidden">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/opengl/tests/gl2_jni/jni/gl_code.cpp b/opengl/tests/gl2_jni/jni/gl_code.cpp
new file mode 100644
index 0000000..c2fabe6
--- /dev/null
+++ b/opengl/tests/gl2_jni/jni/gl_code.cpp
@@ -0,0 +1,165 @@
+// OpenGL ES 2.0 code
+
+#include <nativehelper/jni.h>
+#define LOG_TAG "GL2JNI gl_code.cpp"
+#include <utils/Log.h>
+
+#include <EGL/egl.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+static void printGLString(const char *name, GLenum s) {
+    const char *v = (const char *) glGetString(s);
+    LOGI("GL %s = %s\n", name, v);
+}
+
+static void checkGlError(const char* op) {
+    for (GLint error = glGetError(); error; error
+            = glGetError()) {
+        LOGI("after %s() glError (0x%x)\n", op, error);
+    }
+}
+
+static const char gVertexShader[] = "attribute vec4 vPosition;\n"
+    "void main() {\n"
+    "  gl_Position = vPosition;\n"
+    "}\n";
+
+static const char gFragmentShader[] = "precision mediump float;\n"
+    "void main() {\n"
+    "  gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
+    "}\n";
+
+GLuint loadShader(GLenum shaderType, const char* pSource) {
+    GLuint shader = glCreateShader(shaderType);
+    if (shader) {
+        glShaderSource(shader, 1, &pSource, NULL);
+        glCompileShader(shader);
+        GLint compiled = 0;
+        glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
+        if (!compiled) {
+            GLint infoLen = 0;
+            glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
+            if (infoLen) {
+                char* buf = (char*) malloc(infoLen);
+                if (buf) {
+                    glGetShaderInfoLog(shader, infoLen, NULL, buf);
+                    LOGE("Could not compile shader %d:\n%s\n",
+                            shaderType, buf);
+                    free(buf);
+                }
+                glDeleteShader(shader);
+                shader = 0;
+            }
+        }
+    }
+    return shader;
+}
+
+GLuint createProgram(const char* pVertexSource, const char* pFragmentSource) {
+    GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource);
+    if (!vertexShader) {
+        return 0;
+    }
+
+    GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource);
+    if (!pixelShader) {
+        return 0;
+    }
+
+    GLuint program = glCreateProgram();
+    if (program) {
+        glAttachShader(program, vertexShader);
+        checkGlError("glAttachShader");
+        glAttachShader(program, pixelShader);
+        checkGlError("glAttachShader");
+        glLinkProgram(program);
+        GLint linkStatus = GL_FALSE;
+        glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
+        if (linkStatus != GL_TRUE) {
+            GLint bufLength = 0;
+            glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
+            if (bufLength) {
+                char* buf = (char*) malloc(bufLength);
+                if (buf) {
+                    glGetProgramInfoLog(program, bufLength, NULL, buf);
+                    LOGE("Could not link program:\n%s\n", buf);
+                    free(buf);
+                }
+            }
+            glDeleteProgram(program);
+            program = 0;
+        }
+    }
+    return program;
+}
+
+GLuint gProgram;
+GLuint gvPositionHandle;
+
+bool setupGraphics(int w, int h) {
+    printGLString("Version", GL_VERSION);
+    printGLString("Vendor", GL_VENDOR);
+    printGLString("Renderer", GL_RENDERER);
+    printGLString("Extensions", GL_EXTENSIONS);
+
+    LOGI("setupGraphics(%d, %d)", w, h);
+    gProgram = createProgram(gVertexShader, gFragmentShader);
+    if (!gProgram) {
+        LOGE("Could not create program.");
+        return false;
+    }
+    gvPositionHandle = glGetAttribLocation(gProgram, "vPosition");
+    checkGlError("glGetAttribLocation");
+    LOGI("glGetAttribLocation(\"vPosition\") = %d\n",
+            gvPositionHandle);
+
+    glViewport(0, 0, w, h);
+    checkGlError("glViewport");
+    return true;
+}
+
+const GLfloat gTriangleVertices[] = { 0.0f, 0.5f, -0.5f, -0.5f,
+        0.5f, -0.5f };
+
+void renderFrame() {
+    static float grey;
+    grey += 0.01f;
+    if (grey > 1.0f) {
+        grey = 0.0f;
+    }
+    glClearColor(grey, grey, grey, 1.0f);
+    checkGlError("glClearColor");
+    glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
+    checkGlError("glClear");
+
+    glUseProgram(gProgram);
+    checkGlError("glUseProgram");
+
+    glVertexAttribPointer(gvPositionHandle, 2, GL_FLOAT, GL_FALSE, 0, gTriangleVertices);
+    checkGlError("glVertexAttribPointer");
+    glEnableVertexAttribArray(gvPositionHandle);
+    checkGlError("glEnableVertexAttribArray");
+    glDrawArrays(GL_TRIANGLES, 0, 3);
+    checkGlError("glDrawArrays");
+}
+
+extern "C" {
+    JNIEXPORT void JNICALL Java_com_android_gl2jni_GL2JNILib_init(JNIEnv * env, jobject obj,  jint width, jint height);
+    JNIEXPORT void JNICALL Java_com_android_gl2jni_GL2JNILib_step(JNIEnv * env, jobject obj);
+};
+
+JNIEXPORT void JNICALL Java_com_android_gl2jni_GL2JNILib_init(JNIEnv * env, jobject obj,  jint width, jint height)

+{
+    setupGraphics(width, height);
+}
+
+JNIEXPORT void JNICALL Java_com_android_gl2jni_GL2JNILib_step(JNIEnv * env, jobject obj)
+{
+    renderFrame();
+}
+
diff --git a/opengl/tests/gl2_jni/res/values/strings.xml b/opengl/tests/gl2_jni/res/values/strings.xml
new file mode 100644
index 0000000..e3f7331
--- /dev/null
+++ b/opengl/tests/gl2_jni/res/values/strings.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2006, 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.
+*/
+-->
+
+<!-- This file contains resource definitions for displayed strings, allowing
+     them to be changed based on the locale and options. -->
+
+<resources>
+    <!-- Simple strings. -->
+    <string name="gl2jni_activity">GL2JNI</string>
+
+</resources>
+
diff --git a/opengl/tests/gl2_jni/src/com/android/gl2jni/GL2JNIActivity.java b/opengl/tests/gl2_jni/src/com/android/gl2jni/GL2JNIActivity.java
new file mode 100644
index 0000000..c366a2c
--- /dev/null
+++ b/opengl/tests/gl2_jni/src/com/android/gl2jni/GL2JNIActivity.java
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+package com.android.gl2jni;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.WindowManager;
+
+import java.io.File;
+
+
+public class GL2JNIActivity extends Activity {
+
+    GL2JNIView mView;
+
+    @Override protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        mView = new GL2JNIView(getApplication());
+	setContentView(mView);
+    }
+
+    @Override protected void onPause() {
+        super.onPause();
+        mView.onPause();
+    }
+
+    @Override protected void onResume() {
+        super.onResume();
+        mView.onResume();
+    }
+}
diff --git a/opengl/tests/gl2_jni/src/com/android/gl2jni/GL2JNILib.java b/opengl/tests/gl2_jni/src/com/android/gl2jni/GL2JNILib.java
new file mode 100644
index 0000000..040a984
--- /dev/null
+++ b/opengl/tests/gl2_jni/src/com/android/gl2jni/GL2JNILib.java
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+package com.android.gl2jni;
+
+// Wrapper for native library
+
+public class GL2JNILib {
+
+     static {
+         System.loadLibrary("gl2jni");
+     }
+
+    /**
+     * @param width the current view width
+     * @param height the current view height
+     */
+     public static native void init(int width, int height);
+     public static native void step();
+}
diff --git a/opengl/tests/gl2_jni/src/com/android/gl2jni/GL2JNIView.java b/opengl/tests/gl2_jni/src/com/android/gl2jni/GL2JNIView.java
new file mode 100644
index 0000000..2dae090
--- /dev/null
+++ b/opengl/tests/gl2_jni/src/com/android/gl2jni/GL2JNIView.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+package com.android.gl2jni;
+/*
+ * 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.
+ */
+
+
+import android.content.Context;
+import android.opengl.GLSurfaceView;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+
+import javax.microedition.khronos.egl.EGL10;
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.egl.EGLContext;
+import javax.microedition.khronos.egl.EGLDisplay;
+import javax.microedition.khronos.opengles.GL10;
+
+/**
+ * An implementation of SurfaceView that uses the dedicated surface for
+ * displaying an OpenGL animation.  This allows the animation to run in a
+ * separate thread, without requiring that it be driven by the update mechanism
+ * of the view hierarchy.
+ *
+ * The application-specific rendering code is delegated to a GLView.Renderer
+ * instance.
+ */
+class GL2JNIView extends GLSurfaceView {
+    private static String TAG = "GL2JNIView";
+    GL2JNIView(Context context) {
+        super(context);
+        init();
+    }
+
+    public GL2JNIView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init();
+    }
+
+    private void init() {
+        setEGLContextFactory(new ContextFactory());
+        setEGLConfigChooser(new ConfigChooser());
+        setRenderer(new Renderer());
+    }
+
+    private static class ContextFactory implements GLSurfaceView.EGLContextFactory {
+        private static int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
+        public EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig eglConfig) {
+            Log.w(TAG, "creating OpenGL ES 2.0 context");
+            checkEglError("Before eglCreateContext", egl);
+            int[] attrib_list = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE };
+            EGLContext context = egl.eglCreateContext(display, eglConfig, EGL10.EGL_NO_CONTEXT, attrib_list);
+            checkEglError("After eglCreateContext", egl);
+            return context;
+        }
+
+        public void destroyContext(EGL10 egl, EGLDisplay display, EGLContext context) {
+            egl.eglDestroyContext(display, context);
+        }
+    }
+
+    private static void checkEglError(String prompt, EGL10 egl) {
+        int error;
+        while ((error = egl.eglGetError()) != EGL10.EGL_SUCCESS) {
+            Log.e(TAG, String.format("%s: EGL error: 0x%x", prompt, error));
+        }
+    }
+
+    private static class ConfigChooser implements GLSurfaceView.EGLConfigChooser {
+        private static int EGL_OPENGL_ES2_BIT = 4;
+        private static int[] s_configAttribs2 =
+        {
+            EGL10.EGL_RED_SIZE, 4,
+            EGL10.EGL_GREEN_SIZE, 4,
+            EGL10.EGL_BLUE_SIZE, 4,
+            EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+            EGL10.EGL_NONE
+        };
+        public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
+
+            int[] num_config = new int[1];
+            egl.eglChooseConfig(display, s_configAttribs2, null, 0, num_config);
+
+            int numConfigs = num_config[0];
+
+            Log.w(TAG, String.format("Found %d configurations", numConfigs));
+            if (numConfigs <= 0) {
+                throw new IllegalArgumentException("No configs match configSpec");
+            }
+            EGLConfig[] configs = new EGLConfig[numConfigs];
+            egl.eglChooseConfig(display, s_configAttribs2, configs, numConfigs, num_config);
+            return configs[0];
+        }
+    }
+
+    private static class Renderer implements GLSurfaceView.Renderer {
+        public void onDrawFrame(GL10 gl) {
+            GL2JNILib.step();
+        }
+
+        public void onSurfaceChanged(GL10 gl, int width, int height) {
+            GL2JNILib.init(width, height);
+        }
+
+        public void onSurfaceCreated(GL10 gl, EGLConfig config) {
+            // Do nothing.
+        }
+    }
+}
+
diff --git a/opengl/tests/gl_basic/Android.mk b/opengl/tests/gl_basic/Android.mk
new file mode 100644
index 0000000..6b6341f
--- /dev/null
+++ b/opengl/tests/gl_basic/Android.mk
@@ -0,0 +1,17 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+	gl_basic.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+	libcutils \
+    libEGL \
+    libGLESv1_CM \
+    libui
+
+LOCAL_MODULE:= test-opengl-gl_basic
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_EXECUTABLE)
diff --git a/opengl/tests/gl_basic/gl_basic.cpp b/opengl/tests/gl_basic/gl_basic.cpp
new file mode 100644
index 0000000..7dc2378
--- /dev/null
+++ b/opengl/tests/gl_basic/gl_basic.cpp
@@ -0,0 +1,357 @@
+// Simple OpenGL ES 1.x application showing how to initialize and draw something.
+
+#include <EGL/egl.h>

+#include <GLES/gl.h>
+#include <GLES/glext.h>
+
+#include <ui/FramebufferNativeWindow.h>
+#include <ui/EGLUtils.h>
+
+#include <stdio.h>

+#include <stdlib.h>
+#include <math.h>
+
+using namespace android;
+

+EGLDisplay eglDisplay;

+EGLSurface eglSurface;

+EGLContext eglContext;

+GLuint texture;

+

+#define FIXED_ONE 0x10000
+#define ITERATIONS 50

+

+int init_gl_surface(void);

+void free_gl_surface(void);

+void init_scene(void);

+void render();

+void create_texture(void);
+int readTimer(void);

+
+static void gluLookAt(float eyeX, float eyeY, float eyeZ,
+        float centerX, float centerY, float centerZ, float upX, float upY,
+        float upZ)
+{
+    // See the OpenGL GLUT documentation for gluLookAt for a description
+    // of the algorithm. We implement it in a straightforward way:
+
+    float fx = centerX - eyeX;
+    float fy = centerY - eyeY;
+    float fz = centerZ - eyeZ;
+
+    // Normalize f
+    float rlf = 1.0f / sqrtf(fx*fx + fy*fy + fz*fz);
+    fx *= rlf;
+    fy *= rlf;
+    fz *= rlf;
+
+    // Normalize up
+    float rlup = 1.0f / sqrtf(upX*upX + upY*upY + upZ*upZ);
+    upX *= rlup;
+    upY *= rlup;
+    upZ *= rlup;
+
+    // compute s = f x up (x means "cross product")
+
+    float sx = fy * upZ - fz * upY;
+    float sy = fz * upX - fx * upZ;
+    float sz = fx * upY - fy * upX;
+
+    // compute u = s x f
+    float ux = sy * fz - sz * fy;
+    float uy = sz * fx - sx * fz;
+    float uz = sx * fy - sy * fx;
+
+    float m[16] ;
+    m[0] = sx;
+    m[1] = ux;
+    m[2] = -fx;
+    m[3] = 0.0f;
+
+    m[4] = sy;
+    m[5] = uy;
+    m[6] = -fy;
+    m[7] = 0.0f;
+
+    m[8] = sz;
+    m[9] = uz;
+    m[10] = -fz;
+    m[11] = 0.0f;
+
+    m[12] = 0.0f;
+    m[13] = 0.0f;
+    m[14] = 0.0f;
+    m[15] = 1.0f;
+
+    glMultMatrixf(m);
+    glTranslatef(-eyeX, -eyeY, -eyeZ);
+}
+
+
+void printEGLConfiguration(EGLDisplay dpy, EGLConfig config) {
+
+#define X(VAL) {VAL, #VAL}
+    struct {EGLint attribute; const char* name;} names[] = {
+    X(EGL_BUFFER_SIZE),
+    X(EGL_ALPHA_SIZE),
+    X(EGL_BLUE_SIZE),
+    X(EGL_GREEN_SIZE),
+    X(EGL_RED_SIZE),
+    X(EGL_DEPTH_SIZE),
+    X(EGL_STENCIL_SIZE),
+    X(EGL_CONFIG_CAVEAT),
+    X(EGL_CONFIG_ID),
+    X(EGL_LEVEL),
+    X(EGL_MAX_PBUFFER_HEIGHT),
+    X(EGL_MAX_PBUFFER_PIXELS),
+    X(EGL_MAX_PBUFFER_WIDTH),
+    X(EGL_NATIVE_RENDERABLE),
+    X(EGL_NATIVE_VISUAL_ID),
+    X(EGL_NATIVE_VISUAL_TYPE),
+    X(EGL_PRESERVED_RESOURCES),
+    X(EGL_SAMPLES),
+    X(EGL_SAMPLE_BUFFERS),
+    X(EGL_SURFACE_TYPE),
+    X(EGL_TRANSPARENT_TYPE),
+    X(EGL_TRANSPARENT_RED_VALUE),
+    X(EGL_TRANSPARENT_GREEN_VALUE),
+    X(EGL_TRANSPARENT_BLUE_VALUE),
+    X(EGL_BIND_TO_TEXTURE_RGB),
+    X(EGL_BIND_TO_TEXTURE_RGBA),
+    X(EGL_MIN_SWAP_INTERVAL),
+    X(EGL_MAX_SWAP_INTERVAL),
+    X(EGL_LUMINANCE_SIZE),
+    X(EGL_ALPHA_MASK_SIZE),
+    X(EGL_COLOR_BUFFER_TYPE),
+    X(EGL_RENDERABLE_TYPE),
+    X(EGL_CONFORMANT),
+   };
+#undef X
+
+    for (size_t j = 0; j < sizeof(names) / sizeof(names[0]); j++) {
+        EGLint value = -1;
+        EGLint returnVal = eglGetConfigAttrib(dpy, config, names[j].attribute, &value);
+        EGLint error = eglGetError();
+        if (returnVal && error == EGL_SUCCESS) {
+            printf(" %s: ", names[j].name);
+            printf("%d (0x%x)", value, value);
+        }
+    }
+    printf("\n");
+}
+
+static void checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE) {
+    if (returnVal != EGL_TRUE) {
+        fprintf(stderr, "%s() returned %d\n", op, returnVal);
+    }
+
+    for (EGLint error = eglGetError(); error != EGL_SUCCESS; error
+            = eglGetError()) {
+        fprintf(stderr, "after %s() eglError %s (0x%x)\n", op, EGLUtils::strerror(error),
+                error);
+    }
+}
+
+int printEGLConfigurations(EGLDisplay dpy) {
+    EGLint numConfig = 0;
+    EGLint returnVal = eglGetConfigs(dpy, NULL, 0, &numConfig);
+    checkEglError("eglGetConfigs", returnVal);
+    if (!returnVal) {
+        return false;
+    }
+
+    printf("Number of EGL configurations: %d\n", numConfig);
+
+    EGLConfig* configs = (EGLConfig*) malloc(sizeof(EGLConfig) * numConfig);
+    if (! configs) {
+        printf("Could not allocate configs.\n");
+        return false;
+    }
+
+    returnVal = eglGetConfigs(dpy, configs, numConfig, &numConfig);
+    checkEglError("eglGetConfigs", returnVal);
+    if (!returnVal) {
+        free(configs);
+        return false;
+    }
+
+    for(int i = 0; i < numConfig; i++) {
+        printf("Configuration %d\n", i);
+        printEGLConfiguration(dpy, configs[i]);
+    }
+
+    free(configs);
+    return true;
+}
+

+int main(int argc, char **argv)

+{

+    int q;
+    int start, end;

+
+    printf("Initializing EGL...\n");
+

+    if(!init_gl_surface())

+    {

+        printf("GL initialisation failed - exiting\n");

+        return 0;

+    }

+

+    init_scene();

+

+    create_texture();

+

+    printf("Running...\n");
+
+    while(true) {
+        render();
+    }

+

+    free_gl_surface();

+

+    return 0;

+}

+

+int init_gl_surface(void)

+{

+    EGLint numConfigs = 1;

+    EGLConfig myConfig = {0};

+    EGLint attrib[] =

+    {

+            EGL_SURFACE_TYPE, EGL_WINDOW_BIT,

+            EGL_NONE

+    };

+

+    if ( (eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY)) == EGL_NO_DISPLAY )

+    {

+        printf("eglGetDisplay failed\n");

+        return 0;

+    }
+

+    if ( eglInitialize(eglDisplay, NULL, NULL) != EGL_TRUE )

+    {

+        printf("eglInitialize failed\n");

+        return 0;

+    }
+
+    if (! printEGLConfigurations(eglDisplay)) {
+        printf("printEGLConfigurations failed.\n");
+        return 0;
+    }

+    EGLNativeWindowType window = android_createDisplaySurface();

+    EGLUtils::selectConfigForNativeWindow(eglDisplay, attrib, window, &myConfig);

+

+    if ( (eglSurface = eglCreateWindowSurface(eglDisplay, myConfig,
+            window, 0)) == EGL_NO_SURFACE )

+    {

+        printf("eglCreateWindowSurface failed\n");

+        return 0;

+    }

+

+    if ( (eglContext = eglCreateContext(eglDisplay, myConfig, 0, 0)) == EGL_NO_CONTEXT )

+    {

+        printf("eglCreateContext failed\n");

+        return 0;

+    }

+

+    if ( eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext) != EGL_TRUE )

+    {

+        printf("eglMakeCurrent failed\n");

+        return 0;

+    }

+

+    return 1;

+}

+

+void free_gl_surface(void)

+{

+    if (eglDisplay != EGL_NO_DISPLAY)

+    {

+        eglMakeCurrent( EGL_NO_DISPLAY, EGL_NO_SURFACE,

+                EGL_NO_SURFACE, EGL_NO_CONTEXT );

+        eglDestroyContext( eglDisplay, eglContext );

+        eglDestroySurface( eglDisplay, eglSurface );

+        eglTerminate( eglDisplay );

+        eglDisplay = EGL_NO_DISPLAY;

+    }

+}

+

+void init_scene(void)

+{

+    glDisable(GL_DITHER);
+    glEnable(GL_CULL_FACE);
+
+    float ratio = 320.0f / 480.0f;
+    glViewport(0, 0, 320, 480);
+
+    glMatrixMode(GL_PROJECTION);
+    glLoadIdentity();
+    glFrustumf(-ratio, ratio, -1, 1, 1, 10);
+
+    glMatrixMode(GL_MODELVIEW);

+    glLoadIdentity();
+    gluLookAt(
+            0, 0, 3,  // eye
+            0, 0, 0,  // center
+            0, 1, 0); // up
+

+    glEnable(GL_TEXTURE_2D);

+    glEnableClientState(GL_VERTEX_ARRAY);

+    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+}

+

+void create_texture(void)

+{

+    const unsigned int on = 0xff0000ff;
+    const unsigned int off = 0xffffffff;
+    const unsigned int pixels[] =
+    {
+            on, off, on, off, on, off, on, off,
+            off, on, off, on, off, on, off, on,
+            on, off, on, off, on, off, on, off,
+            off, on, off, on, off, on, off, on,
+            on, off, on, off, on, off, on, off,
+            off, on, off, on, off, on, off, on,
+            on, off, on, off, on, off, on, off,
+            off, on, off, on, off, on, off, on,
+    };

+    glGenTextures(1, &texture);

+    glBindTexture(GL_TEXTURE_2D, texture);

+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);

+    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

+    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

+    glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

+}

+

+void render()

+{

+    int i, j;
+    int quads = 1;

+

+    const GLfloat vertices[] = {

+            -1,  -1,  0,

+             1,  -1,  0,

+             1,   1,  0,

+            -1,   1,  0

+    };

+

+    const GLfixed texCoords[] = {

+            0,            0,

+            FIXED_ONE,    0,

+            FIXED_ONE,    FIXED_ONE,

+            0,            FIXED_ONE

+    };

+

+    const GLushort indices[] = { 0, 1, 2,  0, 2, 3 };
+

+    glVertexPointer(3, GL_FLOAT, 0, vertices);

+    glTexCoordPointer(2, GL_FIXED, 0, texCoords);
+
+    glClearColor(1.0, 1.0, 1.0, 1.0);
+
+    int nelem = sizeof(indices)/sizeof(indices[0]);
+    glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
+    glDrawElements(GL_TRIANGLES, nelem, GL_UNSIGNED_SHORT, indices);
+    eglSwapBuffers(eglDisplay, eglSurface);

+}

+
diff --git a/opengl/tests/gl_jni/Android.mk b/opengl/tests/gl_jni/Android.mk
new file mode 100644
index 0000000..4029fa1
--- /dev/null
+++ b/opengl/tests/gl_jni/Android.mk
@@ -0,0 +1,53 @@
+#########################################################################
+# OpenGL ES JNI sample
+# This makefile builds both an activity and a shared library.
+#########################################################################
+ifneq ($(TARGET_SIMULATOR),true) # not 64 bit clean
+
+TOP_LOCAL_PATH:= $(call my-dir)
+
+# Build activity
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := user
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := GLJNI
+
+LOCAL_JNI_SHARED_LIBRARIES := libgljni
+
+include $(BUILD_PACKAGE)
+
+#########################################################################
+# Build JNI Shared Library
+#########################################################################
+
+LOCAL_PATH:= $(LOCAL_PATH)/jni
+
+include $(CLEAR_VARS)
+
+# Optional tag would mean it doesn't get installed by default
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_CFLAGS := -Werror
+
+LOCAL_SRC_FILES:= \
+  gl_code.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+	libutils \
+	libEGL \
+	libGLESv1_CM
+
+LOCAL_MODULE := libgljni
+
+LOCAL_ARM_MODE := arm
+
+LOCAL_PRELINK_MODULE := false
+
+include $(BUILD_SHARED_LIBRARY)
+
+endif # TARGET_SIMULATOR
diff --git a/opengl/tests/gl_jni/AndroidManifest.xml b/opengl/tests/gl_jni/AndroidManifest.xml
new file mode 100644
index 0000000..64bd6bf
--- /dev/null
+++ b/opengl/tests/gl_jni/AndroidManifest.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2009, 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.
+*/
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.gljni">
+    <uses-permission android:name="android.permission.INTERNET" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    <application
+            android:label="@string/gljni_activity">
+        <activity android:name="GLJNIActivity"
+                android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
+            	android:launchMode="singleTask"
+            	android:screenOrientation="landscape"
+            	android:configChanges="orientation|keyboardHidden">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/opengl/tests/gl_jni/jni/gl_code.cpp b/opengl/tests/gl_jni/jni/gl_code.cpp
new file mode 100644
index 0000000..33b25ab
--- /dev/null
+++ b/opengl/tests/gl_jni/jni/gl_code.cpp
@@ -0,0 +1,183 @@
+// OpenGL ES 1.0 code
+
+#include <nativehelper/jni.h>
+#define LOG_TAG "GLJNI gl_code.cpp"
+#include <utils/Log.h>
+
+#include <GLES/gl.h>
+
+#include <stdio.h>
+
+#include <stdlib.h>
+#include <math.h>
+
+GLuint texture;
+GLfloat background;
+
+#define FIXED_ONE 0x10000
+
+static void printGLString(const char *name, GLenum s) {
+    const char *v = (const char *) glGetString(s);
+    LOGI("GL %s = %s\n", name, v);
+}
+
+static void gluLookAt(float eyeX, float eyeY, float eyeZ,
+        float centerX, float centerY, float centerZ, float upX, float upY,
+        float upZ)
+{
+    // See the OpenGL GLUT documentation for gluLookAt for a description
+    // of the algorithm. We implement it in a straightforward way:
+
+    float fx = centerX - eyeX;
+    float fy = centerY - eyeY;
+    float fz = centerZ - eyeZ;
+
+    // Normalize f
+    float rlf = 1.0f / sqrtf(fx*fx + fy*fy + fz*fz);
+    fx *= rlf;
+    fy *= rlf;
+    fz *= rlf;
+
+    // Normalize up
+    float rlup = 1.0f / sqrtf(upX*upX + upY*upY + upZ*upZ);
+    upX *= rlup;
+    upY *= rlup;
+    upZ *= rlup;
+
+    // compute s = f x up (x means "cross product")
+
+    float sx = fy * upZ - fz * upY;
+    float sy = fz * upX - fx * upZ;
+    float sz = fx * upY - fy * upX;
+
+    // compute u = s x f
+    float ux = sy * fz - sz * fy;
+    float uy = sz * fx - sx * fz;
+    float uz = sx * fy - sy * fx;
+
+    float m[16] ;
+    m[0] = sx;
+    m[1] = ux;
+    m[2] = -fx;
+    m[3] = 0.0f;
+
+    m[4] = sy;
+    m[5] = uy;
+    m[6] = -fy;
+    m[7] = 0.0f;
+
+    m[8] = sz;
+    m[9] = uz;
+    m[10] = -fz;
+    m[11] = 0.0f;
+
+    m[12] = 0.0f;
+    m[13] = 0.0f;
+    m[14] = 0.0f;
+    m[15] = 1.0f;
+
+    glMultMatrixf(m);
+    glTranslatef(-eyeX, -eyeY, -eyeZ);
+}
+
+void init_scene(int width, int height)
+{
+    printGLString("Version", GL_VERSION);
+    printGLString("Vendor", GL_VENDOR);
+    printGLString("Renderer", GL_RENDERER);
+    printGLString("Extensions", GL_EXTENSIONS);
+
+    glDisable(GL_DITHER);
+    glEnable(GL_CULL_FACE);
+
+    float ratio = width / height;
+    glViewport(0, 0, width, height);
+
+    glMatrixMode(GL_PROJECTION);
+    glLoadIdentity();
+    glFrustumf(-ratio, ratio, -1, 1, 1, 10);
+
+    glMatrixMode(GL_MODELVIEW);
+
+    glLoadIdentity();
+    gluLookAt(
+            0, 0, 3,  // eye
+            0, 0, 0,  // center
+            0, 1, 0); // up
+
+    glEnable(GL_TEXTURE_2D);
+    glEnableClientState(GL_VERTEX_ARRAY);
+    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+}
+
+void create_texture()
+{
+    const unsigned int on = 0xff0000ff;
+    const unsigned int off = 0xffffffff;
+    const unsigned int pixels[] =
+    {
+            on, off, on, off, on, off, on, off,
+            off, on, off, on, off, on, off, on,
+            on, off, on, off, on, off, on, off,
+            off, on, off, on, off, on, off, on,
+            on, off, on, off, on, off, on, off,
+            off, on, off, on, off, on, off, on,
+            on, off, on, off, on, off, on, off,
+            off, on, off, on, off, on, off, on,
+    };
+
+    glGenTextures(1, &texture);
+    glBindTexture(GL_TEXTURE_2D, texture);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+}
+
+extern "C" {
+    JNIEXPORT void JNICALL Java_com_android_gljni_GLJNILib_init(JNIEnv * env, jobject obj,  jint width, jint height);
+    JNIEXPORT void JNICALL Java_com_android_gljni_GLJNILib_step(JNIEnv * env, jobject obj);
+    JNIEXPORT void JNICALL Java_com_android_gljni_GLJNILib_changeBackground(JNIEnv * env, jobject obj);
+};
+
+JNIEXPORT void JNICALL Java_com_android_gljni_GLJNILib_init(JNIEnv * env, jobject obj,  jint width, jint height)
+{
+    init_scene(width, height);
+    create_texture();
+}
+
+JNIEXPORT void JNICALL Java_com_android_gljni_GLJNILib_step(JNIEnv * env, jobject obj)
+{
+    const GLfloat vertices[] = {
+            -1,  -1,  0,
+             1,  -1,  0,
+             1,   1,  0,
+            -1,   1,  0
+    };
+
+    const GLfixed texCoords[] = {
+            0,            0,
+            FIXED_ONE,    0,
+            FIXED_ONE,    FIXED_ONE,
+            0,            FIXED_ONE
+    };
+
+    const GLushort quadIndices[] = { 0, 1, 2,  0, 2, 3 };
+    glVertexPointer(3, GL_FLOAT, 0, vertices);
+    glTexCoordPointer(2, GL_FIXED, 0, texCoords);
+
+    int nelem = sizeof(quadIndices)/sizeof(quadIndices[0]);
+    static float grey;
+    grey += 0.01f;
+    if (grey > 1.0f) {
+        grey = 0.0f;
+    }
+    glClearColor(background, grey, grey, 1.0f);
+    glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
+    glDrawElements(GL_TRIANGLES, nelem, GL_UNSIGNED_SHORT, quadIndices);
+}
+
+JNIEXPORT void JNICALL Java_com_android_gljni_GLJNILib_changeBackground(JNIEnv * env, jobject obj)
+{
+    background = 1.0f - background;
+}
\ No newline at end of file
diff --git a/opengl/tests/gl_jni/res/values/strings.xml b/opengl/tests/gl_jni/res/values/strings.xml
new file mode 100644
index 0000000..880f5c9
--- /dev/null
+++ b/opengl/tests/gl_jni/res/values/strings.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2006, 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.
+*/
+-->
+
+<!-- This file contains resource definitions for displayed strings, allowing
+     them to be changed based on the locale and options. -->
+
+<resources>
+    <!-- Simple strings. -->
+    <string name="gljni_activity">GLJNI</string>
+
+</resources>
+
diff --git a/opengl/tests/gl_jni/src/com/android/gljni/GLJNIActivity.java b/opengl/tests/gl_jni/src/com/android/gljni/GLJNIActivity.java
new file mode 100644
index 0000000..c6f5313
--- /dev/null
+++ b/opengl/tests/gl_jni/src/com/android/gljni/GLJNIActivity.java
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+package com.android.gljni;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class GLJNIActivity extends Activity {
+
+    GLJNIView mView;
+
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        mView = new GLJNIView(getApplication());
+	    mView.setFocusableInTouchMode(true);
+	    setContentView(mView);
+    }
+
+    @Override
+    protected void onPause() {
+        super.onPause();
+        mView.onPause();
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        mView.onResume();
+    }
+}
diff --git a/opengl/tests/gl_jni/src/com/android/gljni/GLJNILib.java b/opengl/tests/gl_jni/src/com/android/gljni/GLJNILib.java
new file mode 100644
index 0000000..f56d2af
--- /dev/null
+++ b/opengl/tests/gl_jni/src/com/android/gljni/GLJNILib.java
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+package com.android.gljni;
+
+// Wrapper for native library
+
+public class GLJNILib {
+
+     static {
+         System.loadLibrary("gljni");
+     }
+
+    /**
+     * @param width the current view width
+     * @param height the current view height
+     */
+     public static native void init(int width, int height);
+     public static native void step();
+     public static native void changeBackground();
+}
diff --git a/opengl/tests/gl_jni/src/com/android/gljni/GLJNIView.java b/opengl/tests/gl_jni/src/com/android/gljni/GLJNIView.java
new file mode 100644
index 0000000..9a2c8c4
--- /dev/null
+++ b/opengl/tests/gl_jni/src/com/android/gljni/GLJNIView.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+package com.android.gljni;
+/*
+ * 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.
+ */
+
+
+import android.content.Context;
+import android.opengl.GLSurfaceView;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+
+import javax.microedition.khronos.egl.EGL10;
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+/**
+ * An implementation of SurfaceView that uses the dedicated surface for
+ * displaying an OpenGL animation.  This allows the animation to run in a
+ * separate thread, without requiring that it be driven by the update mechanism
+ * of the view hierarchy.
+ *
+ * The application-specific rendering code is delegated to a GLView.Renderer
+ * instance.
+ */
+class GLJNIView extends GLSurfaceView {
+    GLJNIView(Context context) {
+        super(context);
+        init();
+    }
+
+    public GLJNIView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init();
+    }
+
+    private void init() {
+        setRenderer(new Renderer());
+    }
+
+    private class Renderer implements GLSurfaceView.Renderer {
+        private static final String TAG = "Renderer";
+        public void onDrawFrame(GL10 gl) {
+            GLJNILib.step();
+        }
+
+        public void onSurfaceChanged(GL10 gl, int width, int height) {
+            GLJNILib.init(width, height);
+        }
+
+        public void onSurfaceCreated(GL10 gl, EGLConfig config) {
+            // Do nothing.
+        }
+    }
+    
+    @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        GLJNILib.changeBackground();
+        return true;
+    }
+}
+
diff --git a/opengl/tests/gralloc/Android.mk b/opengl/tests/gralloc/Android.mk
new file mode 100644
index 0000000..d43c39a
--- /dev/null
+++ b/opengl/tests/gralloc/Android.mk
@@ -0,0 +1,16 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+    gralloc.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+    libcutils \
+    libutils \
+    libui
+
+LOCAL_MODULE:= test-opengl-gralloc
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_EXECUTABLE)
diff --git a/opengl/tests/gralloc/gralloc.cpp b/opengl/tests/gralloc/gralloc.cpp
new file mode 100644
index 0000000..8987040
--- /dev/null
+++ b/opengl/tests/gralloc/gralloc.cpp
@@ -0,0 +1,110 @@
+/*
+ **
+ ** Copyright 2009, 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 "StopWatch"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <utils/StopWatch.h>
+#include <utils/Log.h>
+
+#include <ui/GraphicBuffer.h>
+#include <ui/GraphicBufferMapper.h>
+
+using namespace android;
+
+void* lamecpy(void* d, void const* s, size_t size) {
+    char* dst = (char*)d;
+    char const* src = (char const*)s;
+    while (size) {
+        *dst++ = *src++;
+        size--;
+    }
+    return d;
+}
+
+int main(int argc, char** argv)
+{
+    size_t size = 128*256*4;
+    void* temp = malloc(size);
+    void* temp2 = malloc(size);
+    memset(temp, 0, size);
+    memset(temp2, 0, size);
+
+
+    sp<GraphicBuffer> buffer = new GraphicBuffer(128, 256, HAL_PIXEL_FORMAT_RGBA_8888,
+            GRALLOC_USAGE_SW_READ_OFTEN |
+            GRALLOC_USAGE_SW_WRITE_OFTEN);
+
+    status_t err = buffer->initCheck();
+    if (err != NO_ERROR) {
+        printf("%s\n", strerror(-err));
+        return 0;
+    }
+
+    void* vaddr;
+    buffer->lock(
+            GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
+            &vaddr);
+
+    {
+        StopWatch watch("memset");
+        for (int i=0 ; i<10 ; i++)
+            memset(vaddr, 0, size);
+    }
+
+    {
+        StopWatch watch("memcpy baseline");
+        for (int i=0 ; i<10 ; i++)
+            memcpy(temp, temp2, size);
+    }
+
+    {
+        StopWatch watch("memcpy from gralloc");
+        for (int i=0 ; i<10 ; i++)
+            memcpy(temp, vaddr, size);
+    }
+
+    {
+        StopWatch watch("memcpy into gralloc");
+        for (int i=0 ; i<10 ; i++)
+            memcpy(vaddr, temp, size);
+    }
+
+
+    {
+        StopWatch watch("lamecpy baseline");
+        for (int i=0 ; i<10 ; i++)
+            lamecpy(temp, temp2, size);
+    }
+
+    {
+        StopWatch watch("lamecpy from gralloc");
+        for (int i=0 ; i<10 ; i++)
+            lamecpy(temp, vaddr, size);
+    }
+
+    {
+        StopWatch watch("lamecpy into gralloc");
+        for (int i=0 ; i<10 ; i++)
+            lamecpy(vaddr, temp, size);
+    }
+
+    buffer->unlock();
+
+    return 0;
+}
diff --git a/opengl/tests/linetex/Android.mk b/opengl/tests/linetex/Android.mk
new file mode 100644
index 0000000..6ff248d
--- /dev/null
+++ b/opengl/tests/linetex/Android.mk
@@ -0,0 +1,17 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+	linetex.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+	libcutils \
+    libEGL \
+    libGLESv1_CM \
+    libui
+
+LOCAL_MODULE:= test-opengl-linetex
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_EXECUTABLE)
diff --git a/opengl/tests/linetex/linetex.cpp b/opengl/tests/linetex/linetex.cpp
new file mode 100644
index 0000000..6842940
--- /dev/null
+++ b/opengl/tests/linetex/linetex.cpp
@@ -0,0 +1,116 @@
+/*
+**
+** Copyright 2006, 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 "fillrate"
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <EGL/egl.h>
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+
+#include <utils/StopWatch.h>
+#include <ui/FramebufferNativeWindow.h>
+#include <ui/EGLUtils.h>
+
+using namespace android;
+
+int main(int argc, char** argv)
+{
+    EGLint configAttribs[] = {
+         EGL_DEPTH_SIZE, 0,
+         EGL_NONE
+     };
+     
+     EGLint majorVersion;
+     EGLint minorVersion;
+     EGLContext context;
+     EGLConfig config;
+     EGLSurface surface;
+     EGLint w, h;
+     EGLDisplay dpy;
+
+     EGLNativeWindowType window = android_createDisplaySurface();
+     
+     dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+     eglInitialize(dpy, &majorVersion, &minorVersion);
+          
+     status_t err = EGLUtils::selectConfigForNativeWindow(
+             dpy, configAttribs, window, &config);
+     if (err) {
+         fprintf(stderr, "couldn't find an EGLConfig matching the screen format\n");
+         return 0;
+     }
+
+     surface = eglCreateWindowSurface(dpy, config, window, NULL);
+     context = eglCreateContext(dpy, config, NULL, NULL);
+     eglMakeCurrent(dpy, surface, surface, context);   
+     eglQuerySurface(dpy, surface, EGL_WIDTH, &w);
+     eglQuerySurface(dpy, surface, EGL_HEIGHT, &h);
+     
+     printf("w=%d, h=%d\n", w, h);
+     
+     glBindTexture(GL_TEXTURE_2D, 0);
+     glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+     glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+     glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+     glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+     glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+     glDisable(GL_DITHER);
+     glDisable(GL_BLEND);
+     glEnable(GL_TEXTURE_2D);
+     glColor4f(1,1,1,1);
+
+
+     // default pack-alignment is 4
+     const uint16_t t16[64] = { 0xFFFF, 0, 0xF800, 0, 0x07E0, 0, 0x001F, 0 };
+
+     const GLfloat vertices[4][2] = {
+             { w/2,  0 },
+             { w/2,  h }
+     };
+
+     const GLfloat texCoords[4][2] = {
+             { 0,  0 },
+             { 1,  1 }
+     };
+
+     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 4, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, t16);
+
+     glViewport(0, 0, w, h);
+     glMatrixMode(GL_PROJECTION);
+     glLoadIdentity();
+     glOrthof(0, w, 0, h, 0, 1);
+
+     glEnableClientState(GL_VERTEX_ARRAY);
+     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+     glVertexPointer(2, GL_FLOAT, 0, vertices);
+     glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
+
+     glClearColor(0,0,0,0);
+     glClear(GL_COLOR_BUFFER_BIT);
+     glDrawArrays(GL_LINES, 0, 2);
+     eglSwapBuffers(dpy, surface);
+
+     usleep(5*1000000);
+
+     eglTerminate(dpy);
+     
+     return 0;
+}
diff --git a/opengl/tests/swapinterval/Android.mk b/opengl/tests/swapinterval/Android.mk
new file mode 100644
index 0000000..619447c
--- /dev/null
+++ b/opengl/tests/swapinterval/Android.mk
@@ -0,0 +1,17 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+	swapinterval.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+	libcutils \
+    libEGL \
+    libGLESv1_CM \
+    libui
+
+LOCAL_MODULE:= test-opengl-swapinterval
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_EXECUTABLE)
diff --git a/opengl/tests/swapinterval/swapinterval.cpp b/opengl/tests/swapinterval/swapinterval.cpp
new file mode 100644
index 0000000..df53b62
--- /dev/null
+++ b/opengl/tests/swapinterval/swapinterval.cpp
@@ -0,0 +1,121 @@
+/*
+ **
+ ** Copyright 2006, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License"); 
+ ** you may not use this file except in compliance with the License. 
+ ** You may obtain a copy of the License at 
+ **
+ **     http://www.apache.org/licenses/LICENSE-2.0 
+ **
+ ** Unless required by applicable law or agreed to in writing, software 
+ ** distributed under the License is distributed on an "AS IS" BASIS, 
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ ** See the License for the specific language governing permissions and 
+ ** limitations under the License.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <EGL/egl.h>
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+
+#include <utils/StopWatch.h>
+#include <ui/FramebufferNativeWindow.h>
+#include <ui/EGLUtils.h>
+
+using namespace android;
+
+int main(int argc, char** argv)
+{
+    EGLint configAttribs[] = {
+            EGL_SURFACE_TYPE,   EGL_WINDOW_BIT,
+            EGL_NONE
+    };
+
+    EGLint majorVersion;
+    EGLint minorVersion;
+    EGLContext context;
+    EGLConfig config;
+    EGLint numConfigs=0;
+    EGLSurface surface;
+    EGLint w, h;
+    EGLDisplay dpy;
+
+    
+    EGLNativeWindowType window = android_createDisplaySurface();
+
+    dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+    eglInitialize(dpy, 0 ,0) ;//&majorVersion, &minorVersion);
+    eglGetConfigs(dpy, NULL, 0, &numConfigs);
+    printf("# configs = %d\n", numConfigs);
+
+    status_t err = EGLUtils::selectConfigForNativeWindow(
+            dpy, configAttribs, window, &config);
+    if (err) {
+        fprintf(stderr, "couldn't find an EGLConfig matching the screen format\n");
+        return 0;
+    }
+
+    EGLint r,g,b,a;
+    eglGetConfigAttrib(dpy, config, EGL_RED_SIZE,   &r);
+    eglGetConfigAttrib(dpy, config, EGL_GREEN_SIZE, &g);
+    eglGetConfigAttrib(dpy, config, EGL_BLUE_SIZE,  &b);
+    eglGetConfigAttrib(dpy, config, EGL_ALPHA_SIZE, &a);
+
+    surface = eglCreateWindowSurface(dpy, config, window, NULL);
+    if (surface == EGL_NO_SURFACE) {
+        EGLint err = eglGetError();
+        fprintf(stderr, "%s, config=%p, format = %d-%d-%d-%d\n",
+                EGLUtils::strerror(err), config, r,g,b,a);
+        return 0;
+    } else {
+        printf("config=%p, format = %d-%d-%d-%d\n", config, r,g,b,a);
+    }
+
+    context = eglCreateContext(dpy, config, NULL, NULL);
+    eglMakeCurrent(dpy, surface, surface, context);   
+    eglQuerySurface(dpy, surface, EGL_WIDTH, &w);
+    eglQuerySurface(dpy, surface, EGL_HEIGHT, &h);
+
+    printf("w=%d, h=%d\n", w, h);
+
+    glDisable(GL_DITHER);
+    glEnable(GL_BLEND);
+
+    glViewport(0, 0, w, h);
+    glOrthof(0, w, 0, h, 0, 1);
+
+    eglSwapInterval(dpy, 1);
+
+    glClearColor(1,0,0,0);
+    glClear(GL_COLOR_BUFFER_BIT);
+    eglSwapBuffers(dpy, surface);
+
+
+    int time = 10;
+    printf("screen should flash red/green quickly for %d s...\n", time);
+
+    int c = 0;
+    nsecs_t start = systemTime();
+    nsecs_t t;
+    do {
+        glClearColor(1,0,0,0);
+        glClear(GL_COLOR_BUFFER_BIT);
+        eglSwapBuffers(dpy, surface);
+        glClearColor(0,1,0,0);
+        glClear(GL_COLOR_BUFFER_BIT);
+        eglSwapBuffers(dpy, surface);
+        t = systemTime() - start;
+        c += 2;
+    } while (int(ns2s(t))<=time);
+
+    double p =  (double(t) / c) / 1000000000.0;
+    printf("refresh-rate is %f fps (%f ms)\n", 1.0f/p, p*1000.0);
+
+    eglTerminate(dpy);
+
+    return 0;
+}
diff --git a/opengl/tests/textures/Android.mk b/opengl/tests/textures/Android.mk
index 8d5f56d..b2fa185 100644
--- a/opengl/tests/textures/Android.mk
+++ b/opengl/tests/textures/Android.mk
@@ -2,7 +2,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:= \
-	textures.c
+	textures.cpp
 
 LOCAL_SHARED_LIBRARIES := \
 	libcutils \
@@ -14,4 +14,6 @@
 
 LOCAL_MODULE_TAGS := optional
 
+LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES
+
 include $(BUILD_EXECUTABLE)
diff --git a/opengl/tests/textures/textures.c b/opengl/tests/textures/textures.cpp
similarity index 86%
rename from opengl/tests/textures/textures.c
rename to opengl/tests/textures/textures.cpp
index 214291b..cbe8ffd 100644
--- a/opengl/tests/textures/textures.c
+++ b/opengl/tests/textures/textures.cpp
@@ -22,30 +22,39 @@
 #include <GLES/gl.h>
 #include <GLES/glext.h>
 
+#include <ui/FramebufferNativeWindow.h>
+#include <ui/EGLUtils.h>
+
+using namespace android;
+
 int main(int argc, char** argv)
 {
-    EGLint s_configAttribs[] = {
-         EGL_RED_SIZE,       5,
-         EGL_GREEN_SIZE,     6,
-         EGL_BLUE_SIZE,      5,
+    EGLint configAttribs[] = {
+         EGL_DEPTH_SIZE, 0,
          EGL_NONE
      };
      
-     EGLint numConfigs = -1;
      EGLint majorVersion;
      EGLint minorVersion;
-     EGLConfig config;
      EGLContext context;
+     EGLConfig config;
      EGLSurface surface;
      EGLint w, h;
-     
      EGLDisplay dpy;
 
+     EGLNativeWindowType window = android_createDisplaySurface();
+     
      dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
      eglInitialize(dpy, &majorVersion, &minorVersion);
-     eglChooseConfig(dpy, s_configAttribs, &config, 1, &numConfigs);
-     surface = eglCreateWindowSurface(dpy, config,
-             android_createDisplaySurface(), NULL);
+          
+     status_t err = EGLUtils::selectConfigForNativeWindow(
+             dpy, configAttribs, window, &config);
+     if (err) {
+         fprintf(stderr, "couldn't find an EGLConfig matching the screen format\n");
+         return 0;
+     }
+
+     surface = eglCreateWindowSurface(dpy, config, window, NULL);
      context = eglCreateContext(dpy, config, NULL, NULL);
      eglMakeCurrent(dpy, surface, surface, context);   
      eglQuerySurface(dpy, surface, EGL_WIDTH, &w);
diff --git a/opengl/tests/tritex/Android.mk b/opengl/tests/tritex/Android.mk
index 76fd8dd..6db3f49 100644
--- a/opengl/tests/tritex/Android.mk
+++ b/opengl/tests/tritex/Android.mk
@@ -2,7 +2,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:= \
-	tritex.c
+	tritex.cpp
 
 LOCAL_SHARED_LIBRARIES := \
 	libcutils \
diff --git a/opengl/tests/tritex/tritex.c b/opengl/tests/tritex/tritex.cpp
similarity index 90%
rename from opengl/tests/tritex/tritex.c
rename to opengl/tests/tritex/tritex.cpp
index 60a7feb..3365ab4 100644
--- a/opengl/tests/tritex/tritex.c
+++ b/opengl/tests/tritex/tritex.cpp
@@ -6,10 +6,16 @@
 
 #include <EGL/egl.h>

 #include <GLES/gl.h>
+#include <GLES/glext.h>
+
+#include <ui/FramebufferNativeWindow.h>
+#include <ui/EGLUtils.h>
 
 #include <stdio.h>

 #include <stdlib.h>
 #include <math.h>
+
+using namespace android;
 

 EGLDisplay eglDisplay;

 EGLSurface eglSurface;

@@ -117,6 +123,7 @@
     EGLConfig myConfig = {0};

     EGLint attrib[] =

     {

+            EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
             EGL_DEPTH_SIZE,     16,

             EGL_NONE

     };

@@ -132,15 +139,12 @@
         printf("eglInitialize failed\n");

         return 0;

     }

-

-    if ( eglChooseConfig(eglDisplay, attrib, &myConfig, 1, &numConfigs) != EGL_TRUE )

-    {

-        printf("eglChooseConfig failed\n");

-        return 0;

-    }

+
+    EGLNativeWindowType window = android_createDisplaySurface();

+    EGLUtils::selectConfigForNativeWindow(eglDisplay, attrib, window, &myConfig);

 

     if ( (eglSurface = eglCreateWindowSurface(eglDisplay, myConfig,
-            android_createDisplaySurface(), 0)) == EGL_NO_SURFACE )

+            window, 0)) == EGL_NO_SURFACE )

     {

         printf("eglCreateWindowSurface failed\n");

         return 0;

@@ -239,12 +243,12 @@
             0,            FIXED_ONE

     };

 

-    const GLushort template[] = { 0, 1, 2,  0, 2, 3 };
+    const GLushort quadIndices[] = { 0, 1, 2,  0, 2, 3 };
 
 
-    GLushort* indices = (GLushort*)malloc(quads*sizeof(template));
+    GLushort* indices = (GLushort*)malloc(quads*sizeof(quadIndices));
     for (i=0 ; i<quads ; i++)
-        memcpy(indices+(sizeof(template)/sizeof(indices[0]))*i, template, sizeof(template));
+        memcpy(indices+(sizeof(quadIndices)/sizeof(indices[0]))*i, quadIndices, sizeof(quadIndices));
 

     glVertexPointer(3, GL_FLOAT, 0, vertices);

     glTexCoordPointer(2, GL_FIXED, 0, texCoords);
@@ -262,7 +266,7 @@
     for (j=0 ; j<10 ; j++) {
         printf("loop %d / 10 (%d quads / loop)\n", j, quads);
 
-        int nelem = sizeof(template)/sizeof(template[0]);
+        int nelem = sizeof(quadIndices)/sizeof(quadIndices[0]);
         glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
         glDrawElements(GL_TRIANGLES, nelem*quads, GL_UNSIGNED_SHORT, indices);
         eglSwapBuffers(eglDisplay, eglSurface);
diff --git a/opengl/tools/glgen/specs/gles11/checks.spec b/opengl/tools/glgen/specs/gles11/checks.spec
index e31a2ce..1468ab9 100644
--- a/opengl/tools/glgen/specs/gles11/checks.spec
+++ b/opengl/tools/glgen/specs/gles11/checks.spec
@@ -1,61 +1,62 @@
-glClipPlanef check eqn 4

-glClipPlanex check eqn 4

-glGetClipPlanefOES check eqn 4

-glGetClipPlanexOES check eqn 4

-glDeleteBuffers check buffers n 

-glDeleteTextures check textures n

-glDrawElements check_AIOOBE indices count

-glFog ifcheck params 1 pname GL_FOG_MODE,GL_FOG_DENSITY,GL_FOG_START,GL_FOG_END ifcheck params 4 pname GL_FOG_COLOR

-glGenBuffers check buffers n

-glGenTextures check textures n

-glGetClipPlane check eqn 4

-glGetIntegerv ifcheck params 1 pname GL_ALPHA_BITS,GL_ALPHA_TEST_FUNC,GL_ALPHA_TEST_REF,GL_BLEND_DST,GL_BLUE_BITS,GL_COLOR_ARRAY_BUFFER_BINDING,GL_COLOR_ARRAY_SIZE,GL_COLOR_ARRAY_STRIDE,GL_COLOR_ARRAY_TYPE,GL_CULL_FACE,GL_DEPTH_BITS,GL_DEPTH_CLEAR_VALUE,GL_DEPTH_FUNC,GL_DEPTH_WRITEMASK,GL_FOG_DENSITY,GL_FOG_END,GL_FOG_MODE,GL_FOG_START,GL_FRONT_FACE,GL_GREEN_BITS,GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES,GL_IMPLEMENTATION_COLOR_READ_TYPE_OES,GL_LIGHT_MODEL_COLOR_CONTROL,GL_LIGHT_MODEL_LOCAL_VIEWER,GL_LIGHT_MODEL_TWO_SIDE,GL_LINE_SMOOTH_HINT,GL_LINE_WIDTH,GL_LOGIC_OP_MODE,GL_MATRIX_INDEX_ARRAY_BUFFER_BINDING_OES,GL_MATRIX_INDEX_ARRAY_SIZE_OES,GL_MATRIX_INDEX_ARRAY_STRIDE_OES,GL_MATRIX_INDEX_ARRAY_TYPE_OES,GL_MATRIX_MODE,GL_MAX_CLIP_PLANES,GL_MAX_ELEMENTS_INDICES,GL_MAX_ELEMENTS_VERTICES,GL_MAX_LIGHTS,GL_MAX_MODELVIEW_STACK_DEPTH,GL_MAX_PALETTE_MATRICES_OES,GL_MAX_PROJECTION_STACK_DEPTH,GL_MAX_TEXTURE_SIZE,GL_MAX_TEXTURE_STACK_DEPTH,GL_MAX_TEXTURE_UNITS,GL_MAX_VERTEX_UNITS_OES,GL_MODELVIEW_STACK_DEPTH,GL_NORMAL_ARRAY_BUFFER_BINDING,GL_NORMAL_ARRAY_STRIDE,GL_NORMAL_ARRAY_TYPE,GL_NUM_COMPRESSED_TEXTURE_FORMATS,GL_PACK_ALIGNMENT,GL_PERSPECTIVE_CORRECTION_HINT,GL_POINT_SIZE,GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES,GL_POINT_SIZE_ARRAY_STRIDE_OES,GL_POINT_SIZE_ARRAY_TYPE_OES,GL_POINT_SMOOTH_HINT,GL_POLYGON_OFFSET_FACTOR,GL_POLYGON_OFFSET_UNITS,GL_PROJECTION_STACK_DEPTH,GL_RED_BITS,GL_SHADE_MODEL,GL_STENCIL_BITS,GL_STENCIL_CLEAR_VALUE,GL_STENCIL_FAIL,GL_STENCIL_FUNC,GL_STENCIL_PASS_DEPTH_FAIL,GL_STENCIL_PASS_DEPTH_PASS,GL_STENCIL_REF,GL_STENCIL_VALUE_MASK,GL_STENCIL_WRITEMASK,GL_SUBPIXEL_BITS,GL_TEXTURE_BINDING_2D,GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING,GL_TEXTURE_COORD_ARRAY_SIZE,GL_TEXTURE_COORD_ARRAY_STRIDE,GL_TEXTURE_COORD_ARRAY_TYPE,GL_TEXTURE_STACK_DEPTH,GL_UNPACK_ALIGNMENT,GL_VERTEX_ARRAY_BUFFER_BINDING,GL_VERTEX_ARRAY_SIZE,GL_VERTEX_ARRAY_STRIDE,GL_VERTEX_ARRAY_TYPE,GL_WEIGHT_ARRAY_BUFFER_BINDING_OES,GL_WEIGHT_ARRAY_SIZE_OES,GL_WEIGHT_ARRAY_STRIDE_OES,GL_WEIGHT_ARRAY_TYPE_OES ifcheck params 2 pname GL_ALIASED_POINT_SIZE_RANGE,GL_ALIASED_LINE_WIDTH_RANGE,GL_DEPTH_RANGE,GL_MAX_VIEWPORT_DIMS,GL_SMOOTH_LINE_WIDTH_RANGE,GL_SMOOTH_POINT_SIZE_RANGE ifcheck params 4 pname GL_COLOR_CLEAR_VALUE,GL_COLOR_WRITEMASK,GL_FOG_COLOR,GL_LIGHT_MODEL_AMBIENT,GL_SCISSOR_BOX,GL_VIEWPORT ifcheck params 16 pname GL_MODELVIEW_MATRIX,GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES,GL_PROJECTION_MATRIX,GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES,GL_TEXTURE_MATRIX,GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES ifcheck params getNumCompressedTextureFormats() pname GL_COMPRESSED_TEXTURE_FORMATS

-glGetLight ifcheck params 1 pname GL_SPOT_EXPONENT,GL_SPOT_CUTOFF,GL_CONSTANT_ATTENUATION,GL_LINEAR_ATTENUATION,GL_QUADRATIC_ATTENUATION ifcheck params 3 pname GL_SPOT_DIRECTION ifcheck params 4 pname GL_AMBIENT,GL_DIFFUSE,GL_SPECULAR,GL_EMISSION

-glGetMaterial ifcheck params 1 pname GL_SHININESS ifcheck params 4 pname GL_AMBIENT,GL_DIFFUSE,GL_SPECULAR,GL_EMISSION,GL_AMBIENT_AND_DIFFUSE

-glGetTexEnv ifcheck params 1 pname GL_TEXTURE_ENV_MODE,GL_COMBINE_RGB,GL_COMBINE_ALPHA ifcheck params 4 pname GL_TEXTURE_ENV_COLOR

-glGetTexParameter check params 1

-glLightModel ifcheck params 1 pname GL_LIGHT_MODEL_TWO_SIDE ifcheck params 4 pname GL_LIGHT_MODEL_AMBIENT

-glLight ifcheck params 1 pname GL_SPOT_EXPONENT,GL_SPOT_CUTOFF,GL_CONSTANT_ATTENUATION,GL_LINEAR_ATTENUATION,GL_QUADRATIC_ATTENUATION ifcheck params 3 pname GL_SPOT_DIRECTION ifcheck params 4 pname GL_AMBIENT,GL_DIFFUSE,GL_SPECULAR,GL_EMISSION

-glLoadMatrix check m 16

-glMaterial ifcheck params 1 pname GL_SHININESS ifcheck params 4 pname GL_AMBIENT,GL_DIFFUSE,GL_SPECULAR,GL_EMISSION,GL_AMBIENT_AND_DIFFUSE

-glMultMatrix check m 16

-glPointParameter check params 1

-glTexEnv ifcheck params 1 pname GL_TEXTURE_ENV_MODE,GL_COMBINE_RGB,GL_COMBINE_ALPHA ifcheck params 4 pname GL_TEXTURE_ENV_COLOR

-glTexImage2D nullAllowed

-glTexSubImage2D nullAllowed

-glBufferData nullAllowed

-glTexParameter check params 1

-glQueryMatrixxOES check mantissa 16 check exponent 16 return -1

-glDrawTexfvOES check coords 5

-glDrawTexivOES check coords 5

-glDrawTexsvOES check coords 5

-glDrawTexxvOES check coords 5

-glBindFramebufferOES unsupported

-glBindRenderbufferOES unsupported

-glBlendEquation unsupported

-glBlendEquationSeparate unsupported

-glBlendFuncSeparate unsupported

-glCheckFramebufferStatusOES unsupported return 0

-glCurrentPaletteMatrixOES unsupported

-glDeleteFramebuffersOES unsupported

-glDeleteRenderbuffersOES unsupported

-glFramebufferRenderbufferOES unsupported

-glFramebufferStorageOES unsupported

-glFramebufferTexture2DOES unsupported

-glGenFramebuffersOES unsupported

-glGenRenderbuffersOES unsupported

-glGenerateMipmapOES unsupported

-glGetBufferParameter unsupported

-glGetFramebufferAttachmentParameterivOES unsupported

-glGetRenderbufferParameterivOES unsupported

-glGetTexGen unsupported

-glIsFramebufferOES unsupported return JNI_FALSE

-glIsRenderbufferOES unsupported return JNI_FALSE

-glLoadPaletteFromModelViewMatrixOES unsupported

-glMatrixIndexPointerOES unsupported

-glRenderbufferStorageOES unsupported return false

-glTexGen unsupported

-glTexGenf unsupported

-glTexGeni unsupported

-glTexGenx unsupported

-glWeightPointerOES unsupported

+glClipPlanef check eqn 4
+glClipPlanex check eqn 4
+glGetClipPlanefOES check eqn 4
+glGetClipPlanexOES check eqn 4
+glDeleteBuffers check buffers n
+glDeleteTextures check textures n
+glDrawElements check_AIOOBE indices count
+glFog ifcheck params 1 pname GL_FOG_MODE,GL_FOG_DENSITY,GL_FOG_START,GL_FOG_END ifcheck params 4 pname GL_FOG_COLOR
+glGenBuffers check buffers n
+glGenTextures check textures n
+glGetClipPlane check eqn 4
+glGetIntegerv ifcheck params 1 pname GL_ALPHA_BITS,GL_ALPHA_TEST_FUNC,GL_ALPHA_TEST_REF,GL_BLEND_DST,GL_BLUE_BITS,GL_COLOR_ARRAY_BUFFER_BINDING,GL_COLOR_ARRAY_SIZE,GL_COLOR_ARRAY_STRIDE,GL_COLOR_ARRAY_TYPE,GL_CULL_FACE,GL_DEPTH_BITS,GL_DEPTH_CLEAR_VALUE,GL_DEPTH_FUNC,GL_DEPTH_WRITEMASK,GL_FOG_DENSITY,GL_FOG_END,GL_FOG_MODE,GL_FOG_START,GL_FRONT_FACE,GL_GREEN_BITS,GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES,GL_IMPLEMENTATION_COLOR_READ_TYPE_OES,GL_LIGHT_MODEL_COLOR_CONTROL,GL_LIGHT_MODEL_LOCAL_VIEWER,GL_LIGHT_MODEL_TWO_SIDE,GL_LINE_SMOOTH_HINT,GL_LINE_WIDTH,GL_LOGIC_OP_MODE,GL_MATRIX_INDEX_ARRAY_BUFFER_BINDING_OES,GL_MATRIX_INDEX_ARRAY_SIZE_OES,GL_MATRIX_INDEX_ARRAY_STRIDE_OES,GL_MATRIX_INDEX_ARRAY_TYPE_OES,GL_MATRIX_MODE,GL_MAX_CLIP_PLANES,GL_MAX_ELEMENTS_INDICES,GL_MAX_ELEMENTS_VERTICES,GL_MAX_LIGHTS,GL_MAX_MODELVIEW_STACK_DEPTH,GL_MAX_PALETTE_MATRICES_OES,GL_MAX_PROJECTION_STACK_DEPTH,GL_MAX_TEXTURE_SIZE,GL_MAX_TEXTURE_STACK_DEPTH,GL_MAX_TEXTURE_UNITS,GL_MAX_VERTEX_UNITS_OES,GL_MODELVIEW_STACK_DEPTH,GL_NORMAL_ARRAY_BUFFER_BINDING,GL_NORMAL_ARRAY_STRIDE,GL_NORMAL_ARRAY_TYPE,GL_NUM_COMPRESSED_TEXTURE_FORMATS,GL_PACK_ALIGNMENT,GL_PERSPECTIVE_CORRECTION_HINT,GL_POINT_SIZE,GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES,GL_POINT_SIZE_ARRAY_STRIDE_OES,GL_POINT_SIZE_ARRAY_TYPE_OES,GL_POINT_SMOOTH_HINT,GL_POLYGON_OFFSET_FACTOR,GL_POLYGON_OFFSET_UNITS,GL_PROJECTION_STACK_DEPTH,GL_RED_BITS,GL_SHADE_MODEL,GL_STENCIL_BITS,GL_STENCIL_CLEAR_VALUE,GL_STENCIL_FAIL,GL_STENCIL_FUNC,GL_STENCIL_PASS_DEPTH_FAIL,GL_STENCIL_PASS_DEPTH_PASS,GL_STENCIL_REF,GL_STENCIL_VALUE_MASK,GL_STENCIL_WRITEMASK,GL_SUBPIXEL_BITS,GL_TEXTURE_BINDING_2D,GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING,GL_TEXTURE_COORD_ARRAY_SIZE,GL_TEXTURE_COORD_ARRAY_STRIDE,GL_TEXTURE_COORD_ARRAY_TYPE,GL_TEXTURE_STACK_DEPTH,GL_UNPACK_ALIGNMENT,GL_VERTEX_ARRAY_BUFFER_BINDING,GL_VERTEX_ARRAY_SIZE,GL_VERTEX_ARRAY_STRIDE,GL_VERTEX_ARRAY_TYPE,GL_WEIGHT_ARRAY_BUFFER_BINDING_OES,GL_WEIGHT_ARRAY_SIZE_OES,GL_WEIGHT_ARRAY_STRIDE_OES,GL_WEIGHT_ARRAY_TYPE_OES ifcheck params 2 pname GL_ALIASED_POINT_SIZE_RANGE,GL_ALIASED_LINE_WIDTH_RANGE,GL_DEPTH_RANGE,GL_MAX_VIEWPORT_DIMS,GL_SMOOTH_LINE_WIDTH_RANGE,GL_SMOOTH_POINT_SIZE_RANGE ifcheck params 4 pname GL_COLOR_CLEAR_VALUE,GL_COLOR_WRITEMASK,GL_FOG_COLOR,GL_LIGHT_MODEL_AMBIENT,GL_SCISSOR_BOX,GL_VIEWPORT ifcheck params 16 pname GL_MODELVIEW_MATRIX,GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES,GL_PROJECTION_MATRIX,GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES,GL_TEXTURE_MATRIX,GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES ifcheck params getNumCompressedTextureFormats() pname GL_COMPRESSED_TEXTURE_FORMATS
+glGetLight ifcheck params 1 pname GL_SPOT_EXPONENT,GL_SPOT_CUTOFF,GL_CONSTANT_ATTENUATION,GL_LINEAR_ATTENUATION,GL_QUADRATIC_ATTENUATION ifcheck params 3 pname GL_SPOT_DIRECTION ifcheck params 4 pname GL_AMBIENT,GL_DIFFUSE,GL_SPECULAR,GL_EMISSION
+glGetMaterial ifcheck params 1 pname GL_SHININESS ifcheck params 4 pname GL_AMBIENT,GL_DIFFUSE,GL_SPECULAR,GL_EMISSION,GL_AMBIENT_AND_DIFFUSE
+glGetTexEnv ifcheck params 1 pname GL_TEXTURE_ENV_MODE,GL_COMBINE_RGB,GL_COMBINE_ALPHA ifcheck params 4 pname GL_TEXTURE_ENV_COLOR
+glGetTexParameter check params 1
+glLightModel ifcheck params 1 pname GL_LIGHT_MODEL_TWO_SIDE ifcheck params 4 pname GL_LIGHT_MODEL_AMBIENT
+glLight ifcheck params 1 pname GL_SPOT_EXPONENT,GL_SPOT_CUTOFF,GL_CONSTANT_ATTENUATION,GL_LINEAR_ATTENUATION,GL_QUADRATIC_ATTENUATION ifcheck params 3 pname GL_SPOT_DIRECTION ifcheck params 4 pname GL_AMBIENT,GL_DIFFUSE,GL_SPECULAR,GL_EMISSION
+glLoadMatrix check m 16
+glMaterial ifcheck params 1 pname GL_SHININESS ifcheck params 4 pname GL_AMBIENT,GL_DIFFUSE,GL_SPECULAR,GL_EMISSION,GL_AMBIENT_AND_DIFFUSE
+glMultMatrix check m 16
+glPointParameter check params 1
+glTexEnv ifcheck params 1 pname GL_TEXTURE_ENV_MODE,GL_COMBINE_RGB,GL_COMBINE_ALPHA ifcheck params 4 pname GL_TEXTURE_ENV_COLOR
+glTexImage2D nullAllowed
+glTexSubImage2D nullAllowed
+glBufferData nullAllowed check data size
+glBufferSubData check data size
+glTexParameter check params 1
+glQueryMatrixxOES check mantissa 16 check exponent 16 return -1
+glDrawTexfvOES check coords 5
+glDrawTexivOES check coords 5
+glDrawTexsvOES check coords 5
+glDrawTexxvOES check coords 5
+glBindFramebufferOES unsupported
+glBindRenderbufferOES unsupported
+glBlendEquation unsupported
+glBlendEquationSeparate unsupported
+glBlendFuncSeparate unsupported
+glCheckFramebufferStatusOES unsupported return 0
+glCurrentPaletteMatrixOES unsupported
+glDeleteFramebuffersOES unsupported
+glDeleteRenderbuffersOES unsupported
+glFramebufferRenderbufferOES unsupported
+glFramebufferStorageOES unsupported
+glFramebufferTexture2DOES unsupported
+glGenFramebuffersOES unsupported
+glGenRenderbuffersOES unsupported
+glGenerateMipmapOES unsupported
+glGetBufferParameter unsupported
+glGetFramebufferAttachmentParameterivOES unsupported
+glGetRenderbufferParameterivOES unsupported
+glGetTexGen unsupported
+glIsFramebufferOES unsupported return JNI_FALSE
+glIsRenderbufferOES unsupported return JNI_FALSE
+glLoadPaletteFromModelViewMatrixOES unsupported
+glMatrixIndexPointerOES unsupported
+glRenderbufferStorageOES unsupported return false
+glTexGen unsupported
+glTexGenf unsupported
+glTexGeni unsupported
+glTexGenx unsupported
+glWeightPointerOES unsupported
diff --git a/opengl/tools/glgen/specs/jsr239/glspec-checks b/opengl/tools/glgen/specs/jsr239/glspec-checks
index 55840fa..063cdc7 100644
--- a/opengl/tools/glgen/specs/jsr239/glspec-checks
+++ b/opengl/tools/glgen/specs/jsr239/glspec-checks
@@ -1,59 +1,60 @@
-glClipPlanef check equation 4

-glClipPlanex check equation 4

-glDeleteBuffers check buffers n 

-glDeleteTextures check textures n

-glDrawElements check_AIOOBE indices count

-glFog ifcheck params 1 pname GL_FOG_MODE,GL_FOG_DENSITY,GL_FOG_START,GL_FOG_END ifcheck params 4 pname GL_FOG_COLOR

-glGenBuffers check buffers n

-glGenTextures check textures n

-glGetClipPlane check eqn 4

-glGetIntegerv ifcheck params 1 pname GL_ALPHA_BITS,GL_ALPHA_TEST_FUNC,GL_ALPHA_TEST_REF,GL_BLEND_DST,GL_BLUE_BITS,GL_COLOR_ARRAY_BUFFER_BINDING,GL_COLOR_ARRAY_SIZE,GL_COLOR_ARRAY_STRIDE,GL_COLOR_ARRAY_TYPE,GL_CULL_FACE,GL_DEPTH_BITS,GL_DEPTH_CLEAR_VALUE,GL_DEPTH_FUNC,GL_DEPTH_WRITEMASK,GL_FOG_DENSITY,GL_FOG_END,GL_FOG_MODE,GL_FOG_START,GL_FRONT_FACE,GL_GREEN_BITS,GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES,GL_IMPLEMENTATION_COLOR_READ_TYPE_OES,GL_LIGHT_MODEL_COLOR_CONTROL,GL_LIGHT_MODEL_LOCAL_VIEWER,GL_LIGHT_MODEL_TWO_SIDE,GL_LINE_SMOOTH_HINT,GL_LINE_WIDTH,GL_LOGIC_OP_MODE,GL_MATRIX_INDEX_ARRAY_BUFFER_BINDING_OES,GL_MATRIX_INDEX_ARRAY_SIZE_OES,GL_MATRIX_INDEX_ARRAY_STRIDE_OES,GL_MATRIX_INDEX_ARRAY_TYPE_OES,GL_MATRIX_MODE,GL_MAX_CLIP_PLANES,GL_MAX_ELEMENTS_INDICES,GL_MAX_ELEMENTS_VERTICES,GL_MAX_LIGHTS,GL_MAX_MODELVIEW_STACK_DEPTH,GL_MAX_PALETTE_MATRICES_OES,GL_MAX_PROJECTION_STACK_DEPTH,GL_MAX_TEXTURE_SIZE,GL_MAX_TEXTURE_STACK_DEPTH,GL_MAX_TEXTURE_UNITS,GL_MAX_VERTEX_UNITS_OES,GL_MODELVIEW_STACK_DEPTH,GL_NORMAL_ARRAY_BUFFER_BINDING,GL_NORMAL_ARRAY_STRIDE,GL_NORMAL_ARRAY_TYPE,GL_NUM_COMPRESSED_TEXTURE_FORMATS,GL_PACK_ALIGNMENT,GL_PERSPECTIVE_CORRECTION_HINT,GL_POINT_SIZE,GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES,GL_POINT_SIZE_ARRAY_STRIDE_OES,GL_POINT_SIZE_ARRAY_TYPE_OES,GL_POINT_SMOOTH_HINT,GL_POLYGON_OFFSET_FACTOR,GL_POLYGON_OFFSET_UNITS,GL_PROJECTION_STACK_DEPTH,GL_RED_BITS,GL_SHADE_MODEL,GL_STENCIL_BITS,GL_STENCIL_CLEAR_VALUE,GL_STENCIL_FAIL,GL_STENCIL_FUNC,GL_STENCIL_PASS_DEPTH_FAIL,GL_STENCIL_PASS_DEPTH_PASS,GL_STENCIL_REF,GL_STENCIL_VALUE_MASK,GL_STENCIL_WRITEMASK,GL_SUBPIXEL_BITS,GL_TEXTURE_BINDING_2D,GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING,GL_TEXTURE_COORD_ARRAY_SIZE,GL_TEXTURE_COORD_ARRAY_STRIDE,GL_TEXTURE_COORD_ARRAY_TYPE,GL_TEXTURE_STACK_DEPTH,GL_UNPACK_ALIGNMENT,GL_VERTEX_ARRAY_BUFFER_BINDING,GL_VERTEX_ARRAY_SIZE,GL_VERTEX_ARRAY_STRIDE,GL_VERTEX_ARRAY_TYPE,GL_WEIGHT_ARRAY_BUFFER_BINDING_OES,GL_WEIGHT_ARRAY_SIZE_OES,GL_WEIGHT_ARRAY_STRIDE_OES,GL_WEIGHT_ARRAY_TYPE_OES ifcheck params 2 pname GL_ALIASED_POINT_SIZE_RANGE,GL_ALIASED_LINE_WIDTH_RANGE,GL_DEPTH_RANGE,GL_MAX_VIEWPORT_DIMS,GL_SMOOTH_LINE_WIDTH_RANGE,GL_SMOOTH_POINT_SIZE_RANGE ifcheck params 4 pname GL_COLOR_CLEAR_VALUE,GL_COLOR_WRITEMASK,GL_FOG_COLOR,GL_LIGHT_MODEL_AMBIENT,GL_SCISSOR_BOX,GL_VIEWPORT ifcheck params 16 pname GL_MODELVIEW_MATRIX,GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES,GL_PROJECTION_MATRIX,GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES,GL_TEXTURE_MATRIX,GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES ifcheck params getNumCompressedTextureFormats() pname GL_COMPRESSED_TEXTURE_FORMATS

-glGetLight ifcheck params 1 pname GL_SPOT_EXPONENT,GL_SPOT_CUTOFF,GL_CONSTANT_ATTENUATION,GL_LINEAR_ATTENUATION,GL_QUADRATIC_ATTENUATION ifcheck params 3 pname GL_SPOT_DIRECTION ifcheck params 4 pname GL_AMBIENT,GL_DIFFUSE,GL_SPECULAR,GL_EMISSION

-glGetMaterial ifcheck params 1 pname GL_SHININESS ifcheck params 4 pname GL_AMBIENT,GL_DIFFUSE,GL_SPECULAR,GL_EMISSION,GL_AMBIENT_AND_DIFFUSE

-glGetTexEnv ifcheck params 1 pname GL_TEXTURE_ENV_MODE,GL_COMBINE_RGB,GL_COMBINE_ALPHA ifcheck params 4 pname GL_TEXTURE_ENV_COLOR

-glGetTexParameter check params 1

-glLightModel ifcheck params 1 pname GL_LIGHT_MODEL_TWO_SIDE ifcheck params 4 pname GL_LIGHT_MODEL_AMBIENT

-glLight ifcheck params 1 pname GL_SPOT_EXPONENT,GL_SPOT_CUTOFF,GL_CONSTANT_ATTENUATION,GL_LINEAR_ATTENUATION,GL_QUADRATIC_ATTENUATION ifcheck params 3 pname GL_SPOT_DIRECTION ifcheck params 4 pname GL_AMBIENT,GL_DIFFUSE,GL_SPECULAR,GL_EMISSION

-glLoadMatrix check m 16

-glMaterial ifcheck params 1 pname GL_SHININESS ifcheck params 4 pname GL_AMBIENT,GL_DIFFUSE,GL_SPECULAR,GL_EMISSION,GL_AMBIENT_AND_DIFFUSE

-glMultMatrix check m 16

-glPointParameter check params 1

-glTexEnv ifcheck params 1 pname GL_TEXTURE_ENV_MODE,GL_COMBINE_RGB,GL_COMBINE_ALPHA ifcheck params 4 pname GL_TEXTURE_ENV_COLOR

-glTexImage2D nullAllowed

-glTexSubImage2D nullAllowed

-glBufferData nullAllowed

-glTexParameter check params 1

-glQueryMatrixxOES check mantissa 16 check exponent 16 return -1

-glDrawTexfvOES check coords 5

-glDrawTexivOES check coords 5

-glDrawTexsvOES check coords 5

-glDrawTexxvOES check coords 5

-glBindFramebufferOES unsupported

-glBindRenderbufferOES unsupported

-glBlendEquation unsupported

-glBlendEquationSeparate unsupported

-glBlendFuncSeparate unsupported

-glCheckFramebufferStatusOES unsupported return 0

-glCurrentPaletteMatrixOES unsupported

-glDeleteFramebuffersOES unsupported

-glDeleteRenderbuffersOES unsupported

-glFramebufferRenderbufferOES unsupported

-glFramebufferStorageOES unsupported

-glFramebufferTexture2DOES unsupported

-glGenFramebuffersOES unsupported

-glGenRenderbuffersOES unsupported

-glGenerateMipmapOES unsupported

-glGetBufferParameter unsupported

-glGetFramebufferAttachmentParameterivOES unsupported

-glGetRenderbufferParameterivOES unsupported

-glGetTexGen unsupported

-glIsFramebufferOES unsupported return JNI_FALSE

-glIsRenderbufferOES unsupported return JNI_FALSE

-glLoadPaletteFromModelViewMatrixOES unsupported

-glMatrixIndexPointerOES unsupported

-glRenderbufferStorageOES unsupported return false

-glTexGen unsupported

-glTexGenf unsupported

-glTexGeni unsupported

-glTexGenx unsupported

-glWeightPointerOES unsupported

+glClipPlanef check equation 4
+glClipPlanex check equation 4
+glDeleteBuffers check buffers n
+glDeleteTextures check textures n
+glDrawElements check_AIOOBE indices count
+glFog ifcheck params 1 pname GL_FOG_MODE,GL_FOG_DENSITY,GL_FOG_START,GL_FOG_END ifcheck params 4 pname GL_FOG_COLOR
+glGenBuffers check buffers n
+glGenTextures check textures n
+glGetClipPlane check eqn 4
+glGetIntegerv ifcheck params 1 pname GL_ALPHA_BITS,GL_ALPHA_TEST_FUNC,GL_ALPHA_TEST_REF,GL_BLEND_DST,GL_BLUE_BITS,GL_COLOR_ARRAY_BUFFER_BINDING,GL_COLOR_ARRAY_SIZE,GL_COLOR_ARRAY_STRIDE,GL_COLOR_ARRAY_TYPE,GL_CULL_FACE,GL_DEPTH_BITS,GL_DEPTH_CLEAR_VALUE,GL_DEPTH_FUNC,GL_DEPTH_WRITEMASK,GL_FOG_DENSITY,GL_FOG_END,GL_FOG_MODE,GL_FOG_START,GL_FRONT_FACE,GL_GREEN_BITS,GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES,GL_IMPLEMENTATION_COLOR_READ_TYPE_OES,GL_LIGHT_MODEL_COLOR_CONTROL,GL_LIGHT_MODEL_LOCAL_VIEWER,GL_LIGHT_MODEL_TWO_SIDE,GL_LINE_SMOOTH_HINT,GL_LINE_WIDTH,GL_LOGIC_OP_MODE,GL_MATRIX_INDEX_ARRAY_BUFFER_BINDING_OES,GL_MATRIX_INDEX_ARRAY_SIZE_OES,GL_MATRIX_INDEX_ARRAY_STRIDE_OES,GL_MATRIX_INDEX_ARRAY_TYPE_OES,GL_MATRIX_MODE,GL_MAX_CLIP_PLANES,GL_MAX_ELEMENTS_INDICES,GL_MAX_ELEMENTS_VERTICES,GL_MAX_LIGHTS,GL_MAX_MODELVIEW_STACK_DEPTH,GL_MAX_PALETTE_MATRICES_OES,GL_MAX_PROJECTION_STACK_DEPTH,GL_MAX_TEXTURE_SIZE,GL_MAX_TEXTURE_STACK_DEPTH,GL_MAX_TEXTURE_UNITS,GL_MAX_VERTEX_UNITS_OES,GL_MODELVIEW_STACK_DEPTH,GL_NORMAL_ARRAY_BUFFER_BINDING,GL_NORMAL_ARRAY_STRIDE,GL_NORMAL_ARRAY_TYPE,GL_NUM_COMPRESSED_TEXTURE_FORMATS,GL_PACK_ALIGNMENT,GL_PERSPECTIVE_CORRECTION_HINT,GL_POINT_SIZE,GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES,GL_POINT_SIZE_ARRAY_STRIDE_OES,GL_POINT_SIZE_ARRAY_TYPE_OES,GL_POINT_SMOOTH_HINT,GL_POLYGON_OFFSET_FACTOR,GL_POLYGON_OFFSET_UNITS,GL_PROJECTION_STACK_DEPTH,GL_RED_BITS,GL_SHADE_MODEL,GL_STENCIL_BITS,GL_STENCIL_CLEAR_VALUE,GL_STENCIL_FAIL,GL_STENCIL_FUNC,GL_STENCIL_PASS_DEPTH_FAIL,GL_STENCIL_PASS_DEPTH_PASS,GL_STENCIL_REF,GL_STENCIL_VALUE_MASK,GL_STENCIL_WRITEMASK,GL_SUBPIXEL_BITS,GL_TEXTURE_BINDING_2D,GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING,GL_TEXTURE_COORD_ARRAY_SIZE,GL_TEXTURE_COORD_ARRAY_STRIDE,GL_TEXTURE_COORD_ARRAY_TYPE,GL_TEXTURE_STACK_DEPTH,GL_UNPACK_ALIGNMENT,GL_VERTEX_ARRAY_BUFFER_BINDING,GL_VERTEX_ARRAY_SIZE,GL_VERTEX_ARRAY_STRIDE,GL_VERTEX_ARRAY_TYPE,GL_WEIGHT_ARRAY_BUFFER_BINDING_OES,GL_WEIGHT_ARRAY_SIZE_OES,GL_WEIGHT_ARRAY_STRIDE_OES,GL_WEIGHT_ARRAY_TYPE_OES ifcheck params 2 pname GL_ALIASED_POINT_SIZE_RANGE,GL_ALIASED_LINE_WIDTH_RANGE,GL_DEPTH_RANGE,GL_MAX_VIEWPORT_DIMS,GL_SMOOTH_LINE_WIDTH_RANGE,GL_SMOOTH_POINT_SIZE_RANGE ifcheck params 4 pname GL_COLOR_CLEAR_VALUE,GL_COLOR_WRITEMASK,GL_FOG_COLOR,GL_LIGHT_MODEL_AMBIENT,GL_SCISSOR_BOX,GL_VIEWPORT ifcheck params 16 pname GL_MODELVIEW_MATRIX,GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES,GL_PROJECTION_MATRIX,GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES,GL_TEXTURE_MATRIX,GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES ifcheck params getNumCompressedTextureFormats() pname GL_COMPRESSED_TEXTURE_FORMATS
+glGetLight ifcheck params 1 pname GL_SPOT_EXPONENT,GL_SPOT_CUTOFF,GL_CONSTANT_ATTENUATION,GL_LINEAR_ATTENUATION,GL_QUADRATIC_ATTENUATION ifcheck params 3 pname GL_SPOT_DIRECTION ifcheck params 4 pname GL_AMBIENT,GL_DIFFUSE,GL_SPECULAR,GL_EMISSION
+glGetMaterial ifcheck params 1 pname GL_SHININESS ifcheck params 4 pname GL_AMBIENT,GL_DIFFUSE,GL_SPECULAR,GL_EMISSION,GL_AMBIENT_AND_DIFFUSE
+glGetTexEnv ifcheck params 1 pname GL_TEXTURE_ENV_MODE,GL_COMBINE_RGB,GL_COMBINE_ALPHA ifcheck params 4 pname GL_TEXTURE_ENV_COLOR
+glGetTexParameter check params 1
+glLightModel ifcheck params 1 pname GL_LIGHT_MODEL_TWO_SIDE ifcheck params 4 pname GL_LIGHT_MODEL_AMBIENT
+glLight ifcheck params 1 pname GL_SPOT_EXPONENT,GL_SPOT_CUTOFF,GL_CONSTANT_ATTENUATION,GL_LINEAR_ATTENUATION,GL_QUADRATIC_ATTENUATION ifcheck params 3 pname GL_SPOT_DIRECTION ifcheck params 4 pname GL_AMBIENT,GL_DIFFUSE,GL_SPECULAR,GL_EMISSION
+glLoadMatrix check m 16
+glMaterial ifcheck params 1 pname GL_SHININESS ifcheck params 4 pname GL_AMBIENT,GL_DIFFUSE,GL_SPECULAR,GL_EMISSION,GL_AMBIENT_AND_DIFFUSE
+glMultMatrix check m 16
+glPointParameter check params 1
+glTexEnv ifcheck params 1 pname GL_TEXTURE_ENV_MODE,GL_COMBINE_RGB,GL_COMBINE_ALPHA ifcheck params 4 pname GL_TEXTURE_ENV_COLOR
+glTexImage2D nullAllowed
+glTexSubImage2D nullAllowed
+glBufferData nullAllowed check data size
+glBufferSubData check data size
+glTexParameter check params 1
+glQueryMatrixxOES check mantissa 16 check exponent 16 return -1
+glDrawTexfvOES check coords 5
+glDrawTexivOES check coords 5
+glDrawTexsvOES check coords 5
+glDrawTexxvOES check coords 5
+glBindFramebufferOES unsupported
+glBindRenderbufferOES unsupported
+glBlendEquation unsupported
+glBlendEquationSeparate unsupported
+glBlendFuncSeparate unsupported
+glCheckFramebufferStatusOES unsupported return 0
+glCurrentPaletteMatrixOES unsupported
+glDeleteFramebuffersOES unsupported
+glDeleteRenderbuffersOES unsupported
+glFramebufferRenderbufferOES unsupported
+glFramebufferStorageOES unsupported
+glFramebufferTexture2DOES unsupported
+glGenFramebuffersOES unsupported
+glGenRenderbuffersOES unsupported
+glGenerateMipmapOES unsupported
+glGetBufferParameter unsupported
+glGetFramebufferAttachmentParameterivOES unsupported
+glGetRenderbufferParameterivOES unsupported
+glGetTexGen unsupported
+glIsFramebufferOES unsupported return JNI_FALSE
+glIsRenderbufferOES unsupported return JNI_FALSE
+glLoadPaletteFromModelViewMatrixOES unsupported
+glMatrixIndexPointerOES unsupported
+glRenderbufferStorageOES unsupported return false
+glTexGen unsupported
+glTexGenf unsupported
+glTexGeni unsupported
+glTexGenx unsupported
+glWeightPointerOES unsupported
diff --git a/opengl/tools/glgen/src/JniCodeEmitter.java b/opengl/tools/glgen/src/JniCodeEmitter.java
index 7340357..2cdb244 100644
--- a/opengl/tools/glgen/src/JniCodeEmitter.java
+++ b/opengl/tools/glgen/src/JniCodeEmitter.java
@@ -893,7 +893,7 @@
                                 ") getDirectBufferPointer(_env, " +
                                 cname + "_buf);");
                         String iii = "    ";
-                        out.println(iii + indent + "if ( ! " + cname + " ) {");	
+                        out.println(iii + indent + "if ( ! " + cname + " ) {");
                         out.println(iii + iii + indent + "return;");
                         out.println(iii + indent + "}");
                     } else {
@@ -907,13 +907,13 @@
                                     ");");
                     }
 
+                    emitNativeBoundsChecks(cfunc, cname, out, true,
+                                           emitExceptionCheck,
+                                           offset, remaining, nullAllowed ? "        " : "    ");
+
                     if (nullAllowed) {
                         out.println(indent + "}");
                     }
-
-                    emitNativeBoundsChecks(cfunc, cname, out, true,
-                                           emitExceptionCheck,
-                                           offset, remaining, "    ");
                 }
             }
         }
diff --git a/vpn/java/android/net/vpn/VpnManager.java b/vpn/java/android/net/vpn/VpnManager.java
index f71bbea..6df612e 100644
--- a/vpn/java/android/net/vpn/VpnManager.java
+++ b/vpn/java/android/net/vpn/VpnManager.java
@@ -45,18 +45,25 @@
     /** Key to the error code of a connectivity broadcast event. */
     public static final String BROADCAST_ERROR_CODE = "err";
     /** Error code to indicate an error from authentication. */
-    public static final int VPN_ERROR_AUTH = 1;
+    public static final int VPN_ERROR_AUTH = 51;
     /** Error code to indicate the connection attempt failed. */
-    public static final int VPN_ERROR_CONNECTION_FAILED = 2;
+    public static final int VPN_ERROR_CONNECTION_FAILED = 101;
     /** Error code to indicate the server is not known. */
-    public static final int VPN_ERROR_UNKNOWN_SERVER = 3;
+    public static final int VPN_ERROR_UNKNOWN_SERVER = 102;
     /** Error code to indicate an error from challenge response. */
-    public static final int VPN_ERROR_CHALLENGE = 4;
+    public static final int VPN_ERROR_CHALLENGE = 5;
     /** Error code to indicate an error of remote server hanging up. */
-    public static final int VPN_ERROR_REMOTE_HUNG_UP = 5;
+    public static final int VPN_ERROR_REMOTE_HUNG_UP = 7;
+    /** Error code to indicate an error of remote PPP server hanging up. */
+    public static final int VPN_ERROR_REMOTE_PPP_HUNG_UP = 48;
+    /** Error code to indicate a PPP negotiation error. */
+    public static final int VPN_ERROR_PPP_NEGOTIATION_FAILED = 42;
     /** Error code to indicate an error of losing connectivity. */
-    public static final int VPN_ERROR_CONNECTION_LOST = 6;
-    private static final int VPN_ERROR_NO_ERROR = 0;
+    public static final int VPN_ERROR_CONNECTION_LOST = 103;
+    /** Largest error code used by VPN. */
+    public static final int VPN_ERROR_LARGEST = 200;
+    /** Error code to indicate a successful connection. */
+    public static final int VPN_ERROR_NO_ERROR = 0;
 
     public static final String PROFILES_PATH = "/data/misc/vpn/profiles";
 
diff --git a/vpn/java/android/net/vpn/VpnType.java b/vpn/java/android/net/vpn/VpnType.java
index c7df943..356f8b1 100644
--- a/vpn/java/android/net/vpn/VpnType.java
+++ b/vpn/java/android/net/vpn/VpnType.java
@@ -16,26 +16,28 @@
 
 package android.net.vpn;
 
+import com.android.internal.R;
+
 /**
  * Enumeration of all supported VPN types.
  * {@hide}
  */
 public enum VpnType {
-    PPTP("PPTP", "", PptpProfile.class),
-    L2TP("L2TP", "", L2tpProfile.class),
-    L2TP_IPSEC_PSK("L2TP/IPSec PSK", "Pre-shared key based L2TP/IPSec VPN",
+    PPTP("PPTP", R.string.pptp_vpn_description, PptpProfile.class),
+    L2TP("L2TP", R.string.l2tp_vpn_description, L2tpProfile.class),
+    L2TP_IPSEC_PSK("L2TP/IPSec PSK", R.string.l2tp_ipsec_psk_vpn_description,
             L2tpIpsecPskProfile.class),
-    L2TP_IPSEC("L2TP/IPSec CRT", "Certificate based L2TP/IPSec VPN",
+    L2TP_IPSEC("L2TP/IPSec CRT", R.string.l2tp_ipsec_crt_vpn_description,
             L2tpIpsecProfile.class);
 
     private String mDisplayName;
-    private String mDescription;
+    private int mDescriptionId;
     private Class<? extends VpnProfile> mClass;
 
-    VpnType(String displayName, String description,
+    VpnType(String displayName, int descriptionId,
             Class<? extends VpnProfile> klass) {
         mDisplayName = displayName;
-        mDescription = description;
+        mDescriptionId = descriptionId;
         mClass = klass;
     }
 
@@ -43,8 +45,8 @@
         return mDisplayName;
     }
 
-    public String getDescription() {
-        return mDescription;
+    public int getDescriptionId() {
+        return mDescriptionId;
     }
 
     public Class<? extends VpnProfile> getProfileClass() {