Merge change 10326

* changes:
  Javadoc used startApplication() which doesnt exists, changed to createApplication()
diff --git a/NOTICE b/NOTICE
index 267a6aa..bb9c5f2 100644
--- a/NOTICE
+++ b/NOTICE
@@ -220,3 +220,54 @@
 
    END OF TERMS AND CONDITIONS
 
+
+
+UNICODE, INC. LICENSE AGREEMENT - DATA FILES AND SOFTWARE
+
+Unicode Data Files include all data files under the directories
+http://www.unicode.org/Public/, http://www.unicode.org/reports/,
+and http://www.unicode.org/cldr/data/ . Unicode Software includes any
+source code published in the Unicode Standard or under the directories
+http://www.unicode.org/Public/, http://www.unicode.org/reports/, and
+http://www.unicode.org/cldr/data/.
+
+NOTICE TO USER: Carefully read the following legal agreement. BY
+DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING UNICODE INC.'S DATA
+FILES ("DATA FILES"), AND/OR SOFTWARE ("SOFTWARE"), YOU UNEQUIVOCALLY
+ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE TERMS AND CONDITIONS OF
+THIS AGREEMENT. IF YOU DO NOT AGREE, DO NOT DOWNLOAD, INSTALL, COPY,
+DISTRIBUTE OR USE THE DATA FILES OR SOFTWARE.
+
+COPYRIGHT AND PERMISSION NOTICE
+
+Copyright © 1991-2008 Unicode, Inc. All rights reserved. Distributed
+under the Terms of Use in http://www.unicode.org/copyright.html.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Unicode data files and any associated documentation (the
+"Data Files") or Unicode software and any associated documentation (the
+"Software") to deal in the Data Files or Software without restriction,
+including without limitation the rights to use, copy, modify, merge,
+publish, distribute, and/or sell copies of the Data Files or Software,
+and to permit persons to whom the Data Files or Software are furnished to
+do so, provided that (a) the above copyright notice(s) and this permission
+notice appear with all copies of the Data Files or Software, (b) both the
+above copyright notice(s) and this permission notice appear in associated
+documentation, and (c) there is clear notice in each modified Data File
+or in the Software as well as in the documentation associated with the
+Data File(s) or Software that the data or software has been modified.
+
+THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
+INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
+OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
+OR PERFORMANCE OF THE DATA FILES OR SOFTWARE.
+
+Except as contained in this notice, the name of a copyright holder
+shall not be used in advertising or otherwise to promote the sale, use
+or other dealings in these Data Files or Software without prior written
+authorization of the copyright holder.
diff --git a/awt/Android.mk b/awt/Android.mk
index c7480f5..213c6ce 100644
--- a/awt/Android.mk
+++ b/awt/Android.mk
@@ -28,4 +28,4 @@
 
 LOCAL_DX_FLAGS := --core-library
 
-include $(BUILD_JAVA_LIBRARY)
+#include $(BUILD_JAVA_LIBRARY)
diff --git a/camera/libcameraservice/CameraHardwareStub.cpp b/camera/libcameraservice/CameraHardwareStub.cpp
index 0f1ae8e..a7af57c 100644
--- a/camera/libcameraservice/CameraHardwareStub.cpp
+++ b/camera/libcameraservice/CameraHardwareStub.cpp
@@ -314,7 +314,7 @@
     String8 result;
     AutoMutex lock(&mLock);
     if (mFakeCamera != 0) {
-        mFakeCamera->dump(fd, args);
+        mFakeCamera->dump(fd);
         mParameters.dump(fd, args);
         snprintf(buffer, 255, " preview frame(%d), size (%d), running(%s)\n", mCurrentPreviewFrame, mPreviewFrameSize, mPreviewRunning?"true": "false");
         result.append(buffer);
diff --git a/camera/libcameraservice/CameraService.cpp b/camera/libcameraservice/CameraService.cpp
index cb8ab58..e4b6791 100644
--- a/camera/libcameraservice/CameraService.cpp
+++ b/camera/libcameraservice/CameraService.cpp
@@ -32,6 +32,7 @@
 #include <media/AudioSystem.h>
 #include "CameraService.h"
 
+#include <cutils/atomic.h>
 #include <cutils/properties.h>
 
 namespace android {
@@ -42,6 +43,7 @@
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <pthread.h>
+#include <signal.h>
 }
 
 // When you enable this, as well as DEBUG_REFS=1 and
@@ -63,6 +65,10 @@
 static int debug_frame_cnt;
 #endif
 
+static int getCallingPid() {
+    return IPCThreadState::self()->getCallingPid();
+}
+
 // ----------------------------------------------------------------------------
 
 void CameraService::instantiate() {
@@ -76,6 +82,7 @@
     BnCameraService()
 {
     LOGI("CameraService started: pid=%d", getpid());
+    mUsers = 0;
 }
 
 CameraService::~CameraService()
@@ -87,72 +94,105 @@
 
 sp<ICamera> CameraService::connect(const sp<ICameraClient>& cameraClient)
 {
-    LOGD("Connect E from ICameraClient %p", cameraClient->asBinder().get());
+    int callingPid = getCallingPid();
+    LOGD("CameraService::connect E (pid %d, client %p)", callingPid,
+            cameraClient->asBinder().get());
 
-    Mutex::Autolock lock(mLock);
+    Mutex::Autolock lock(mServiceLock);
     sp<Client> client;
     if (mClient != 0) {
         sp<Client> currentClient = mClient.promote();
         if (currentClient != 0) {
             sp<ICameraClient> currentCameraClient(currentClient->getCameraClient());
             if (cameraClient->asBinder() == currentCameraClient->asBinder()) {
-                // this is the same client reconnecting...
-                LOGD("Connect X same client (%p) is reconnecting...", cameraClient->asBinder().get());
+                // This is the same client reconnecting...
+                LOGD("CameraService::connect X (pid %d, same client %p) is reconnecting...",
+                    callingPid, cameraClient->asBinder().get());
                 return currentClient;
             } else {
-                // it's another client... reject it
-                LOGD("new client (%p) attempting to connect - rejected", cameraClient->asBinder().get());
+                // It's another client... reject it
+                LOGD("CameraService::connect X (pid %d, new client %p) rejected. "
+                    "(old pid %d, old client %p)",
+                    callingPid, cameraClient->asBinder().get(),
+                    currentClient->mClientPid, currentCameraClient->asBinder().get());
+                if (kill(currentClient->mClientPid, 0) == -1 && errno == ESRCH) {
+                    LOGD("The old client is dead!");
+                }
                 return client;
             }
         } else {
             // can't promote, the previous client has died...
-            LOGD("new client connecting, old reference was dangling...");
+            LOGD("New client (pid %d) connecting, old reference was dangling...",
+                    callingPid);
             mClient.clear();
         }
     }
 
+    if (mUsers > 0) {
+        LOGD("Still have client, rejected");
+        return client;
+    }
+
     // create a new Client object
-    client = new Client(this, cameraClient, IPCThreadState::self()->getCallingPid());
+    client = new Client(this, cameraClient, callingPid);
     mClient = client;
 #if DEBUG_CLIENT_REFERENCES
     // Enable tracking for this object, and track increments and decrements of
     // the refcount.
     client->trackMe(true, true);
 #endif
-    LOGD("Connect X");
+    LOGD("CameraService::connect X");
     return client;
 }
 
 void CameraService::removeClient(const sp<ICameraClient>& cameraClient)
 {
-    // declar this outside the lock to make absolutely sure the
+    int callingPid = getCallingPid();
+
+    // Declare this outside the lock to make absolutely sure the
     // destructor won't be called with the lock held.
     sp<Client> client;
 
-    Mutex::Autolock lock(mLock);
+    Mutex::Autolock lock(mServiceLock);
 
     if (mClient == 0) {
         // This happens when we have already disconnected.
-        LOGV("mClient is null.");
+        LOGD("removeClient (pid %d): already disconnected", callingPid);
         return;
     }
 
-    // Promote mClient. It should never fail because we're called from
-    // a binder call, so someone has to have a strong reference.
+    // Promote mClient. It can fail if we are called from this path:
+    // Client::~Client() -> disconnect() -> removeClient().
     client = mClient.promote();
     if (client == 0) {
-        LOGW("can't get a strong reference on mClient!");
+        LOGD("removeClient (pid %d): no more strong reference", callingPid);
         mClient.clear();
         return;
     }
 
     if (cameraClient->asBinder() != client->getCameraClient()->asBinder()) {
         // ugh! that's not our client!!
-        LOGW("removeClient() called, but mClient doesn't match!");
+        LOGW("removeClient (pid %d): mClient doesn't match!", callingPid);
     } else {
         // okay, good, forget about mClient
         mClient.clear();
     }
+
+    LOGD("removeClient (pid %d) done", callingPid);
+}
+
+// The reason we need this count is a new CameraService::connect() request may
+// come in while the previous Client's destructor has not been run or is still
+// running. If the last strong reference of the previous Client is gone but
+// destructor has not been run, we should not allow the new Client to be created
+// because we need to wait for the previous Client to tear down the hardware
+// first.
+void CameraService::incUsers() {
+    android_atomic_inc(&mUsers);
+}
+
+void CameraService::decUsers() {
+    android_atomic_dec(&mUsers);
 }
 
 static sp<MediaPlayer> newMediaPlayer(const char *file) 
@@ -177,7 +217,8 @@
 CameraService::Client::Client(const sp<CameraService>& cameraService,
         const sp<ICameraClient>& cameraClient, pid_t clientPid)
 {
-    LOGD("Client E constructor");
+    int callingPid = getCallingPid();
+    LOGD("Client::Client E (pid %d)", callingPid);
     mCameraService = cameraService;
     mCameraClient = cameraClient;
     mClientPid = clientPid;
@@ -189,22 +230,28 @@
 
     // Callback is disabled by default
     mPreviewCallbackFlag = FRAME_CALLBACK_FLAG_NOOP;
-    LOGD("Client X constructor");
+    cameraService->incUsers();
+    LOGD("Client::Client X (pid %d)", callingPid);
 }
 
 status_t CameraService::Client::checkPid()
 {
-    if (mClientPid == IPCThreadState::self()->getCallingPid()) return NO_ERROR;
-    LOGW("Attempt to use locked camera (%p) from different process", getCameraClient()->asBinder().get());
+    int callingPid = getCallingPid();
+    if (mClientPid == callingPid) return NO_ERROR;
+    LOGW("Attempt to use locked camera (client %p) from different process "
+        " (old pid %d, new pid %d)",
+        getCameraClient()->asBinder().get(), mClientPid, callingPid);
     return -EBUSY;
 }
 
 status_t CameraService::Client::lock()
 {
+    int callingPid = getCallingPid();
+    LOGD("lock from pid %d (mClientPid %d)", callingPid, mClientPid);
     Mutex::Autolock _l(mLock);
     // lock camera to this client if the the camera is unlocked
     if (mClientPid == 0) {
-        mClientPid = IPCThreadState::self()->getCallingPid();
+        mClientPid = callingPid;
         return NO_ERROR;
     }
     // returns NO_ERROR if the client already owns the camera, -EBUSY otherwise
@@ -213,25 +260,34 @@
 
 status_t CameraService::Client::unlock()
 {
+    int callingPid = getCallingPid();
+    LOGD("unlock from pid %d (mClientPid %d)", callingPid, mClientPid);    
     Mutex::Autolock _l(mLock);
     // allow anyone to use camera
-    LOGV("unlock (%p)", getCameraClient()->asBinder().get());
     status_t result = checkPid();
-    if (result == NO_ERROR) mClientPid = 0;
+    if (result == NO_ERROR) {
+        mClientPid = 0;
+        LOGD("clear mCameraClient (pid %d)", callingPid);
+        // we need to remove the reference so that when app goes
+        // away, the reference count goes to 0.
+        mCameraClient.clear();
+    }
     return result;
 }
 
 status_t CameraService::Client::connect(const sp<ICameraClient>& client)
 {
+    int callingPid = getCallingPid();
+
     // connect a new process to the camera
-    LOGV("connect (%p)", client->asBinder().get());
+    LOGD("Client::connect E (pid %d, client %p)", callingPid, client->asBinder().get());
 
     // I hate this hack, but things get really ugly when the media recorder
     // service is handing back the camera to the app. The ICameraClient
     // destructor will be called during the same IPC, making it look like
     // the remote client is trying to disconnect. This hack temporarily
     // sets the mClientPid to an invalid pid to prevent the hardware from
-    //  being torn down.
+    // being torn down.
     {
 
         // hold a reference to the old client or we will deadlock if the client is
@@ -239,25 +295,30 @@
         sp<ICameraClient> oldClient;
         {
             Mutex::Autolock _l(mLock);
-            if (mClientPid != 0) {
-                LOGW("Tried to connect to locked camera");
+            if (mClientPid != 0 && checkPid() != NO_ERROR) {
+                LOGW("Tried to connect to locked camera (old pid %d, new pid %d)",
+                        mClientPid, callingPid);
                 return -EBUSY;
             }
             oldClient = mCameraClient;
 
             // did the client actually change?
-            if (client->asBinder() == mCameraClient->asBinder()) return NO_ERROR;
+            if (client->asBinder() == mCameraClient->asBinder()) {
+                LOGD("Connect to the same client");
+                return NO_ERROR;
+            }
 
             mCameraClient = client;
             mClientPid = -1;
             mPreviewCallbackFlag = FRAME_CALLBACK_FLAG_NOOP;
-            LOGV("connect new process (%d) to existing camera client", mClientPid);
+            LOGD("Connect to the new client (pid %d, client %p)",
+                callingPid, mCameraClient->asBinder().get());
         }
 
     }
     // the old client destructor is called when oldClient goes out of scope
     // now we set the new PID to lock the interface again
-    mClientPid = IPCThreadState::self()->getCallingPid();
+    mClientPid = callingPid;
 
     return NO_ERROR;
 }
@@ -274,8 +335,11 @@
 
 CameraService::Client::~Client()
 {
+    int callingPid = getCallingPid();
+
     // tear down client
-    LOGD("Client (%p)  E destructor", getCameraClient()->asBinder().get());
+    LOGD("Client::~Client E (pid %d, client %p)",
+            callingPid, getCameraClient()->asBinder().get());
     if (mSurface != 0 && !mUseOverlay) {
 #if HAVE_ANDROID_OS
         pthread_t thr;
@@ -301,49 +365,59 @@
     }
 
     // make sure we tear down the hardware
-    mClientPid = IPCThreadState::self()->getCallingPid();
+    mClientPid = callingPid;
     disconnect();
-    LOGD("Client X destructor");
+    LOGD("Client::~Client X (pid %d)", mClientPid);
 }
 
 void CameraService::Client::disconnect()
 {
-    LOGD("Client (%p) E disconnect from (%d)",
-            getCameraClient()->asBinder().get(),
-            IPCThreadState::self()->getCallingPid());
+    int callingPid = getCallingPid();
+
+    LOGD("Client::disconnect() E (pid %d client %p)",
+            callingPid, getCameraClient()->asBinder().get());
+
     Mutex::Autolock lock(mLock);
     if (mClientPid <= 0) {
-        LOGV("camera is unlocked, don't tear down hardware");
+        LOGD("camera is unlocked (mClientPid = %d), don't tear down hardware", mClientPid);
         return;
     }
     if (checkPid() != NO_ERROR) {
-        LOGV("Different client - don't disconnect");
+        LOGD("Different client - don't disconnect");
         return;
     }
 
-    mCameraService->removeClient(mCameraClient);
-    if (mHardware != 0) {
-        LOGV("hardware teardown");
-        // Before destroying mHardware, we must make sure it's in the
-        // idle state.
-        mHardware->stopPreview();
-        // Cancel all picture callbacks.
-        mHardware->cancelPicture(true, true, true);
-        // Release the hardware resources.
-        mHardware->release();
-    }
+    // Make sure disconnect() is done once and once only, whether it is called
+    // from the user directly, or called by the destructor.
+    if (mHardware == 0) return;
+
+    LOGD("hardware teardown");
+    // Before destroying mHardware, we must make sure it's in the
+    // idle state.
+    mHardware->stopPreview();
+    // Cancel all picture callbacks.
+    mHardware->cancelPicture(true, true, true);
+    // Release the hardware resources.
+    mHardware->release();
     mHardware.clear();
-    LOGD("Client X disconnect");
+
+    mCameraService->removeClient(mCameraClient);
+    mCameraService->decUsers();
+
+    LOGD("Client::disconnect() X (pid %d)", callingPid);
 }
 
 // pass the buffered ISurface to the camera service
 status_t CameraService::Client::setPreviewDisplay(const sp<ISurface>& surface)
 {
-    LOGD("setPreviewDisplay(%p)", surface.get());
+    LOGD("setPreviewDisplay(%p) (pid %d)",
+         ((surface == NULL) ? NULL : surface.get()), getCallingPid());
     Mutex::Autolock lock(mLock);
     status_t result = checkPid();
     if (result != NO_ERROR) return result;
+
     Mutex::Autolock surfaceLock(mSurfaceLock);
+    result = NO_ERROR;
     // asBinder() is safe on NULL (returns NULL)
     if (surface->asBinder() != mSurface->asBinder()) {
         if (mSurface != 0 && !mUseOverlay) {
@@ -351,24 +425,35 @@
             mSurface->unregisterBuffers();
         }
         mSurface = surface;
+        // If preview has been already started, set overlay or register preview
+        // buffers now.
+        if (mHardware->previewEnabled()) {
+            if (mUseOverlay) {
+                result = setOverlay();
+            } else if (mSurface != 0) {
+                result = registerPreviewBuffers();
+            }
+        }
     }
-    return NO_ERROR;
+    return result;
 }
 
 // set the preview callback flag to affect how the received frames from
 // preview are handled.
 void CameraService::Client::setPreviewCallbackFlag(int callback_flag)
 {
-    LOGV("setPreviewCallbackFlag");
+    LOGV("setPreviewCallbackFlag (pid %d)", getCallingPid());
     Mutex::Autolock lock(mLock);
     if (checkPid() != NO_ERROR) return;
     mPreviewCallbackFlag = callback_flag;
 }
 
-// start preview mode, must call setPreviewDisplay first
+// start preview mode
 status_t CameraService::Client::startCameraMode(camera_mode mode)
 {
-    LOGD("startCameraMode(%d)", mode);
+    int callingPid = getCallingPid();
+
+    LOGD("startCameraMode(%d) (pid %d)", mode, callingPid);
 
     /* we cannot call into mHardware with mLock held because
      * mHardware has callbacks onto us which acquire this lock
@@ -383,23 +468,25 @@
         return INVALID_OPERATION;
     }
 
-    if (mSurface == 0) {
-        LOGE("setPreviewDisplay must be called before startCameraMode!");
-        return INVALID_OPERATION;
-    }
-
     switch(mode) {
     case CAMERA_RECORDING_MODE:
+        if (mSurface == 0) {
+            LOGE("setPreviewDisplay must be called before startRecordingMode.");
+            return INVALID_OPERATION;
+        }
         return startRecordingMode();
 
     default: // CAMERA_PREVIEW_MODE
+        if (mSurface == 0) {
+            LOGD("mSurface is not set yet.");
+        }
         return startPreviewMode();
     }
 }
 
 status_t CameraService::Client::startRecordingMode()
 {
-    LOGV("startRecordingMode");
+    LOGD("startRecordingMode (pid %d)", getCallingPid());
 
     status_t ret = UNKNOWN_ERROR;
 
@@ -417,17 +504,72 @@
     }
 
     // start recording mode
-    ret = mHardware->startRecording(recordingCallback,
-                                    mCameraService.get());
+    ret = mHardware->startRecording(recordingCallback, mCameraService.get());
     if (ret != NO_ERROR) {
         LOGE("mHardware->startRecording() failed with status %d", ret);
     }
     return ret;
 }
 
+status_t CameraService::Client::setOverlay()
+{
+    LOGD("setOverlay");
+    int w, h;
+    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;
+    }
+
+    status_t ret = NO_ERROR;
+    if (mSurface != 0) {
+        sp<OverlayRef> ref = mSurface->createOverlay(w, h, fmt);
+        ret = mHardware->setOverlay(new Overlay(ref));
+    } else {
+        ret = mHardware->setOverlay(NULL);
+    }
+    if (ret != NO_ERROR) {
+        LOGE("mHardware->setOverlay() failed with status %d\n", ret);
+    }
+    return ret;
+}
+
+status_t CameraService::Client::registerPreviewBuffers()
+{
+    int w, h;
+    CameraParameters params(mHardware->getParameters());
+    params.getPreviewSize(&w, &h);
+
+    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,
+                                 mHardware->getPreviewHeap());
+
+    status_t ret = mSurface->registerBuffers(buffers);
+    if (ret != NO_ERROR) {
+        LOGE("registerBuffers failed with status %d", ret);
+    }
+    return ret;
+}
+
 status_t CameraService::Client::startPreviewMode()
 {
-    LOGV("startPreviewMode");
+    LOGD("startPreviewMode (pid %d)", getCallingPid());
 
     // if preview has been enabled, nothing needs to be done
     if (mHardware->previewEnabled()) {
@@ -438,55 +580,24 @@
 #if DEBUG_DUMP_PREVIEW_FRAME_TO_FILE
     debug_frame_cnt = 0;
 #endif
-    status_t ret = UNKNOWN_ERROR;
-    int w, h;
-    CameraParameters params(mHardware->getParameters());
-    params.getPreviewSize(&w, &h);
+    status_t ret = NO_ERROR;
 
     if (mUseOverlay) {
-        const char *format = params.getPreviewFormat();
-        int fmt;
-        LOGD("Use Overlays");
-        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 preview display has been set, set overlay now.
+        if (mSurface != 0) {
+            ret = setOverlay();
         }
-        sp<OverlayRef> ref = mSurface->createOverlay(w, h, fmt);
-        ret = mHardware->setOverlay(new Overlay(ref));
-        if (ret != NO_ERROR) {
-            LOGE("mHardware->setOverlay() failed with status %d\n", ret);
-            return ret;
-        }
+        if (ret != NO_ERROR) return ret;
         ret = mHardware->startPreview(NULL, mCameraService.get());
-        if (ret != NO_ERROR)
-            LOGE("mHardware->startPreview() failed with status %d\n", ret);
-
     } else {
         ret = mHardware->startPreview(previewCallback,
                                       mCameraService.get());
-        if (ret == NO_ERROR) {
-
-            mSurface->unregisterBuffers();
-
-            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,
-                                         mHardware->getPreviewHeap());
-
-            mSurface->registerBuffers(buffers);
-        } else {
-          LOGE("mHardware->startPreview() failed with status %d", ret);
+        if (ret != NO_ERROR) return ret;
+        // If preview display has been set, register preview buffers now.
+        if (mSurface != 0) {
+           // Unregister here because the surface registered with raw heap.
+           mSurface->unregisterBuffers();
+           ret = registerPreviewBuffers();
         }
     }
     return ret;
@@ -494,11 +605,15 @@
 
 status_t CameraService::Client::startPreview()
 {
+    LOGD("startPreview (pid %d)", getCallingPid());
+    
     return startCameraMode(CAMERA_PREVIEW_MODE);
 }
 
 status_t CameraService::Client::startRecording()
 {
+    LOGD("startRecording (pid %d)", getCallingPid());
+
     if (mMediaPlayerBeep.get() != NULL) {
         mMediaPlayerBeep->seekTo(0);
         mMediaPlayerBeep->start();
@@ -509,7 +624,7 @@
 // stop preview mode
 void CameraService::Client::stopPreview()
 {
-    LOGD("stopPreview()");
+    LOGD("stopPreview (pid %d)", getCallingPid());
 
     Mutex::Autolock lock(mLock);
     if (checkPid() != NO_ERROR) return;
@@ -531,7 +646,7 @@
 // stop recording mode
 void CameraService::Client::stopRecording()
 {
-    LOGV("stopRecording()");
+    LOGD("stopRecording (pid %d)", getCallingPid());
 
     Mutex::Autolock lock(mLock);
     if (checkPid() != NO_ERROR) return;
@@ -546,15 +661,13 @@
         mMediaPlayerBeep->start();
     }
     mHardware->stopRecording();
-    LOGV("stopRecording(), hardware stopped OK");
+    LOGD("stopRecording(), hardware stopped OK");
     mPreviewBuffer.clear();
 }
 
 // release a recording frame
 void CameraService::Client::releaseRecordingFrame(const sp<IMemory>& mem)
 {
-    LOGV("releaseRecordingFrame()");
-
     Mutex::Autolock lock(mLock);
     if (checkPid() != NO_ERROR) return;
 
@@ -586,7 +699,7 @@
     sp<Client> client = 0;
     CameraService *service = static_cast<CameraService*>(user);
     if (service != NULL) {
-        Mutex::Autolock ourLock(service->mLock);
+        Mutex::Autolock ourLock(service->mServiceLock);
         if (service->mClient != 0) {
             client = service->mClient.promote();
             if (client == 0) {
@@ -684,7 +797,7 @@
 }
 
 // recording callback
-void CameraService::Client::recordingCallback(const sp<IMemory>& mem, void* user)
+void CameraService::Client::recordingCallback(nsecs_t timestamp, const sp<IMemory>& mem, void* user)
 {
     LOGV("recordingCallback");
     sp<Client> client = getClientFromCookie(user);
@@ -692,13 +805,13 @@
         return;
     }
     // The strong pointer guarantees the client will exist, but no lock is held.
-    client->postRecordingFrame(mem);
+    client->postRecordingFrame(timestamp, mem);
 }
 
 // take a picture - image is returned in callback
 status_t CameraService::Client::autoFocus()
 {
-    LOGV("autoFocus");
+    LOGD("autoFocus (pid %d)", getCallingPid());
 
     Mutex::Autolock lock(mLock);
     status_t result = checkPid();
@@ -716,7 +829,7 @@
 // take a picture - image is returned in callback
 status_t CameraService::Client::takePicture()
 {
-    LOGD("takePicture");
+    LOGD("takePicture (pid %d)", getCallingPid());
 
     Mutex::Autolock lock(mLock);
     status_t result = checkPid();
@@ -894,8 +1007,6 @@
 // get preview/capture parameters - key/value pairs
 String8 CameraService::Client::getParameters() const
 {
-    LOGD("getParameters");
-
     Mutex::Autolock lock(mLock);
 
     if (mHardware == 0) {
@@ -903,30 +1014,33 @@
         return String8();
     }
 
-    return mHardware->getParameters().flatten();
+    String8 params(mHardware->getParameters().flatten());
+    LOGD("getParameters(%s)", params.string());
+    return params;
 }
 
 void CameraService::Client::postAutoFocus(bool focused)
 {
     LOGV("postAutoFocus");
-    mCameraClient->autoFocusCallback(focused);
+    mCameraClient->notifyCallback(CAMERA_MSG_FOCUS, (int32_t)focused, 0);
 }
 
 void CameraService::Client::postShutter()
 {
-    mCameraClient->shutterCallback();
+    LOGD("postShutter");
+    mCameraClient->notifyCallback(CAMERA_MSG_SHUTTER, 0, 0);
 }
 
 void CameraService::Client::postRaw(const sp<IMemory>& mem)
 {
     LOGD("postRaw");
-    mCameraClient->rawCallback(mem);
+    mCameraClient->dataCallback(CAMERA_MSG_RAW_IMAGE, mem);
 }
 
 void CameraService::Client::postJpeg(const sp<IMemory>& mem)
 {
     LOGD("postJpeg");
-    mCameraClient->jpegCallback(mem);
+    mCameraClient->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mem);
 }
 
 void CameraService::Client::copyFrameAndPostCopiedFrame(sp<IMemoryHeap> heap, size_t offset, size_t size)
@@ -954,17 +1068,17 @@
         LOGE("failed to allocate space for frame callback");
         return;
     }
-    mCameraClient->previewCallback(frame);
+    mCameraClient->dataCallback(CAMERA_MSG_PREVIEW_FRAME, frame);
 }
 
-void CameraService::Client::postRecordingFrame(const sp<IMemory>& 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->recordingCallback(frame);
+    mCameraClient->dataCallbackTimestamp(timestamp, CAMERA_MSG_VIDEO_FRAME, frame);
 }
 
 void CameraService::Client::postPreviewFrame(const sp<IMemory>& mem)
@@ -998,7 +1112,7 @@
         copyFrameAndPostCopiedFrame(heap, offset, size);
     } else {
         LOGV("frame is directly sent out without copying");
-        mCameraClient->previewCallback(mem);
+        mCameraClient->dataCallback(CAMERA_MSG_PREVIEW_FRAME, mem);
     }
 
     // Is this is one-shot only?
@@ -1012,7 +1126,7 @@
 
 void CameraService::Client::postError(status_t error)
 {
-    mCameraClient->errorCallback(error);
+    mCameraClient->notifyCallback(CAMERA_MSG_ERROR, error, 0);
 }
 
 status_t CameraService::dump(int fd, const Vector<String16>& args)
@@ -1023,12 +1137,12 @@
     if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
         snprintf(buffer, SIZE, "Permission Denial: "
                 "can't dump CameraService from pid=%d, uid=%d\n",
-                IPCThreadState::self()->getCallingPid(),
+                getCallingPid(),
                 IPCThreadState::self()->getCallingUid());
         result.append(buffer);
         write(fd, result.string(), result.size());
     } else {
-        AutoMutex lock(&mLock);
+        AutoMutex lock(&mServiceLock);
         if (mClient != 0) {
             sp<Client> currentClient = mClient.promote();
             sprintf(buffer, "Client (%p) PID: %d\n",
@@ -1046,8 +1160,6 @@
 }
 
 
-#if DEBUG_HEAP_LEAKS
-
 #define CHECK_INTERFACE(interface, data, reply) \
         do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \
             LOGW("Call incorrectly routed to " #interface); \
@@ -1079,6 +1191,7 @@
 
     status_t err = BnCameraService::onTransact(code, data, reply, flags);
 
+#if DEBUG_HEAP_LEAKS
     LOGD("+++ onTransact err %d code %d", err, code);
 
     if (err == UNKNOWN_TRANSACTION || err == PERMISSION_DENIED) {
@@ -1114,9 +1227,9 @@
             break;
         }
     }
+#endif // DEBUG_HEAP_LEAKS
+
     return err;
 }
 
-#endif // DEBUG_HEAP_LEAKS
-
 }; // namespace android
diff --git a/camera/libcameraservice/CameraService.h b/camera/libcameraservice/CameraService.h
index 6752f26..ea93789 100644
--- a/camera/libcameraservice/CameraService.h
+++ b/camera/libcameraservice/CameraService.h
@@ -58,10 +58,8 @@
 
             void            removeClient(const sp<ICameraClient>& cameraClient);
 
-#if DEBUG_HEAP_LEAKS
     virtual status_t onTransact(
         uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);
-#endif
 
 private:
 
@@ -134,7 +132,7 @@
 
                     status_t    checkPid();
 
-        static      void        recordingCallback(const sp<IMemory>& mem, void* user);
+        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);
@@ -146,7 +144,7 @@
                     void        postRaw(const sp<IMemory>& mem);
                     void        postJpeg(const sp<IMemory>& mem);
                     void        postPreviewFrame(const sp<IMemory>& mem);
-                    void        postRecordingFrame(const sp<IMemory>& frame);
+                    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);
@@ -159,6 +157,8 @@
         status_t                startCameraMode(camera_mode mode);
         status_t                startPreviewMode();
         status_t                startRecordingMode();
+        status_t                setOverlay();
+        status_t                registerPreviewBuffers();
 
         // Ensures atomicity among the public methods
         mutable     Mutex                       mLock;
@@ -196,7 +196,12 @@
                             CameraService();
     virtual                 ~CameraService();
 
-    mutable     Mutex                       mLock;
+    // We use a count for number of clients (shoule only be 0 or 1).
+    volatile    int32_t                     mUsers;
+    virtual     void                        incUsers();
+    virtual     void                        decUsers();
+
+    mutable     Mutex                       mServiceLock;
                 wp<Client>                  mClient;
 
 #if DEBUG_HEAP_LEAKS
diff --git a/camera/libcameraservice/FakeCamera.cpp b/camera/libcameraservice/FakeCamera.cpp
index 3592eab..3daf47d 100644
--- a/camera/libcameraservice/FakeCamera.cpp
+++ b/camera/libcameraservice/FakeCamera.cpp
@@ -1,12 +1,39 @@
+/*
+**
+** Copyright 2008, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License"); 
+** you may not use this file except in compliance with the License. 
+** You may obtain a copy of the License at 
+**
+**     http://www.apache.org/licenses/LICENSE-2.0 
+**
+** Unless required by applicable law or agreed to in writing, software 
+** distributed under the License is distributed on an "AS IS" BASIS, 
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+** See the License for the specific language governing permissions and 
+** limitations under the License.
+*/
+
 #define LOG_TAG "FakeCamera"
 #include <utils/Log.h>
 
 #include <string.h>
 #include <stdlib.h>
+#include <utils/String8.h>
+
 #include "FakeCamera.h"
 
+
 namespace android {
 
+// TODO: All this rgb to yuv should probably be in a util class.
+
+// TODO: I think something is wrong in this class because the shadow is kBlue
+// and the square color should alternate between kRed and kGreen. However on the
+// emulator screen these are all shades of gray. Y seems ok but the U and V are
+// probably not.
+
 static int tables_initialized = 0;
 uint8_t *gYTable, *gCbTable, *gCrTable;
 
@@ -389,7 +416,7 @@
 }
 
 
-status_t FakeCamera::dump(int fd, const Vector<String16>& args)
+void FakeCamera::dump(int fd) const
 {
     const size_t SIZE = 256;
     char buffer[SIZE];
@@ -397,7 +424,6 @@
     snprintf(buffer, 255, " width x height (%d x %d), counter (%d), check x-y coordinate(%d, %d)\n", mWidth, mHeight, mCounter, mCheckX, mCheckY);
     result.append(buffer);
     ::write(fd, result.string(), result.size());
-    return NO_ERROR;
 }
 
 
diff --git a/camera/libcameraservice/FakeCamera.h b/camera/libcameraservice/FakeCamera.h
index 77c994c..f7f8803 100644
--- a/camera/libcameraservice/FakeCamera.h
+++ b/camera/libcameraservice/FakeCamera.h
@@ -18,21 +18,37 @@
 #ifndef ANDROID_HARDWARE_FAKECAMERA_H
 #define ANDROID_HARDWARE_FAKECAMERA_H
 
-#include <ui/CameraHardwareInterface.h>
+#include <sys/types.h>
+#include <stdint.h>
 
 namespace android {
 
+/*
+ * FakeCamera is used in the CameraHardwareStub to provide a fake video feed
+ * when the system does not have a camera in hardware.
+ * The fake video is a moving black and white checkerboard background with a
+ * bouncing gray square in the foreground.
+ * This class is not thread-safe.
+ *
+ * TODO: Since the major methods provides a raw/uncompressed video feed, rename
+ * this class to RawVideoSource.
+ */
+
 class FakeCamera {
 public:
     FakeCamera(int width, int height);
     ~FakeCamera();
 
     void setSize(int width, int height);
-    void getNextFrameAsRgb565(uint16_t *buffer);
     void getNextFrameAsYuv422(uint8_t *buffer);
-    status_t dump(int fd, const Vector<String16>& args);
+    // Write to the fd a string representing the current state.
+    void dump(int fd) const;
 
 private:
+    // TODO: remove the uint16_t buffer param everywhere since it is a field of
+    // this class.
+    void getNextFrameAsRgb565(uint16_t *buffer);
+
     void drawSquare(uint16_t *buffer, int x, int y, int size, int color, int shadow);
     void drawCheckerboard(uint16_t *buffer, int size);
 
diff --git a/cmds/keystore/Android.mk b/cmds/keystore/Android.mk
new file mode 100644
index 0000000..3daf44e
--- /dev/null
+++ b/cmds/keystore/Android.mk
@@ -0,0 +1,22 @@
+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_MODULE:= keystore
+
+include $(BUILD_EXECUTABLE)
+
+endif # !simulator))
diff --git a/cmds/keystore/certtool.h b/cmds/keystore/certtool.h
new file mode 100644
index 0000000..aefad66
--- /dev/null
+++ b/cmds/keystore/certtool.h
@@ -0,0 +1,91 @@
+/*
+**
+** 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
new file mode 100644
index 0000000..a18114e
--- /dev/null
+++ b/cmds/keystore/common.h
@@ -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.
+*/
+
+#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
new file mode 100644
index 0000000..9a1f845
--- /dev/null
+++ b/cmds/keystore/keymgmt.c
@@ -0,0 +1,426 @@
+/*
+** 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
new file mode 100644
index 0000000..0e928db
--- /dev/null
+++ b/cmds/keystore/keymgmt.h
@@ -0,0 +1,82 @@
+/*
+** 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_get.h b/cmds/keystore/keystore_get.h
new file mode 100644
index 0000000..7665e81
--- /dev/null
+++ b/cmds/keystore/keystore_get.h
@@ -0,0 +1,53 @@
+/*
+**
+** 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 __KEYSTORE_GET_H__
+#define __KEYSTORE_GET_H__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "certtool.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)
+{
+    char buffer[MAX_KEY_VALUE_LENGTH];
+    char *value;
+    int length;
+
+    if (get_cert(key, (unsigned char *)buffer, &length) != 0) {
+        return NULL;
+    }
+    value = malloc(length + 1);
+    if (!value) {
+        return NULL;
+    }
+    memcpy(value, buffer, length);
+    value[length] = 0;
+    if (size) {
+        *size = length;
+    }
+    return value;
+}
+
+#endif
diff --git a/cmds/keystore/netkeystore.c b/cmds/keystore/netkeystore.c
new file mode 100644
index 0000000..637e0d8
--- /dev/null
+++ b/cmds/keystore/netkeystore.c
@@ -0,0 +1,411 @@
+/*
+** 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
new file mode 100644
index 0000000..a87a667
--- /dev/null
+++ b/cmds/keystore/netkeystore.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 __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
new file mode 100644
index 0000000..33541cc
--- /dev/null
+++ b/cmds/keystore/tests/Android.mk
@@ -0,0 +1,28 @@
+# 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
new file mode 100644
index 0000000..e7e686b
--- /dev/null
+++ b/cmds/keystore/tests/netkeystore_test.c
@@ -0,0 +1,249 @@
+/*
+ * 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/main_runtime.cpp b/cmds/runtime/main_runtime.cpp
index 1531a9e..476f38a 100644
--- a/cmds/runtime/main_runtime.cpp
+++ b/cmds/runtime/main_runtime.cpp
@@ -45,9 +45,9 @@
     "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,3001,3002,3003",
     /* CAP_SYS_TTY_CONFIG & CAP_SYS_RESOURCE & CAP_NET_BROADCAST &
      * CAP_NET_ADMIN & CAP_NET_RAW & CAP_NET_BIND_SERVICE  & CAP_KILL &
-     * CAP_SYS_BOOT
+     * CAP_SYS_BOOT CAP_SYS_NICE
      */
-    "--capabilities=88161312,88161312",
+    "--capabilities=96549920,96549920",
     "--runtime-init",
     "--nice-name=system_server",
     "com.android.server.SystemServer"
diff --git a/include/private/opengles/gl_context.h b/include/private/opengles/gl_context.h
index 0c7ad46..e32e332 100644
--- a/include/private/opengles/gl_context.h
+++ b/include/private/opengles/gl_context.h
@@ -285,6 +285,7 @@
     vec4_t      normalizedObjPosition;
     vec4_t      spotDir;
     vec4_t      normalizedSpotDir;
+    vec4_t      objViewer;
     GLfixed     spotExp;
     GLfixed     spotCutoff;
     GLfixed     spotCutoffCosine;
@@ -456,7 +457,7 @@
     void validate();
     matrixf_t& top() { return stack[depth]; }
     const matrixf_t& top() const { return stack[depth]; }
-    const uint32_t top_ops() const { return ops[depth]; }
+    uint32_t top_ops() const { return ops[depth]; }
     inline bool isRigidBody() const {
         return !(ops[depth] & ~(OP_TRANSLATE|OP_UNIFORM_SCALE|OP_ROTATE));
     }
diff --git a/include/tts/TtsEngine.h b/include/tts/TtsEngine.h
new file mode 100644
index 0000000..ed084ca
--- /dev/null
+++ b/include/tts/TtsEngine.h
@@ -0,0 +1,239 @@
+/*
+ * Copyright (C) 2009 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <media/AudioSystem.h>
+
+// This header defines the interface used by the Android platform
+// to access Text-To-Speech functionality in shared libraries that implement
+// speech synthesis and the management of resources associated with the
+// synthesis.
+// An example of the implementation of this interface can be found in
+// FIXME: add path+name to implementation of default TTS engine
+// Libraries implementing this interface are used in:
+//  frameworks/base/tts/jni/android_tts_SpeechSynthesis.cpp
+
+namespace android {
+
+enum tts_synth_status {
+    TTS_SYNTH_DONE              = 0,
+    TTS_SYNTH_PENDING           = 1
+};
+
+enum tts_callback_status {
+    TTS_CALLBACK_HALT           = 0,
+    TTS_CALLBACK_CONTINUE       = 1
+};
+
+// The callback is used by the implementation of this interface to notify its
+// client, the Android TTS service, that the last requested synthesis has been
+// completed. // TODO reword
+// The callback for synthesis completed takes:
+// @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]    int           - The number of channels
+// @param [inout] int8_t *&     - A buffer of audio data only valid during the
+//                                execution of the callback
+// @param [inout] size_t  &     - The size of the buffer
+// @param [in] tts_synth_status - indicate whether the synthesis is done, or
+//                                 if more data is to be synthesized.
+// @return TTS_CALLBACK_HALT to indicate the synthesis must stop,
+//         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);
+
+class TtsEngine;
+extern "C" TtsEngine* getTtsEngine();
+
+enum tts_result {
+    TTS_SUCCESS                 = 0,
+    TTS_FAILURE                 = -1,
+    TTS_FEATURE_UNSUPPORTED     = -2,
+    TTS_VALUE_INVALID           = -3,
+    TTS_PROPERTY_UNSUPPORTED    = -4,
+    TTS_PROPERTY_SIZE_TOO_SMALL = -5,
+    TTS_MISSING_RESOURCES       = -6
+};
+
+enum tts_support_result {
+    TTS_LANG_COUNTRY_VAR_AVAILABLE = 2,
+    TTS_LANG_COUNTRY_AVAILABLE = 1,
+    TTS_LANG_AVAILABLE = 0,
+    TTS_LANG_MISSING_DATA = -1,
+    TTS_LANG_NOT_SUPPORTED = -2
+};
+
+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
+    virtual tts_result init(synthDoneCB_t synthDoneCBPtr);
+
+    // Shut down the TTS engine and releases all associated resources.
+    // @return TTS_SUCCESS, or TTS_FAILURE
+    virtual tts_result shutdown();
+
+    // Interrupt synthesis and flushes any synthesized data that hasn't been
+    // output yet. This will block until callbacks underway are completed.
+    // @return TTS_SUCCESS, or TTS_FAILURE
+    virtual tts_result stop();
+
+    // Returns the level of support for the language, country and variant.
+    // @return TTS_LANG_COUNTRY_VAR_AVAILABLE if the language, country and variant are supported,
+    //            and the corresponding resources are correctly installed
+    //         TTS_LANG_COUNTRY_AVAILABLE if the language and country are supported and the
+    //             corresponding resources are correctly installed, but there is no match for
+    //             the specified variant
+    //         TTS_LANG_AVAILABLE if the language is supported and the
+    //             corresponding resources are correctly installed, but there is no match for
+    //             the specified country and variant
+    //         TTS_LANG_MISSING_DATA if the required resources to provide any level of support
+    //             for the language are not correctly installed
+    //         TTS_LANG_NOT_SUPPORTED if the language is not supported by the TTS engine.
+    virtual tts_support_result isLanguageAvailable(const char *lang, const char *country,
+            const char *variant);
+
+    // Load the resources associated with the specified language. The loaded
+    // language will only be used once a call to setLanguage() with the same
+    // language value is issued. Language and country values are coded according to the ISO three
+    // letter codes for languages and countries, as can be retrieved from a java.util.Locale
+    // instance. The variant value is encoded as the variant string retrieved from a
+    // java.util.Locale instance built with that variant data.
+    // @param lang pointer to the ISO three letter code for the language
+    // @param country pointer to the ISO three letter code for the country
+    // @param variant pointer to the variant code
+    // @return TTS_SUCCESS, or TTS_FAILURE
+    virtual tts_result loadLanguage(const char *lang, const char *country, const char *variant);
+    
+    // Load the resources associated with the specified language, country and Locale variant.
+    // The loaded language will only be used once a call to setLanguageFromLocale() with the same
+    // language value is issued. Language and country values are coded according to the ISO three
+    // letter codes for languages and countries, as can be retrieved from a java.util.Locale
+    // instance. The variant value is encoded as the variant string retrieved from a
+    // java.util.Locale instance built with that variant data.
+    // @param lang pointer to the ISO three letter code for the language
+    // @param country pointer to the ISO three letter code for the country
+    // @param variant pointer to the variant code
+    // @return TTS_SUCCESS, or TTS_FAILURE
+    virtual tts_result setLanguage(const char *lang, const char *country, const char *variant);
+
+    // Retrieve the currently set language, country and variant, or empty strings if none of
+    // parameters have been set. Language and country are represented by their 3-letter ISO code
+    // @param[out]   pointer to the retrieved 3-letter code language value
+    // @param[out]   pointer to the retrieved 3-letter code country value
+    // @param[out]   pointer to the retrieved variant value
+    // @return TTS_SUCCESS, or TTS_FAILURE
+    virtual tts_result getLanguage(char *language, char *country, char *variant);
+
+    // Notifies the engine what audio parameters should be used for the synthesis.
+    // This is meant to be used as a hint, the engine implementation will set the output values
+    // to those of the synthesis format, based on a given hint.
+    // @param[inout] encoding in: the desired audio sample format
+    //                         out: the format used by the TTS engine
+    // @param[inout] rate in: the desired audio sample rate
+    //                         out: the sample rate used by the TTS engine
+    // @param[inout] channels in: the desired number of audio channels
+    //                         out: the number of channels used by the TTS engine
+    // @return TTS_SUCCESS, or TTS_FAILURE
+    virtual tts_result setAudioFormat(AudioSystem::audio_format& encoding, uint32_t& rate,
+            int& channels);
+
+    // Set a property for the the TTS engine
+    // "size" is the maximum size of "value" for properties "property"
+    // @param property pointer to the property name
+    // @param value    pointer to the property value
+    // @param size     maximum size required to store this type of property
+    // @return         TTS_PROPERTY_UNSUPPORTED, or TTS_SUCCESS, or TTS_FAILURE,
+    //                  or TTS_VALUE_INVALID
+    virtual tts_result setProperty(const char *property, const char *value,
+            const size_t size);
+
+    // Retrieve a property from the TTS engine
+    // @param        property pointer to the property name
+    // @param[out]   value    pointer to the retrieved language value
+    // @param[inout] iosize   in: stores the size available to store the
+    //                          property value.
+    //                        out: stores the size required to hold the language
+    //                          value if getLanguage() returned
+    //                          TTS_PROPERTY_SIZE_TOO_SMALL, unchanged otherwise
+    // @return TTS_PROPERTY_UNSUPPORTED, or TTS_SUCCESS,
+    //         or TTS_PROPERTY_SIZE_TOO_SMALL
+    virtual tts_result getProperty(const char *property, char *value,
+            size_t *iosize);
+
+    // Synthesize the text.
+    // As the synthesis is performed, the engine invokes the callback to notify
+    // the TTS framework that it has filled the given buffer, and indicates how
+    // many bytes it wrote. The callback is called repeatedly until the engine
+    // has generated all the audio data corresponding to the text.
+    // Note about the format of the input: the text parameter may use the
+    // following elements
+    // and their respective attributes as defined in the SSML 1.0 specification:
+    //    * lang
+    //    * say-as:
+    //          o interpret-as
+    //    * phoneme
+    //    * voice:
+    //          o gender,
+    //          o age,
+    //          o variant,
+    //          o name
+    //    * emphasis
+    //    * break:
+    //          o strength,
+    //          o time
+    //    * prosody:
+    //          o pitch,
+    //          o contour,
+    //          o range,
+    //          o rate,
+    //          o duration,
+    //          o volume
+    //    * mark
+    // Differences between this text format and SSML are:
+    //    * full SSML documents are not supported
+    //    * namespaces are not supported
+    // Text is coded in UTF-8.
+    // @param text      the UTF-8 text to synthesize
+    // @param userdata  pointer to be returned when the call is invoked
+    // @param buffer    the location where the synthesized data must be written
+    // @param bufferSize the number of bytes that can be written in buffer
+    // @return          TTS_SUCCESS or TTS_FAILURE
+    virtual tts_result synthesizeText(const char *text, int8_t *buffer,
+            size_t bufferSize, void *userdata);
+
+    // Synthesize IPA text.
+    // As the synthesis is performed, the engine invokes the callback to notify
+    // the TTS framework that it has filled the given buffer, and indicates how
+    // many bytes it wrote. The callback is called repeatedly until the engine
+    // has generated all the audio data corresponding to the IPA data.
+    // @param ipa      the IPA data to synthesize
+    // @param userdata  pointer to be returned when the call is invoked
+    // @param buffer    the location where the synthesized data must be written
+    // @param bufferSize the number of bytes that can be written in buffer
+    // @return TTS_FEATURE_UNSUPPORTED if IPA is not supported,
+    //         otherwise TTS_SUCCESS or TTS_FAILURE
+    virtual tts_result synthesizeIpa(const char *ipa, int8_t *buffer,
+            size_t bufferSize, void *userdata);
+};
+
+} // namespace android
+
diff --git a/include/ui/Camera.h b/include/ui/Camera.h
index e593fea..afb07b5 100644
--- a/include/ui/Camera.h
+++ b/include/ui/Camera.h
@@ -18,6 +18,7 @@
 #ifndef ANDROID_HARDWARE_CAMERA_H
 #define ANDROID_HARDWARE_CAMERA_H
 
+#include <utils/Timers.h>
 #include <ui/ICameraClient.h>
 
 namespace android {
@@ -63,23 +64,45 @@
 #define FRAME_CALLBACK_FLAG_CAMERA                   0x05
 #define FRAME_CALLBACK_FLAG_BARCODE_SCANNER          0x07
 
+// 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 fatal errors
+enum {
+    CAMERA_ERROR_UKNOWN  = 1,
+    CAMERA_ERROR_SERVER_DIED = 100
+};
+
 class ICameraService;
 class ICamera;
 class Surface;
 class Mutex;
 class String8;
 
-typedef void (*shutter_callback)(void *cookie);
-typedef void (*frame_callback)(const sp<IMemory>& mem, void *cookie);
-typedef void (*autofocus_callback)(bool focused, void *cookie);
-typedef void (*error_callback)(status_t err, void *cookie);
+// ref-counted object for callbacks
+class CameraListener: virtual public RefBase
+{
+public:
+    virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2) = 0;
+    virtual void postData(int32_t msgType, const sp<IMemory>& dataPtr) = 0;
+    virtual void postDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr) = 0;
+};
 
 class Camera : public BnCameraClient, public IBinder::DeathRecipient
 {
 public:
             // construct a camera client from an existing remote
-            Camera(const sp<ICamera>& camera);
-
+    static  sp<Camera>  create(const sp<ICamera>& camera);
     static  sp<Camera>  connect();
                         ~Camera();
             void        init();
@@ -128,27 +151,20 @@
             // get preview/capture parameters - key/value pairs
             String8     getParameters() const;
 
-            void        setShutterCallback(shutter_callback cb, void *cookie);
-            void        setRawCallback(frame_callback cb, void *cookie);
-            void        setJpegCallback(frame_callback cb, void *cookie);
-            void        setRecordingCallback(frame_callback cb, void *cookie);
-            void        setPreviewCallback(frame_callback cb, void *cookie, int preview_callback_flag = FRAME_CALLBACK_FLAG_NOOP);
-            void        setErrorCallback(error_callback cb, void *cookie);
-            void        setAutoFocusCallback(autofocus_callback cb, void *cookie);
+            void        setListener(const sp<CameraListener>& listener);
+            void        setPreviewCallbackFlags(int preview_callback_flag);
 
     // ICameraClient interface
-    virtual void        shutterCallback();
-    virtual void        rawCallback(const sp<IMemory>& picture);
-    virtual void        jpegCallback(const sp<IMemory>& picture);
-    virtual void        previewCallback(const sp<IMemory>& frame);
-    virtual void        errorCallback(status_t error);
-    virtual void        autoFocusCallback(bool focused);
-    virtual void        recordingCallback(const sp<IMemory>& frame);
+    virtual void        notifyCallback(int32_t msgType, int32_t ext, int32_t ext2);
+    virtual void        dataCallback(int32_t msgType, const sp<IMemory>& dataPtr);
+    virtual void        dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr);
 
     sp<ICamera>         remote();
 
 private:
                         Camera();
+                        Camera(const Camera&);
+                        Camera& operator=(const Camera);
                         virtual void binderDied(const wp<IBinder>& who);
 
             class DeathNotifier: public IBinder::DeathRecipient
@@ -168,20 +184,7 @@
             sp<ICamera>         mCamera;
             status_t            mStatus;
 
-            shutter_callback    mShutterCallback;
-            void                *mShutterCallbackCookie;
-            frame_callback      mRawCallback;
-            void                *mRawCallbackCookie;
-            frame_callback      mJpegCallback;
-            void                *mJpegCallbackCookie;
-            frame_callback      mPreviewCallback;
-            void                *mPreviewCallbackCookie;
-            frame_callback      mRecordingCallback;
-            void                *mRecordingCallbackCookie;
-            error_callback      mErrorCallback;
-            void                *mErrorCallbackCookie;
-            autofocus_callback  mAutoFocusCallback;
-            void                *mAutoFocusCallbackCookie;
+            sp<CameraListener>  mListener;
 
             friend class DeathNotifier;
 
diff --git a/include/ui/CameraHardwareInterface.h b/include/ui/CameraHardwareInterface.h
index 73036f0..822b4a8 100644
--- a/include/ui/CameraHardwareInterface.h
+++ b/include/ui/CameraHardwareInterface.h
@@ -28,7 +28,7 @@
 typedef void (*preview_callback)(const sp<IMemory>& mem, void* user);
 
 /** Callback for startRecord() */
-typedef void (*recording_callback)(const sp<IMemory>& mem, void* user);
+typedef void (*recording_callback)(nsecs_t timestamp, const sp<IMemory>& mem, void* user);
 
 /** Callback for takePicture() */
 typedef void (*shutter_callback)(void* user);
diff --git a/include/ui/ICameraClient.h b/include/ui/ICameraClient.h
index 73b951c..1001c71 100644
--- a/include/ui/ICameraClient.h
+++ b/include/ui/ICameraClient.h
@@ -21,6 +21,7 @@
 #include <utils/IInterface.h>
 #include <utils/Parcel.h>
 #include <utils/IMemory.h>
+#include <utils/Timers.h>
 
 namespace android {
 
@@ -29,14 +30,9 @@
 public:
     DECLARE_META_INTERFACE(CameraClient);
 
-    virtual void            shutterCallback() = 0;
-    virtual void            rawCallback(const sp<IMemory>& picture) = 0;
-    virtual void            jpegCallback(const sp<IMemory>& picture) = 0;
-    virtual void            previewCallback(const sp<IMemory>& frame) = 0;
-    virtual void            errorCallback(status_t error) = 0;
-    virtual void            autoFocusCallback(bool focused) = 0;
-    virtual void            recordingCallback(const sp<IMemory>& frame) = 0;
-
+    virtual void            notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2) = 0;
+    virtual void            dataCallback(int32_t msgType, const sp<IMemory>& data) = 0;
+    virtual void            dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& data) = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/include/ui/Point.h b/include/ui/Point.h
index dbbad1e..1653120 100644
--- a/include/ui/Point.h
+++ b/include/ui/Point.h
@@ -31,12 +31,9 @@
     // because we want the compiler generated versions
 
     // Default constructor doesn't initialize the Point
-    inline Point()
-    {
+    inline Point() {
     }
-
-    inline Point(int _x, int _y) : x(_x), y(_y)
-    {
+    inline Point(int x, int y) : x(x), y(y) {
     }
 
     inline bool operator == (const Point& rhs) const {
@@ -57,8 +54,8 @@
     }
 
     inline Point& operator - () {
-        x=-x;
-        y=-y;
+        x = -x;
+        y = -y;
         return *this;
     }
     
@@ -73,11 +70,13 @@
         return *this;
     }
     
-    Point operator + (const Point& rhs) const {
-        return Point(x+rhs.x, y+rhs.y);
+    const Point operator + (const Point& rhs) const {
+        const Point result(x+rhs.x, y+rhs.y);
+        return result;
     }
-    Point operator - (const Point& rhs) const {
-        return Point(x-rhs.x, y-rhs.y);
+    const Point operator - (const Point& rhs) const {
+        const Point result(x-rhs.x, y-rhs.y);
+        return result;
     }    
 };
 
diff --git a/include/ui/Rect.h b/include/ui/Rect.h
index d232847..da72944 100644
--- a/include/ui/Rect.h
+++ b/include/ui/Rect.h
@@ -33,23 +33,16 @@
     // we don't provide copy-ctor and operator= on purpose
     // because we want the compiler generated versions
 
-    inline Rect()
-    {
+    inline Rect() {
     }
-
     inline Rect(int w, int h)
-        : left(0), top(0), right(w), bottom(h)
-    {
+        : left(0), top(0), right(w), bottom(h) {
     }
-
     inline Rect(int l, int t, int r, int b)
-        : left(l), top(t), right(r), bottom(b)
-    {
+        : left(l), top(t), right(r), bottom(b) {
     }
-
     inline Rect(const Point& lt, const Point& rb) 
-        : left(lt.x), top(lt.y), right(rb.x), bottom(rb.y)
-    {
+        : left(lt.x), top(lt.y), right(rb.x), bottom(rb.y) {
     }
 
     void makeInvalid();
@@ -78,21 +71,22 @@
         return bottom-top;
     }
 
-    // returns left-top Point non-const reference, can be assigned
-    inline Point& leftTop() {
-        return reinterpret_cast<Point&>(left);
+    void setLeftTop(const Point& lt) {
+        left = lt.x;
+        top  = lt.y;
     }
-    // returns right bottom non-const reference, can be assigned
-    inline Point& rightBottom() {
-        return reinterpret_cast<Point&>(right);
+
+    void setRightBottom(const Point& rb) {
+        right = rb.x;
+        bottom  = rb.y;
     }
     
     // the following 4 functions return the 4 corners of the rect as Point
-    inline const Point& leftTop() const {
-        return reinterpret_cast<const Point&>(left);
+    Point leftTop() const {
+        return Point(left, top);
     }
-    inline const Point& rightBottom() const {
-        return reinterpret_cast<const Point&>(right);
+    Point rightBottom() const {
+        return Point(right, bottom);
     }
     Point rightTop() const {
         return Point(right, top);
@@ -133,8 +127,8 @@
     Rect& operator -= (const Point& rhs) {
         return offsetBy(-rhs.x, -rhs.y);
     }
-    Rect operator + (const Point& rhs) const;
-    Rect operator - (const Point& rhs) const;
+    const Rect operator + (const Point& rhs) const;
+    const Rect operator - (const Point& rhs) const;
 
     void translate(int dx, int dy) { // legacy, don't use.
         offsetBy(dx, dy);
diff --git a/include/utils/Asset.h b/include/utils/Asset.h
index 453a204..5908bcc 100644
--- a/include/utils/Asset.h
+++ b/include/utils/Asset.h
@@ -45,6 +45,7 @@
     virtual ~Asset(void);
 
     static int32_t getGlobalCount();
+    static String8 getAssetAllocations();
     
     /* used when opening an asset */
     typedef enum AccessMode {
@@ -110,6 +111,12 @@
     virtual int openFileDescriptor(off_t* outStart, off_t* outLength) const = 0;
     
     /*
+     * Return whether this asset's buffer is allocated in RAM (not mmapped).
+     * Note: not virtual so it is safe to call even when being destroyed.
+     */
+    virtual bool isAllocated(void) const { return false; }
+    
+    /*
      * Get a string identifying the asset's source.  This might be a full
      * path, it might be a colon-separated list of identifiers.
      *
@@ -197,6 +204,9 @@
 
     AccessMode  mAccessMode;        // how the asset was opened
     String8    mAssetSource;       // debug string
+    
+    Asset*		mNext;				// linked list.
+    Asset*		mPrev;
 };
 
 
@@ -239,6 +249,7 @@
     virtual off_t getLength(void) const { return mLength; }
     virtual off_t getRemainingLength(void) const { return mLength-mOffset; }
     virtual int openFileDescriptor(off_t* outStart, off_t* outLength) const;
+    virtual bool isAllocated(void) const { return mBuf != NULL; }
 
 private:
     off_t       mStart;         // absolute file offset of start of chunk
@@ -295,6 +306,7 @@
     virtual off_t getLength(void) const { return mUncompressedLen; }
     virtual off_t getRemainingLength(void) const { return mUncompressedLen-mOffset; }
     virtual int openFileDescriptor(off_t* outStart, off_t* outLength) const { return -1; }
+    virtual bool isAllocated(void) const { return mBuf != NULL; }
 
 private:
     off_t       mStart;         // offset to start of compressed data
diff --git a/include/utils/AssetManager.h b/include/utils/AssetManager.h
index e94c0e8..d8994e0 100644
--- a/include/utils/AssetManager.h
+++ b/include/utils/AssetManager.h
@@ -153,6 +153,18 @@
     AssetDir* openDir(const char* dirName);
 
     /*
+     * Open a directory within a particular path of the asset manager.
+     *
+     * The contents of the directory are an amalgam of vendor-specific,
+     * locale-specific, and generic assets stored loosely or in asset
+     * packages.  Depending on the cache setting and previous accesses,
+     * this call may incur significant disk overhead.
+     *
+     * To open the top-level directory, pass in "".
+     */
+    AssetDir* openNonAssetDir(void* cookie, const char* dirName);
+
+    /*
      * Get the type of a file in the asset hierarchy.  They will either
      * be "regular" or "directory".  [Currently only works for "regular".]
      *
@@ -239,6 +251,9 @@
         Asset* getResourceTableAsset();
         Asset* setResourceTableAsset(Asset* asset);
 
+        ResTable* getResourceTable();
+        ResTable* setResourceTable(ResTable* res);
+        
         bool isUpToDate();
         
     protected:
@@ -253,6 +268,7 @@
         time_t mModWhen;
 
         Asset* mResourceTableAsset;
+        ResTable* mResourceTable;
 
         static Mutex gLock;
         static DefaultKeyedVector<String8, wp<SharedZip> > gOpen;
@@ -276,8 +292,11 @@
          */
         ZipFileRO* getZip(const String8& path);
 
-        Asset* getZipResourceTable(const String8& path);
-        Asset* setZipResourceTable(const String8& path, Asset* asset);
+        Asset* getZipResourceTableAsset(const String8& path);
+        Asset* setZipResourceTableAsset(const String8& path, Asset* asset);
+
+        ResTable* getZipResourceTable(const String8& path);
+        ResTable* setZipResourceTable(const String8& path, ResTable* res);
 
         // generate path, e.g. "common/en-US-noogle.zip"
         static String8 getPathName(const char* path);
diff --git a/include/utils/BackupHelpers.h b/include/utils/BackupHelpers.h
new file mode 100644
index 0000000..b1f5045
--- /dev/null
+++ b/include/utils/BackupHelpers.h
@@ -0,0 +1,158 @@
+/*
+ * 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 _UTILS_BACKUP_HELPERS_H
+#define _UTILS_BACKUP_HELPERS_H
+
+#include <utils/Errors.h>
+#include <utils/String8.h>
+#include <utils/KeyedVector.h>
+
+namespace android {
+
+enum {
+    BACKUP_HEADER_ENTITY_V1 = 0x61746144, // Data (little endian)
+};
+
+typedef struct {
+    int type; // BACKUP_HEADER_ENTITY_V1
+    int keyLen; // length of the key name, not including the null terminator
+    int dataSize; // size of the data, not including the padding, -1 means delete
+} entity_header_v1;
+
+struct SnapshotHeader {
+    int magic0;
+    int fileCount;
+    int magic1;
+    int totalSize;
+};
+
+struct FileState {
+    int modTime_sec;
+    int modTime_nsec;
+    int mode;
+    int size;
+    int crc32;
+    int nameLen;
+};
+
+struct FileRec {
+    String8 file;
+    bool deleted;
+    FileState s;
+};
+
+
+/**
+ * Writes the data.
+ *
+ * If an error occurs, it poisons this object and all write calls will fail
+ * with the error that occurred.
+ */
+class BackupDataWriter
+{
+public:
+    BackupDataWriter(int fd);
+    // does not close fd
+    ~BackupDataWriter();
+
+    status_t WriteEntityHeader(const String8& key, size_t dataSize);
+    status_t WriteEntityData(const void* data, size_t size);
+
+    void SetKeyPrefix(const String8& keyPrefix);
+
+private:
+    explicit BackupDataWriter();
+    status_t write_padding_for(int n);
+    
+    int m_fd;
+    status_t m_status;
+    ssize_t m_pos;
+    int m_entityCount;
+    String8 m_keyPrefix;
+};
+
+/**
+ * Reads the data.
+ *
+ * If an error occurs, it poisons this object and all write calls will fail
+ * with the error that occurred.
+ */
+class BackupDataReader
+{
+public:
+    BackupDataReader(int fd);
+    // does not close fd
+    ~BackupDataReader();
+
+    status_t Status();
+    status_t ReadNextHeader(bool* done, int* type);
+
+    bool HasEntities();
+    status_t ReadEntityHeader(String8* key, size_t* dataSize);
+    status_t SkipEntityData(); // must be called with the pointer at the begining of the data.
+    ssize_t ReadEntityData(void* data, size_t size);
+
+private:
+    explicit BackupDataReader();
+    status_t skip_padding();
+    
+    int m_fd;
+    bool m_done;
+    status_t m_status;
+    ssize_t m_pos;
+    ssize_t m_dataEndPos;
+    int m_entityCount;
+    union {
+        int type;
+        entity_header_v1 entity;
+    } m_header;
+    String8 m_key;
+};
+
+int back_up_files(int oldSnapshotFD, BackupDataWriter* dataStream, int newSnapshotFD,
+        char const* const* files, char const* const *keys, int fileCount);
+
+class RestoreHelperBase
+{
+public:
+    RestoreHelperBase();
+    ~RestoreHelperBase();
+
+    status_t WriteFile(const String8& filename, BackupDataReader* in);
+    status_t WriteSnapshot(int fd);
+
+private:
+    void* m_buf;
+    bool m_loggedUnknownMetadata;
+    KeyedVector<String8,FileRec> m_files;
+};
+
+#define TEST_BACKUP_HELPERS 1
+
+#if TEST_BACKUP_HELPERS
+int backup_helper_test_empty();
+int backup_helper_test_four();
+int backup_helper_test_files();
+int backup_helper_test_null_base();
+int backup_helper_test_missing_file();
+int backup_helper_test_data_writer();
+int backup_helper_test_data_reader();
+#endif
+
+} // namespace android
+
+#endif // _UTILS_BACKUP_HELPERS_H
diff --git a/include/utils/ByteOrder.h b/include/utils/ByteOrder.h
index 4c06067..baa3a83 100644
--- a/include/utils/ByteOrder.h
+++ b/include/utils/ByteOrder.h
@@ -38,6 +38,16 @@
  * intent is to allow us to avoid byte swapping on the device.
  */
 
+static inline uint32_t android_swap_long(uint32_t v)
+{
+    return (v<<24) | ((v<<8)&0x00FF0000) | ((v>>8)&0x0000FF00) | (v>>24);
+}
+
+static inline uint16_t android_swap_short(uint16_t v)
+{
+    return (v<<8) | (v>>8);
+}
+
 #define DEVICE_BYTE_ORDER LITTLE_ENDIAN
 
 #if BYTE_ORDER == DEVICE_BYTE_ORDER
@@ -49,16 +59,6 @@
 
 #else
 
-static inline uint32_t android_swap_long(uint32_t v)
-{
-    return (v<<24) | ((v<<8)&0x00FF0000) | ((v>>8)&0x0000FF00) | (v>>24);
-}
-
-static inline uint16_t android_swap_short(uint16_t v)
-{
-    return (v<<8) | (v>>8);
-}
-
 #define	dtohl(x)	(android_swap_long(x))
 #define	dtohs(x)	(android_swap_short(x))
 #define	htodl(x)	(android_swap_long(x))
@@ -66,4 +66,16 @@
 
 #endif
 
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define fromlel(x) (x)
+#define fromles(x) (x)
+#define tolel(x) (x)
+#define toles(x) (x)
+#else
+#define fromlel(x) (android_swap_long(x))
+#define fromles(x) (android_swap_short(x))
+#define tolel(x) (android_swap_long(x))
+#define toles(x) (android_swap_short(x))
+#endif
+
 #endif // _LIBS_UTILS_BYTE_ORDER_H
diff --git a/include/utils/Parcel.h b/include/utils/Parcel.h
index 9087c44..af1490a 100644
--- a/include/utils/Parcel.h
+++ b/include/utils/Parcel.h
@@ -80,8 +80,11 @@
     status_t            writeStrongBinder(const sp<IBinder>& val);
     status_t            writeWeakBinder(const wp<IBinder>& val);
 
-    // doesn't take ownership of the native_handle
-    status_t            writeNativeHandle(const native_handle& handle);
+    // Place a native_handle into the parcel (the native_handle's file-
+    // descriptors are dup'ed, so it is safe to delete the native_handle
+    // when this function returns). 
+    // Doesn't take ownership of the native_handle.
+    status_t            writeNativeHandle(const native_handle* handle);
     
     // Place a file descriptor into the parcel.  The given fd must remain
     // valid for the lifetime of the parcel.
@@ -114,12 +117,11 @@
     wp<IBinder>         readWeakBinder() const;
 
     
-    // if alloc is NULL, native_handle is allocated with malloc(), otherwise
-    // alloc is used. If the function fails, the effects of alloc() must be
-    // reverted by the caller.
-    native_handle*     readNativeHandle(
-            native_handle* (*alloc)(void* cookie, int numFds, int ints),
-            void* cookie) const;
+    // Retrieve native_handle from the parcel. This returns a copy of the
+    // parcel's native_handle (the caller takes ownership). The caller
+    // must free the native_handle with native_handle_close() and 
+    // native_handle_delete().
+    native_handle*     readNativeHandle() const;
 
     
     // Retrieve a file descriptor from the parcel.  This returns the raw fd
diff --git a/include/utils/ResourceTypes.h b/include/utils/ResourceTypes.h
index d01d83f..e524e2a 100644
--- a/include/utils/ResourceTypes.h
+++ b/include/utils/ResourceTypes.h
@@ -71,7 +71,7 @@
  * The relative sizes of the stretchy segments indicates the relative
  * amount of stretchiness of the regions bordered by the segments.  For
  * example, regions 3, 7 and 11 above will take up more horizontal space
- * than regions 1, 5 and 9 since the horizonal segment associated with
+ * than regions 1, 5 and 9 since the horizontal segment associated with
  * the first set of regions is larger than the other set of regions.  The
  * ratios of the amount of horizontal (or vertical) space taken by any
  * two stretchable slices is exactly the ratio of their corresponding
@@ -87,7 +87,7 @@
  * the leftmost slices always start at x=0 and the rightmost slices
  * always end at the end of the image. So, for example, the regions 0,
  * 4 and 8 (which are fixed along the X axis) start at x value 0 and
- * go to xDiv[0] amd slices 2, 6 and 10 start at xDiv[1] and end at
+ * go to xDiv[0] and slices 2, 6 and 10 start at xDiv[1] and end at
  * xDiv[2].
  *
  * The array pointed to by the colors field lists contains hints for
@@ -626,25 +626,25 @@
     event_code_t next();
 
     // These are available for all nodes:
-    const int32_t getCommentID() const;
+    int32_t getCommentID() const;
     const uint16_t* getComment(size_t* outLen) const;
-    const uint32_t getLineNumber() const;
+    uint32_t getLineNumber() const;
     
     // This is available for TEXT:
-    const int32_t getTextID() const;
+    int32_t getTextID() const;
     const uint16_t* getText(size_t* outLen) const;
     ssize_t getTextValue(Res_value* outValue) const;
     
     // These are available for START_NAMESPACE and END_NAMESPACE:
-    const int32_t getNamespacePrefixID() const;
+    int32_t getNamespacePrefixID() const;
     const uint16_t* getNamespacePrefix(size_t* outLen) const;
-    const int32_t getNamespaceUriID() const;
+    int32_t getNamespaceUriID() const;
     const uint16_t* getNamespaceUri(size_t* outLen) const;
     
     // These are available for START_TAG and END_TAG:
-    const int32_t getElementNamespaceID() const;
+    int32_t getElementNamespaceID() const;
     const uint16_t* getElementNamespace(size_t* outLen) const;
-    const int32_t getElementNameID() const;
+    int32_t getElementNameID() const;
     const uint16_t* getElementName(size_t* outLen) const;
     
     // Remaining methods are for retrieving information about attributes
@@ -653,14 +653,14 @@
     size_t getAttributeCount() const;
     
     // Returns -1 if no namespace, -2 if idx out of range.
-    const int32_t getAttributeNamespaceID(size_t idx) const;
+    int32_t getAttributeNamespaceID(size_t idx) const;
     const uint16_t* getAttributeNamespace(size_t idx, size_t* outLen) const;
     
-    const int32_t getAttributeNameID(size_t idx) const;
+    int32_t getAttributeNameID(size_t idx) const;
     const uint16_t* getAttributeName(size_t idx, size_t* outLen) const;
-    const uint32_t getAttributeNameResID(size_t idx) const;
+    uint32_t getAttributeNameResID(size_t idx) const;
     
-    const int32_t getAttributeValueStringID(size_t idx) const;
+    int32_t getAttributeValueStringID(size_t idx) const;
     const uint16_t* getAttributeStringValue(size_t idx, size_t* outLen) const;
     
     int32_t getAttributeDataType(size_t idx) const;
@@ -825,7 +825,11 @@
     };
     
     enum {
-        DENSITY_ANY = 0
+        DENSITY_DEFAULT = 0,
+        DENSITY_LOW = 120,
+        DENSITY_MEDIUM = 160,
+        DENSITY_HIGH = 240,
+        DENSITY_NONE = 0xffff
     };
     
     union {
@@ -854,7 +858,6 @@
     
     enum {
         MASK_KEYSHIDDEN = 0x0003,
-        SHIFT_KEYSHIDDEN = 0,
         KEYSHIDDEN_ANY = 0x0000,
         KEYSHIDDEN_NO = 0x0001,
         KEYSHIDDEN_YES = 0x0002,
@@ -866,7 +869,7 @@
             uint8_t keyboard;
             uint8_t navigation;
             uint8_t inputFlags;
-            uint8_t pad0;
+            uint8_t inputPad0;
         };
         uint32_t input;
     };
@@ -905,6 +908,31 @@
         uint32_t version;
     };
     
+    enum {
+        // screenLayout bits for screen size class.
+        MASK_SCREENSIZE = 0x0f,
+        SCREENSIZE_ANY  = 0x00,
+        SCREENSIZE_SMALL = 0x01,
+        SCREENSIZE_NORMAL = 0x02,
+        SCREENSIZE_LARGE = 0x03,
+        
+        // screenLayout bits for wide/long screen variation.
+        MASK_SCREENLONG = 0x30,
+        SCREENLONG_ANY = 0x00,
+        SCREENLONG_NO = 0x10,
+        SCREENLONG_YES = 0x20,
+    };
+    
+    union {
+        struct {
+            uint8_t screenLayout;
+            uint8_t screenConfigPad0;
+            uint8_t screenConfigPad1;
+            uint8_t screenConfigPad2;
+        };
+        uint32_t screenConfig;
+    };
+    
     inline void copyFromDeviceNoSwap(const ResTable_config& o) {
         const size_t size = dtohl(o.size);
         if (size >= sizeof(ResTable_config)) {
@@ -950,6 +978,8 @@
         diff = (int32_t)(screenSize - o.screenSize);
         if (diff != 0) return diff;
         diff = (int32_t)(version - o.version);
+        if (diff != 0) return diff;
+        diff = (int32_t)(screenLayout - o.screenLayout);
         return (int)diff;
     }
     
@@ -967,7 +997,8 @@
         CONFIG_ORIENTATION = 0x0080,
         CONFIG_DENSITY = 0x0100,
         CONFIG_SCREEN_SIZE = 0x0200,
-        CONFIG_VERSION = 0x0400
+        CONFIG_VERSION = 0x0400,
+        CONFIG_SCREEN_LAYOUT = 0x0800
     };
     
     // Compare two configuration, returning CONFIG_* flags set for each value
@@ -985,122 +1016,251 @@
         if (navigation != o.navigation) diffs |= CONFIG_NAVIGATION;
         if (screenSize != o.screenSize) diffs |= CONFIG_SCREEN_SIZE;
         if (version != o.version) diffs |= CONFIG_VERSION;
+        if (screenLayout != o.screenLayout) diffs |= CONFIG_SCREEN_LAYOUT;
         return diffs;
     }
     
-    // Return true if 'this' is more specific than 'o'.  Optionally, if
-    // 'requested' is null, then they will also be compared against the
-    // requested configuration and true will only be returned if 'this'
-    // is a better candidate than 'o' for the configuration.  This assumes that
-    // match() has already been used to remove any configurations that don't
-    // match the requested configuration at all; if they are not first filtered,
-    // non-matching results can be considered better than matching ones.
+    // Return true if 'this' is more specific than 'o'.
     inline bool
-    isBetterThan(const ResTable_config& o, const ResTable_config* requested = NULL) const {
+    isMoreSpecificThan(const ResTable_config& o) const {
         // The order of the following tests defines the importance of one
         // configuration parameter over another.  Those tests first are more
         // important, trumping any values in those following them.
-        if (imsi != 0 && (!requested || requested->imsi != 0)) {
-            if (mcc != 0 && (!requested || requested->mcc != 0)) {
-                if (o.mcc == 0) {
-                    return true;
-                }
+        if (imsi || o.imsi) {
+            if (mcc != o.mcc) {
+                if (!mcc) return false;
+                if (!o.mcc) return true;
             }
-            if (mnc != 0 && (!requested || requested->mnc != 0)) {
-                if (o.mnc == 0) {
-                    return true;
-                }
+
+            if (mnc != o.mnc) {
+                if (!mnc) return false;
+                if (!o.mnc) return true;
             }
         }
-        if (locale != 0 && (!requested || requested->locale != 0)) {
-            if (language[0] != 0 && (!requested || requested->language[0] != 0)) {
-                if (o.language[0] == 0) {
-                    return true;
-                }
+
+        if (locale || o.locale) {
+            if (language[0] != o.language[0]) {
+                if (!language[0]) return false;
+                if (!o.language[0]) return true;
             }
-            if (country[0] != 0 && (!requested || requested->country[0] != 0)) {
-                if (o.country[0] == 0) {
-                    return true;
-                }
+
+            if (country[0] != o.country[0]) {
+                if (!country[0]) return false;
+                if (!o.country[0]) return true;
             }
         }
-        if (screenType != 0 && (!requested || requested->screenType != 0)) {
-            if (orientation != 0 && (!requested || requested->orientation != 0)) {
-                if (o.orientation == 0) {
-                    return true;
-                }
+
+        if (screenConfig || o.screenConfig) {
+            if (((screenLayout^o.screenLayout) & MASK_SCREENSIZE) != 0) {
+                if (!(screenLayout & MASK_SCREENSIZE)) return false;
+                if (!(o.screenLayout & MASK_SCREENSIZE)) return true;
             }
-            if (density != 0 && (!requested || requested->density != 0)) {
-                if (o.density == 0) {
-                    return true;
-                }
-            }
-            if (touchscreen != 0 && (!requested || requested->touchscreen != 0)) {
-                if (o.touchscreen == 0) {
-                    return true;
-                }
+            if (((screenLayout^o.screenLayout) & MASK_SCREENLONG) != 0) {
+                if (!(screenLayout & MASK_SCREENLONG)) return false;
+                if (!(o.screenLayout & MASK_SCREENLONG)) return true;
             }
         }
-        if (input != 0 && (!requested || requested->input != 0)) {
-            const int keysHidden = inputFlags&MASK_KEYSHIDDEN;
-            const int reqKeysHidden = requested
-                    ? requested->inputFlags&MASK_KEYSHIDDEN : 0;
-            if (keysHidden != 0 && reqKeysHidden != 0) {
-                const int oKeysHidden = o.inputFlags&MASK_KEYSHIDDEN;
-                //LOGI("isBetterThan keysHidden: cur=%d, given=%d, config=%d\n",
-                //        keysHidden, oKeysHidden, reqKeysHidden);
-                if (oKeysHidden == 0) {
-                    //LOGI("Better because 0!");
-                    return true;
-                }
-                // For compatibility, we count KEYSHIDDEN_NO as being
-                // the same as KEYSHIDDEN_SOFT.  Here we disambiguate these
-                // may making an exact match more specific.
-                if (keysHidden == reqKeysHidden && oKeysHidden != reqKeysHidden) {
-                    // The current configuration is an exact match, and
-                    // the given one is not, so the current one is better.
-                    //LOGI("Better because other not same!");
-                    return true;
-                }
+
+        if (screenType || o.screenType) {
+            if (orientation != o.orientation) {
+                if (!orientation) return false;
+                if (!o.orientation) return true;
             }
-            if (keyboard != 0 && (!requested || requested->keyboard != 0)) {
-                if (o.keyboard == 0) {
-                    return true;
-                }
-            }
-            if (navigation != 0 && (!requested || requested->navigation != 0)) {
-                if (o.navigation == 0) {
-                    return true;
-                }
+
+            // density is never 'more specific'
+            // as the default just equals 160
+
+            if (touchscreen != o.touchscreen) {
+                if (!touchscreen) return false;
+                if (!o.touchscreen) return true;
             }
         }
-        if (screenSize != 0 && (!requested || requested->screenSize != 0)) {
-            if (screenWidth != 0 && (!requested || requested->screenWidth != 0)) {
-                if (o.screenWidth == 0) {
-                    return true;
-                }
+
+        if (input || o.input) {
+            if (((inputFlags^o.inputFlags) & MASK_KEYSHIDDEN) != 0) {
+                if (!(inputFlags & MASK_KEYSHIDDEN)) return false;
+                if (!(o.inputFlags & MASK_KEYSHIDDEN)) return true;
             }
-            if (screenHeight != 0 && (!requested || requested->screenHeight != 0)) {
-                if (o.screenHeight == 0) {
-                    return true;
-                }
+
+            if (keyboard != o.keyboard) {
+                if (!keyboard) return false;
+                if (!o.keyboard) return true;
+            }
+
+            if (navigation != o.navigation) {
+                if (!navigation) return false;
+                if (!o.navigation) return true;
             }
         }
-        if (version != 0 && (!requested || requested->version != 0)) {
-            if (sdkVersion != 0 && (!requested || requested->sdkVersion != 0)) {
-                if (o.sdkVersion == 0) {
-                    return true;
-                }
+
+        if (screenSize || o.screenSize) {
+            if (screenWidth != o.screenWidth) {
+                if (!screenWidth) return false;
+                if (!o.screenWidth) return true;
             }
-            if (minorVersion != 0 && (!requested || requested->minorVersion != 0)) {
-                if (o.minorVersion == 0) {
-                    return true;
-                }
+
+            if (screenHeight != o.screenHeight) {
+                if (!screenHeight) return false;
+                if (!o.screenHeight) return true;
+            }
+        }
+
+        if (version || o.version) {
+            if (sdkVersion != o.sdkVersion) {
+                if (!sdkVersion) return false;
+                if (!o.sdkVersion) return true;
+            }
+
+            if (minorVersion != o.minorVersion) {
+                if (!minorVersion) return false;
+                if (!o.minorVersion) return true;
             }
         }
         return false;
     }
-    
+
+    // Return true if 'this' is a better match than 'o' for the 'requested'
+    // configuration.  This assumes that match() has already been used to
+    // remove any configurations that don't match the requested configuration
+    // at all; if they are not first filtered, non-matching results can be
+    // considered better than matching ones.
+    // The general rule per attribute: if the request cares about an attribute
+    // (it normally does), if the two (this and o) are equal it's a tie.  If
+    // they are not equal then one must be generic because only generic and
+    // '==requested' will pass the match() call.  So if this is not generic,
+    // it wins.  If this IS generic, o wins (return false).
+    inline bool
+    isBetterThan(const ResTable_config& o,
+            const ResTable_config* requested) const {
+        if (requested) {
+            if (imsi || o.imsi) {
+                if ((mcc != o.mcc) && requested->mcc) {
+                    return (mcc);
+                }
+
+                if ((mnc != o.mnc) && requested->mnc) {
+                    return (mnc);
+                }
+            }
+
+            if (locale || o.locale) {
+                if ((language[0] != o.language[0]) && requested->language[0]) {
+                    return (language[0]);
+                }
+
+                if ((country[0] != o.country[0]) && requested->country[0]) {
+                    return (country[0]);
+                }
+            }
+
+            if (screenConfig || o.screenConfig) {
+                if (((screenLayout^o.screenLayout) & MASK_SCREENSIZE) != 0
+                        && (requested->screenLayout & MASK_SCREENSIZE)) {
+                    return (screenLayout & MASK_SCREENSIZE);
+                }
+                if (((screenLayout^o.screenLayout) & MASK_SCREENLONG) != 0
+                        && (requested->screenLayout & MASK_SCREENLONG)) {
+                    return (screenLayout & MASK_SCREENLONG);
+                }
+            }
+
+            if (screenType || o.screenType) {
+                if ((orientation != o.orientation) && requested->orientation) {
+                    return (orientation);
+                }
+
+                if (density != o.density) {
+                    // density is tough.  Any density is potentially useful
+                    // because the system will scale it.  Scaling down
+                    // is generally better than scaling up.
+                    // Default density counts as 160dpi (the system default)
+                    // TODO - remove 160 constants
+                    int h = (density?density:160);
+                    int l = (o.density?o.density:160);
+                    bool bImBigger = true;
+                    if (l > h) {
+                        int t = h;
+                        h = l;
+                        l = t;
+                        bImBigger = false;
+                    }
+ 
+                    int reqValue = (requested->density?requested->density:160);
+                    if (reqValue >= h) {
+                        // requested value higher than both l and h, give h
+                        return bImBigger;
+                    }
+                    if (l >= reqValue) {
+                        // requested value lower than both l and h, give l
+                        return !bImBigger;
+                    }
+                    // saying that scaling down is 2x better than up
+                    if (((2 * l) - reqValue) * h > reqValue * reqValue) {
+                        return !bImBigger;
+                    } else { 
+                        return bImBigger;
+                    }
+                }
+
+                if ((touchscreen != o.touchscreen) && requested->touchscreen) {
+                    return (touchscreen);
+                }
+            }
+
+            if (input || o.input) {
+                const int keysHidden = inputFlags & MASK_KEYSHIDDEN;
+                const int oKeysHidden = o.inputFlags & MASK_KEYSHIDDEN;
+                if (keysHidden != oKeysHidden) {
+                    const int reqKeysHidden =
+                            requested->inputFlags & MASK_KEYSHIDDEN;
+                    if (reqKeysHidden) {
+
+                        if (!keysHidden) return false;
+                        if (!oKeysHidden) return true;
+                        // For compatibility, we count KEYSHIDDEN_NO as being
+                        // the same as KEYSHIDDEN_SOFT.  Here we disambiguate
+                        // these by making an exact match more specific.
+                        if (reqKeysHidden == keysHidden) return true;
+                        if (reqKeysHidden == oKeysHidden) return false;
+                    }
+                }
+
+                if ((keyboard != o.keyboard) && requested->keyboard) {
+                    return (keyboard);
+                }
+
+                if ((navigation != o.navigation) && requested->navigation) {
+                    return (navigation);
+                }
+            }
+
+            if (screenSize || o.screenSize) {
+                if ((screenWidth != o.screenWidth) && requested->screenWidth) {
+                    return (screenWidth);
+                }
+
+                if ((screenHeight != o.screenHeight) &&
+                        requested->screenHeight) {
+                    return (screenHeight);
+                }
+            }
+
+            if (version || o.version) {
+                if ((sdkVersion != o.sdkVersion) && requested->sdkVersion) {
+                    return (sdkVersion);
+                }
+
+                if ((minorVersion != o.minorVersion) &&
+                        requested->minorVersion) {
+                    return (minorVersion);
+                }
+            }
+
+            return false;
+        }
+        return isMoreSpecificThan(o);
+    }
+
     // Return true if 'this' can be considered a match for the parameters in 
     // 'settings'.
     // Note this is asymetric.  A default piece of data will match every request
@@ -1132,13 +1292,27 @@
                 return false;
             }
         }
+        if (screenConfig != 0) {
+            const int screenSize = screenLayout&MASK_SCREENSIZE;
+            const int setScreenSize = settings.screenLayout&MASK_SCREENSIZE;
+            if (setScreenSize != 0 && screenSize != 0
+                    && screenSize != setScreenSize) {
+                return false;
+            }
+            
+            const int screenLong = screenLayout&MASK_SCREENLONG;
+            const int setScreenLong = settings.screenLayout&MASK_SCREENLONG;
+            if (setScreenLong != 0 && screenLong != 0
+                    && screenLong != setScreenLong) {
+                return false;
+            }
+        }
         if (screenType != 0) {
             if (settings.orientation != 0 && orientation != 0
                 && orientation != settings.orientation) {
                 return false;
             }
-            // Density not taken into account, always match, no matter what
-            // density is specified for the resource
+            // density always matches - we can scale it.  See isBetterThan
             if (settings.touchscreen != 0 && touchscreen != 0
                 && touchscreen != settings.touchscreen) {
                 return false;
@@ -1205,13 +1379,15 @@
 
     String8 toString() const {
         char buf[200];
-        sprintf(buf, "imsi=%d/%d lang=%c%c reg=%c%c orient=0x%02x touch=0x%02x dens=0x%02x "
-                "kbd=0x%02x nav=0x%02x input=0x%02x screenW=0x%04x screenH=0x%04x vers=%d.%d",
+        sprintf(buf, "imsi=%d/%d lang=%c%c reg=%c%c orient=%d touch=%d dens=%d "
+                "kbd=%d nav=%d input=%d scrnW=%d scrnH=%d sz=%d long=%d vers=%d.%d",
                 mcc, mnc,
                 language[0] ? language[0] : '-', language[1] ? language[1] : '-',
                 country[0] ? country[0] : '-', country[1] ? country[1] : '-',
                 orientation, touchscreen, density, keyboard, navigation, inputFlags,
-                screenWidth, screenHeight, sdkVersion, minorVersion);
+                screenWidth, screenHeight,
+                screenLayout&MASK_SCREENSIZE, screenLayout&MASK_SCREENLONG,
+                sdkVersion, minorVersion);
         return String8(buf);
     }
 };
@@ -1296,7 +1472,7 @@
  * This is the beginning of information about an entry in the resource
  * table.  It holds the reference to the name of this entry, and is
  * immediately followed by one of:
- *   * A Res_value structures, if FLAG_COMPLEX is -not- set.
+ *   * A Res_value structure, if FLAG_COMPLEX is -not- set.
  *   * An array of ResTable_map structures, if FLAG_COMPLEX is set.
  *     These supply a set of name/value mappings of data.
  */
@@ -1435,6 +1611,7 @@
                  bool copyData=false);
     status_t add(Asset* asset, void* cookie,
                  bool copyData=false);
+    status_t add(ResTable* src);
 
     status_t getError() const;
 
@@ -1478,7 +1655,8 @@
     ssize_t resolveReference(Res_value* inOutValue,
                              ssize_t blockIndex,
                              uint32_t* outLastRef = NULL,
-                             uint32_t* inoutTypeSpecFlags = NULL) const;
+                             uint32_t* inoutTypeSpecFlags = NULL,
+                             ResTable_config* outConfig = NULL) const;
 
     enum {
         TMP_BUFFER_SIZE = 16
@@ -1552,7 +1730,8 @@
          */
         ssize_t resolveAttributeReference(Res_value* inOutValue,
                 ssize_t blockIndex, uint32_t* outLastRef = NULL,
-                uint32_t* inoutTypeSpecFlags = NULL) const;
+                uint32_t* inoutTypeSpecFlags = NULL,
+                ResTable_config* inoutConfig = NULL) const;
 
         void dumpToLog() const;
         
@@ -1676,7 +1855,7 @@
     void getLocales(Vector<String8>* locales) const;
 
 #ifndef HAVE_ANDROID_OS
-    void print() const;
+    void print(bool inclValues) const;
 #endif
 
 private:
@@ -1698,6 +1877,8 @@
     status_t parsePackage(
         const ResTable_package* const pkg, const Header* const header);
 
+    void print_value(const Package* pkg, const Res_value& value) const;
+    
     mutable Mutex               mLock;
 
     status_t                    mError;
diff --git a/include/utils/String8.h b/include/utils/String8.h
index c49faf6..ecc5774 100644
--- a/include/utils/String8.h
+++ b/include/utils/String8.h
@@ -29,11 +29,107 @@
 
 // ---------------------------------------------------------------------------
 
+extern "C" {
+
+typedef uint32_t char32_t;
+
+size_t strlen32(const char32_t *);
+size_t strnlen32(const char32_t *, size_t);
+
+/*
+ * Returns the length of "src" when "src" is valid UTF-8 string.
+ * Returns 0 if src is NULL, 0-length string or non UTF-8 string.
+ * This function should be used to determine whether "src" is valid UTF-8
+ * characters with valid unicode codepoints. "src" must be null-terminated.
+ *
+ * If you are going to use other GetUtf... functions defined in this header
+ * with string which may not be valid UTF-8 with valid codepoint (form 0 to
+ * 0x10FFFF), you should use this function before calling others, since the
+ * other functions do not check whether the string is valid UTF-8 or not.
+ *
+ * If you do not care whether "src" is valid UTF-8 or not, you should use
+ * strlen() as usual, which should be much faster.
+ */
+size_t utf8_length(const char *src);
+
+/*
+ * Returns the UTF-32 length of "src".
+ */
+size_t utf32_length(const char *src, size_t src_len);
+
+/*
+ * Returns the UTF-8 length of "src".
+ */
+size_t utf8_length_from_utf32(const char32_t *src, size_t src_len);
+
+/*
+ * Returns the unicode value at "index".
+ * Returns -1 when the index is invalid (equals to or more than "src_len").
+ * If returned value is positive, it is able to be converted to char32_t, which
+ * is unsigned. Then, if "next_index" is not NULL, the next index to be used is
+ * stored in "next_index". "next_index" can be NULL.
+ */
+int32_t utf32_at(const char *src, size_t src_len,
+                 size_t index, size_t *next_index);
+
+/*
+ * Stores a UTF-32 string converted from "src" in "dst", if "dst_length" is not
+ * large enough to store the string, the part of the "src" string is stored
+ * into "dst".
+ * Returns the size actually used for storing the string.
+ * "dst" is not null-terminated when dst_len is fully used (like strncpy).
+ */
+size_t utf8_to_utf32(const char* src, size_t src_len,
+                     char32_t* dst, size_t dst_len);
+
+/*
+ * Stores a UTF-8 string converted from "src" in "dst", if "dst_length" is not
+ * large enough to store the string, the part of the "src" string is stored
+ * into "dst" as much as possible. See the examples for more detail.
+ * Returns the size actually used for storing the string.
+ * dst" is not null-terminated when dst_len is fully used (like strncpy).
+ *
+ * Example 1
+ * "src" == \u3042\u3044 (\xE3\x81\x82\xE3\x81\x84)
+ * "src_len" == 2
+ * "dst_len" >= 7
+ * ->
+ * Returned value == 6
+ * "dst" becomes \xE3\x81\x82\xE3\x81\x84\0
+ * (note that "dst" is null-terminated)
+ *
+ * Example 2
+ * "src" == \u3042\u3044 (\xE3\x81\x82\xE3\x81\x84)
+ * "src_len" == 2
+ * "dst_len" == 5
+ * ->
+ * Returned value == 3
+ * "dst" becomes \xE3\x81\x82\0
+ * (note that "dst" is null-terminated, but \u3044 is not stored in "dst"
+ * since "dst" does not have enough size to store the character)
+ *
+ * Example 3
+ * "src" == \u3042\u3044 (\xE3\x81\x82\xE3\x81\x84)
+ * "src_len" == 2
+ * "dst_len" == 6
+ * ->
+ * Returned value == 6
+ * "dst" becomes \xE3\x81\x82\xE3\x81\x84
+ * (note that "dst" is NOT null-terminated, like strncpy)
+ */
+size_t utf32_to_utf8(const char32_t* src, size_t src_len,
+                     char* dst, size_t dst_len);
+
+}
+
+// ---------------------------------------------------------------------------
+
 namespace android {
 
 class TextOutput;
 
-//! This is a string holding UTF-8 characters.
+//! This is a string holding UTF-8 characters. Does not allow the value more
+// than 0x10FFFF, which is not valid unicode codepoint.
 class String8
 {
 public:
@@ -45,7 +141,8 @@
     explicit                    String8(const String16& o);
     explicit                    String8(const char16_t* o);
     explicit                    String8(const char16_t* o, size_t numChars);
-    
+    explicit                    String8(const char32_t* o);
+    explicit                    String8(const char32_t* o, size_t numChars);
                                 ~String8();
     
     inline  const char*         string() const;
@@ -59,11 +156,20 @@
             status_t            setTo(const char* other);
             status_t            setTo(const char* other, size_t numChars);
             status_t            setTo(const char16_t* other, size_t numChars);
-    
+            status_t            setTo(const char32_t* other,
+                                      size_t length);
+
             status_t            append(const String8& other);
             status_t            append(const char* other);
             status_t            append(const char* other, size_t numChars);
 
+            // Note that this function takes O(N) time to calculate the value.
+            // No cache value is stored.
+            size_t              getUtf32Length() const;
+            int32_t             getUtf32At(size_t index,
+                                           size_t *next_index) const;
+            size_t              getUtf32(char32_t* dst, size_t dst_len) const;
+
     inline  String8&            operator=(const String8& other);
     inline  String8&            operator=(const char* other);
     
@@ -103,7 +209,7 @@
             void                toLower(size_t start, size_t numChars);
             void                toUpper();
             void                toUpper(size_t start, size_t numChars);
-            
+
     /*
      * These methods operate on the string as if it were a path name.
      */
@@ -346,7 +452,7 @@
     return mString;
 }
 
-}; // namespace android
+}  // namespace android
 
 // ---------------------------------------------------------------------------
 
diff --git a/include/utils/TimeUtils.h b/include/utils/TimeUtils.h
deleted file mode 100644
index b19e021..0000000
--- a/include/utils/TimeUtils.h
+++ /dev/null
@@ -1,89 +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.
- */
-
-#ifndef ANDROID_TIME_H
-#define ANDROID_TIME_H
-
-#include <time.h>
-#include <cutils/tztime.h>
-#include <stdint.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <utils/String8.h>
-#include <utils/String16.h>
-
-namespace android {
-
-/*
- * This class is the core implementation of the android.util.Time java
- * class.  It doesn't implement some of the methods that are implemented
- * in Java.  They could be done here, but it's not expected that this class
- * will be used.  If that assumption is incorrect, feel free to update this
- * file.  The reason to do it here is to not mix the implementation of this
- * class and the jni glue code.
- */
-class Time
-{
-public:
-    struct tm t;
-
-    // this object doesn't own this string
-    const char *timezone;
-
-    enum {
-        SEC = 1,
-        MIN = 2,
-        HOUR = 3,
-        MDAY = 4,
-        MON = 5,
-        YEAR = 6,
-        WDAY = 7,
-        YDAY = 8
-    };
-
-    static int compare(Time& a, Time& b);
-
-    Time();
-
-    void switchTimezone(const char *timezone);
-    String8 format(const char *format, const struct strftime_locale *locale) const;
-    void format2445(short* buf, bool hasTime) const;
-    String8 toString() const;
-    void setToNow();
-    int64_t toMillis(bool ignoreDst);
-    void set(int64_t millis);
-
-    inline void set(int sec, int min, int hour, int mday, int mon, int year,
-            int isdst)
-    {
-        this->t.tm_sec = sec;
-        this->t.tm_min = min;
-        this->t.tm_hour = hour;
-        this->t.tm_mday = mday;
-        this->t.tm_mon = mon;
-        this->t.tm_year = year;
-        this->t.tm_isdst = isdst;
-#ifdef HAVE_TM_GMTOFF
-        this->t.tm_gmtoff = 0;
-#endif
-        this->t.tm_wday = 0;
-        this->t.tm_yday = 0;
-    }
-};
-
-}; // namespace android
-
-#endif // ANDROID_TIME_H
diff --git a/include/utils/threads.h b/include/utils/threads.h
index 8d8d46a..b320915 100644
--- a/include/utils/threads.h
+++ b/include/utils/threads.h
@@ -79,6 +79,13 @@
     ANDROID_PRIORITY_LESS_FAVORABLE = +1,
 };
 
+enum {
+    ANDROID_TGROUP_DEFAULT          = 0,
+    ANDROID_TGROUP_BG_NONINTERACT   = 1,
+    ANDROID_TGROUP_FG_BOOST         = 2,
+    ANDROID_TGROUP_MAX              = ANDROID_TGROUP_FG_BOOST,
+};
+
 // Create and run a new thread.
 extern int androidCreateThread(android_thread_func_t, void *);
 
diff --git a/libs/audioflinger/A2dpAudioInterface.cpp b/libs/audioflinger/A2dpAudioInterface.cpp
index b6d5078..16a4f2d 100644
--- a/libs/audioflinger/A2dpAudioInterface.cpp
+++ b/libs/audioflinger/A2dpAudioInterface.cpp
@@ -71,8 +71,8 @@
 }
 
 AudioStreamIn* A2dpAudioInterface::openInputStream(
-        int format, int channelCount, uint32_t sampleRate, status_t *status,
-        AudioSystem::audio_in_acoustics acoustics)
+        int inputSource, int format, int channelCount, uint32_t sampleRate,
+        status_t *status, AudioSystem::audio_in_acoustics acoustics)
 {
     if (status)
         *status = -1;
diff --git a/libs/audioflinger/A2dpAudioInterface.h b/libs/audioflinger/A2dpAudioInterface.h
index 7901a8c..091e775 100644
--- a/libs/audioflinger/A2dpAudioInterface.h
+++ b/libs/audioflinger/A2dpAudioInterface.h
@@ -55,6 +55,7 @@
                                 status_t *status=0);
 
     virtual AudioStreamIn* openInputStream(
+                                int inputSource,
                                 int format,
                                 int channelCount,
                                 uint32_t sampleRate,
diff --git a/libs/audioflinger/AudioBufferProvider.h b/libs/audioflinger/AudioBufferProvider.h
index 1a467c7..81c5c39 100644
--- a/libs/audioflinger/AudioBufferProvider.h
+++ b/libs/audioflinger/AudioBufferProvider.h
@@ -36,6 +36,8 @@
         };
         size_t frameCount;
     };
+
+    virtual ~AudioBufferProvider() {}
     
     virtual status_t getNextBuffer(Buffer* buffer) = 0;
     virtual void releaseBuffer(Buffer* buffer) = 0;
diff --git a/libs/audioflinger/AudioDumpInterface.h b/libs/audioflinger/AudioDumpInterface.h
index 9a94102..b72c94e 100644
--- a/libs/audioflinger/AudioDumpInterface.h
+++ b/libs/audioflinger/AudioDumpInterface.h
@@ -78,9 +78,9 @@
     virtual status_t    setParameter(const char* key, const char* value)
                             {return mFinalInterface->setParameter(key, value);}
 
-    virtual AudioStreamIn* openInputStream( int format, int channelCount, uint32_t sampleRate, status_t *status,
-                                            AudioSystem::audio_in_acoustics acoustics)
-                            {return mFinalInterface->openInputStream( format, channelCount, sampleRate, status, acoustics);}
+    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 status_t    dump(int fd, const Vector<String16>& args) { return mFinalInterface->dumpState(fd, args); }
 
diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp
index 43df7dd..b8e5bd0 100644
--- a/libs/audioflinger/AudioFlinger.cpp
+++ b/libs/audioflinger/AudioFlinger.cpp
@@ -202,8 +202,8 @@
     SortedVector < sp<MixerThread::Track> > tracks;
     SortedVector < wp<MixerThread::Track> > activeTracks;
     
-    LOGV_IF(enable, "set output to A2DP\n");
-    LOGV_IF(!enable, "set output to hardware audio\n");
+    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) {
@@ -212,6 +212,7 @@
     } else {
         mA2dpMixerThread->getTracks_l(tracks, activeTracks);
         mHardwareMixerThread->putTracks_l(tracks, activeTracks);
+        mA2dpMixerThread->mOutput->standby();
     }
     mA2dpEnabled = enable;
     mNotifyA2dpChange = true;
@@ -499,7 +500,8 @@
     }
 
 #ifdef WITH_A2DP
-    LOGD("setRouting %d %d %d, tid %d, calling tid %d\n", mode, routes, mask, gettid(), IPCThreadState::self()->getCallingPid());
+    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);
@@ -655,16 +657,12 @@
     
     if (stream == AudioSystem::VOICE_CALL ||
         stream == AudioSystem::BLUETOOTH_SCO) {
-        float hwValue = value;
+        float hwValue;
         if (stream == AudioSystem::VOICE_CALL) {
             hwValue = (float)AudioSystem::logToLinear(value)/100.0f;
-            // FIXME: This is a temporary fix to re-base the internally
-            // generated in-call audio so that it is never muted, which is
-            // already the case for the hardware routed in-call audio.
-            // When audio stream handling is reworked, this should be
-            // addressed more cleanly.  Fixes #1324; see discussion at
-            // http://review.source.android.com/8224
-            value = value * 0.99 + 0.01;        
+            // 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;
         }
@@ -681,6 +679,11 @@
     mA2dpMixerThread->setStreamVolume(stream, value);
 #endif
 
+    mHardwareMixerThread->setStreamVolume(stream, value);
+#ifdef WITH_A2DP
+    mA2dpMixerThread->setStreamVolume(stream, value);
+#endif
+
     return ret;
 }
 
@@ -718,15 +721,14 @@
     if (uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) {
         return 0.0f;
     }
-    float value = mHardwareMixerThread->streamVolume(stream);
     
+    float volume = mHardwareMixerThread->streamVolume(stream); 
+    // remove correction applied by setStreamVolume()
     if (stream == AudioSystem::VOICE_CALL) {
-        // FIXME: Re-base internally generated in-call audio,
-        // reverse of above in setStreamVolume.
-        value = (value - 0.01) / 0.99;
+        volume = (volume - 0.01) / 0.99 ;
     }
     
-    return value;
+    return volume;
 }
 
 bool AudioFlinger::streamMute(int stream) const
@@ -744,12 +746,13 @@
 
 bool AudioFlinger::isMusicActive() const
 {
+    Mutex::Autolock _l(mLock);
  #ifdef WITH_A2DP
      if (isA2dpEnabled()) {
-         return mA2dpMixerThread->isMusicActive();
+         return mA2dpMixerThread->isMusicActive_l();
      }
  #endif
-    return mHardwareMixerThread->isMusicActive();
+    return mHardwareMixerThread->isMusicActive_l();
 }
 
 status_t AudioFlinger::setParameter(const char* key, const char* value)
@@ -824,24 +827,22 @@
         {
             AutoMutex lock(mHardwareLock);
             if (mForcedSpeakerCount++ == 0) {
-                mRouteRestoreTime = 0;
-                mMusicMuteSaved = mHardwareMixerThread->streamMute(AudioSystem::MUSIC);
-                if (mForcedRoute == 0 && !(mSavedRoute & AudioSystem::ROUTE_SPEAKER)) {
-                    LOGV("Route forced to Speaker ON %08x", mSavedRoute | AudioSystem::ROUTE_SPEAKER);
-                    mHardwareMixerThread->setStreamMute(AudioSystem::MUSIC, true);
-                    mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
-                    mAudioHardware->setMasterVolume(0);
-                    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);
-                    mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
-                    mAudioHardware->setMasterVolume(mHardwareMixerThread->masterVolume());
-                    mHardwareStatus = AUDIO_HW_IDLE;
+                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);
         }
@@ -902,7 +903,7 @@
             }
             LOGV("mA2dpDisableCount decremented to %d", mA2dpDisableCount);
         } else {
-            LOGE("mA2dpDisableCount is already zero");
+            LOGV("mA2dpDisableCount is already zero");
         }
     }
 }
@@ -1289,7 +1290,7 @@
     status_t lStatus;
     
     // Resampler implementation limits input sampling rate to 2 x output sampling rate.
-    if (sampleRate > MAX_SAMPLE_RATE || sampleRate > mSampleRate*2) {
+    if (sampleRate > mSampleRate*2) {
         LOGE("Sample rate out of range: %d mSampleRate %d", sampleRate, mSampleRate);
         lStatus = BAD_VALUE;
         goto Exit;
@@ -1452,7 +1453,8 @@
     return mStreamTypes[stream].mute;
 }
 
-bool AudioFlinger::MixerThread::isMusicActive() const
+// isMusicActive_l() must be called with AudioFlinger::mLock held
+bool AudioFlinger::MixerThread::isMusicActive_l() const
 {
     size_t count = mActiveTracks.size();
     for (size_t i = 0 ; i < count ; ++i) {
@@ -1497,18 +1499,6 @@
     return status;
 }
 
-// removeTrack_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::MixerThread::removeTrack_l(wp<Track> track, int name)
-{
-    sp<Track> t = track.promote();
-    if (t!=NULL && (t->mState <= TrackBase::STOPPED)) {
-        t->reset();
-        deleteTrackName_l(name);
-        removeActiveTrack_l(track);
-        mAudioFlinger->mWaitWorkCV.broadcast();
-    }
-}
-
 // destroyTrack_l() must be called with AudioFlinger::mLock held
 void AudioFlinger::MixerThread::destroyTrack_l(const sp<Track>& track)
 {
@@ -1577,7 +1567,6 @@
 AudioFlinger::MixerThread::TrackBase::TrackBase(
             const sp<MixerThread>& mixerThread,
             const sp<Client>& client,
-            int streamType,
             uint32_t sampleRate,
             int format,
             int channelCount,
@@ -1587,7 +1576,6 @@
     :   RefBase(),
         mMixerThread(mixerThread),
         mClient(client),
-        mStreamType(streamType),
         mFrameCount(0),
         mState(IDLE),
         mClientTid(-1),
@@ -1618,8 +1606,8 @@
                 new(mCblk) audio_track_cblk_t();
                 // clear all buffers
                 mCblk->frameCount = frameCount;
-                mCblk->sampleRate = (uint16_t)sampleRate;
-                mCblk->channels = (uint16_t)channelCount;
+                mCblk->sampleRate = sampleRate;
+                mCblk->channels = (uint8_t)channelCount;
                 if (sharedBuffer == 0) {
                     mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
                     memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
@@ -1642,8 +1630,8 @@
            new(mCblk) audio_track_cblk_t();
            // clear all buffers
            mCblk->frameCount = frameCount;
-           mCblk->sampleRate = (uint16_t)sampleRate;
-           mCblk->channels = (uint16_t)channelCount;
+           mCblk->sampleRate = sampleRate;
+           mCblk->channels = (uint8_t)channelCount;
            mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
            memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
            // Force underrun condition to avoid false underrun callback until first data is
@@ -1704,7 +1692,7 @@
 }
 
 int AudioFlinger::MixerThread::TrackBase::channelCount() const {
-    return mCblk->channels;
+    return (int)mCblk->channels;
 }
 
 void* AudioFlinger::MixerThread::TrackBase::getBuffer(uint32_t offset, uint32_t frames) const {
@@ -1714,7 +1702,7 @@
 
     // 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) ) {
+        (cblk->channels == 2 && ((unsigned long)bufferStart & 3))) {
         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,
@@ -1737,12 +1725,13 @@
             int channelCount,
             int frameCount,
             const sp<IMemory>& sharedBuffer)
-    :   TrackBase(mixerThread, client, streamType, sampleRate, format, channelCount, frameCount, 0, sharedBuffer)
+    :   TrackBase(mixerThread, client, sampleRate, format, channelCount, frameCount, 0, sharedBuffer)
 {
     mVolume[0] = 1.0f;
     mVolume[1] = 1.0f;
     mMute = false;
     mSharedBuffer = sharedBuffer;
+    mStreamType = streamType;
 }
 
 AudioFlinger::MixerThread::Track::~Track()
@@ -1750,7 +1739,6 @@
     wp<Track> weak(this); // never create a strong ref from the dtor
     Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock);
     mState = TERMINATED;
-    mMixerThread->removeTrack_l(weak, mName);
 }
 
 void AudioFlinger::MixerThread::Track::destroy()
@@ -1927,15 +1915,15 @@
 AudioFlinger::MixerThread::RecordTrack::RecordTrack(
             const sp<MixerThread>& mixerThread,
             const sp<Client>& client,
-            int streamType,
+            int inputSource,
             uint32_t sampleRate,
             int format,
             int channelCount,
             int frameCount,
             uint32_t flags)
-    :   TrackBase(mixerThread, client, streamType, sampleRate, format,
+    :   TrackBase(mixerThread, client, sampleRate, format,
                   channelCount, frameCount, flags, 0),
-        mOverflow(false)
+        mOverflow(false), mInputSource(inputSource)
 {
 }
 
@@ -2052,7 +2040,10 @@
     inBuffer.i16 = data;
     
     if (mCblk->user == 0) {
-        if (mOutputMixerThread->isMusicActive()) {
+        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){
@@ -2260,7 +2251,7 @@
 
 sp<IAudioRecord> AudioFlinger::openRecord(
         pid_t pid,
-        int streamType,
+        int inputSource,
         uint32_t sampleRate,
         int format,
         int channelCount,
@@ -2283,18 +2274,12 @@
         goto Exit;
     }
 
-    if (uint32_t(streamType) >= AudioRecord::NUM_STREAM_TYPES) {
+    if (uint32_t(inputSource) >= AudioRecord::NUM_INPUT_SOURCES) {
         LOGE("invalid stream type");
         lStatus = BAD_VALUE;
         goto Exit;
     }
 
-    if (sampleRate > MAX_SAMPLE_RATE) {
-        LOGE("Sample rate out of range");
-        lStatus = BAD_VALUE;
-        goto Exit;
-    }
-
     if (mAudioRecordThread == 0) {
         LOGE("Audio record thread not started");
         lStatus = NO_INIT;
@@ -2326,7 +2311,7 @@
         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, streamType, sampleRate,
+        recordTrack = new MixerThread::RecordTrack(mHardwareMixerThread, client, inputSource, sampleRate,
                                                    format, channelCount, frameCount, flags);
     }
     if (recordTrack->getCblk() == NULL) {
@@ -2432,7 +2417,9 @@
                
                 LOGV("AudioRecordThread: loop starting");
                 if (mRecordTrack != 0) {
-                    input = mAudioHardware->openInputStream(mRecordTrack->format(), 
+                    input = mAudioHardware->openInputStream(
+                                    mRecordTrack->inputSource(),
+                                    mRecordTrack->format(), 
                                     mRecordTrack->channelCount(), 
                                     mRecordTrack->sampleRate(), 
                                     &mStartStatus,
diff --git a/libs/audioflinger/AudioFlinger.h b/libs/audioflinger/AudioFlinger.h
index db5cc74..634934e 100644
--- a/libs/audioflinger/AudioFlinger.h
+++ b/libs/audioflinger/AudioFlinger.h
@@ -139,7 +139,7 @@
     // record interface
     virtual sp<IAudioRecord> openRecord(
                                 pid_t pid,
-                                int streamType,
+                                int inputSource,
                                 uint32_t sampleRate,
                                 int format,
                                 int channelCount,
@@ -232,7 +232,6 @@
 
                                 TrackBase(const sp<MixerThread>& mixerThread,
                                         const sp<Client>& client,
-                                        int streamType,
                                         uint32_t sampleRate,
                                         int format,
                                         int channelCount,
@@ -260,10 +259,6 @@
                 return mCblk;
             }
 
-            int type() const {
-                return mStreamType;
-            }
-
             int format() const {
                 return mFormat;
             }
@@ -293,7 +288,6 @@
             sp<Client>          mClient;
             sp<IMemory>         mCblkMemory;
             audio_track_cblk_t* mCblk;
-            int                 mStreamType;
             void*               mBuffer;
             void*               mBufferEnd;
             uint32_t            mFrameCount;
@@ -328,6 +322,11 @@
                     void        mute(bool);
                     void        setVolume(float left, float right);
 
+                    int type() const {
+                        return mStreamType;
+                    }
+
+
         protected:
             friend class MixerThread;
             friend class AudioFlinger;
@@ -364,6 +363,7 @@
             int8_t              mRetryCount;
             sp<IMemory>         mSharedBuffer;
             bool                mResetDone;
+            int                 mStreamType;
         };  // end of Track
 
         // record track
@@ -371,7 +371,7 @@
         public:
                                 RecordTrack(const sp<MixerThread>& mixerThread,
                                         const sp<Client>& client,
-                                        int streamType,
+                                        int inputSource,
                                         uint32_t sampleRate,
                                         int format,
                                         int channelCount,
@@ -385,6 +385,8 @@
                     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;
@@ -397,6 +399,7 @@
             virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer);
 
             bool                mOverflow;
+            int                 mInputSource;
         };
 
         // playback track
@@ -460,7 +463,7 @@
         virtual     float       streamVolume(int stream) const;
         virtual     bool        streamMute(int stream) const;
 
-                    bool        isMusicActive() const;
+                    bool        isMusicActive_l() const;
         
                     
                     sp<Track>   createTrack_l(
@@ -501,7 +504,6 @@
         MixerThread& operator = (const MixerThread&);
   
         status_t    addTrack_l(const sp<Track>& track);
-        void        removeTrack_l(wp<Track> track, int name);
         void        destroyTrack_l(const sp<Track>& track);
         int         getTrackName_l();
         void        deleteTrackName_l(int name);
diff --git a/libs/audioflinger/AudioHardwareGeneric.cpp b/libs/audioflinger/AudioHardwareGeneric.cpp
index 62beada..1e159b8 100644
--- a/libs/audioflinger/AudioHardwareGeneric.cpp
+++ b/libs/audioflinger/AudioHardwareGeneric.cpp
@@ -30,6 +30,7 @@
 #include <utils/String8.h>
 
 #include "AudioHardwareGeneric.h"
+#include <media/AudioRecord.h>
 
 namespace android {
 
@@ -93,9 +94,15 @@
 }
 
 AudioStreamIn* AudioHardwareGeneric::openInputStream(
-        int format, int channelCount, uint32_t sampleRate, status_t *status,
-        AudioSystem::audio_in_acoustics acoustics)
+        int inputSource, int format, int channelCount, 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)) {
+        return 0;
+    }
+
     AutoMutex lock(mLock);
 
     // only one input stream allowed
diff --git a/libs/audioflinger/AudioHardwareGeneric.h b/libs/audioflinger/AudioHardwareGeneric.h
index c949aa1..c89df87 100644
--- a/libs/audioflinger/AudioHardwareGeneric.h
+++ b/libs/audioflinger/AudioHardwareGeneric.h
@@ -112,6 +112,7 @@
             status_t *status=0);
 
     virtual AudioStreamIn* openInputStream(
+            int inputSource,
             int format,
             int channelCount,
             uint32_t sampleRate,
diff --git a/libs/audioflinger/AudioHardwareInterface.cpp b/libs/audioflinger/AudioHardwareInterface.cpp
index ac76a19..cc1bd8f 100644
--- a/libs/audioflinger/AudioHardwareInterface.cpp
+++ b/libs/audioflinger/AudioHardwareInterface.cpp
@@ -53,7 +53,7 @@
     "EARPIECE ",
     "SPEAKER ",
     "BLUETOOTH ",
-    "HEADSET "
+    "HEADSET ",
     "BLUETOOTH_A2DP "
 };
 static const char* routeNone = "NONE";
diff --git a/libs/audioflinger/AudioHardwareStub.cpp b/libs/audioflinger/AudioHardwareStub.cpp
index b13cb1c..0ab4c60 100644
--- a/libs/audioflinger/AudioHardwareStub.cpp
+++ b/libs/audioflinger/AudioHardwareStub.cpp
@@ -23,6 +23,7 @@
 #include <utils/String8.h>
 
 #include "AudioHardwareStub.h"
+#include <media/AudioRecord.h>
 
 namespace android {
 
@@ -56,9 +57,15 @@
 }
 
 AudioStreamIn* AudioHardwareStub::openInputStream(
-        int format, int channelCount, uint32_t sampleRate,
+        int inputSource, int format, int channelCount, 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)) {
+        return 0;
+    }
+
     AudioStreamInStub* in = new AudioStreamInStub();
     status_t lStatus = in->set(format, channelCount, sampleRate, acoustics);
     if (status) {
diff --git a/libs/audioflinger/AudioHardwareStub.h b/libs/audioflinger/AudioHardwareStub.h
index d406424..bf63cc5 100644
--- a/libs/audioflinger/AudioHardwareStub.h
+++ b/libs/audioflinger/AudioHardwareStub.h
@@ -78,6 +78,7 @@
                                 status_t *status=0);
 
     virtual AudioStreamIn* openInputStream(
+                                int inputSource,
                                 int format,
                                 int channelCount,
                                 uint32_t sampleRate,
diff --git a/libs/surfaceflinger/Android.mk b/libs/surfaceflinger/Android.mk
index 2212436..ec5aa3f 100644
--- a/libs/surfaceflinger/Android.mk
+++ b/libs/surfaceflinger/Android.mk
@@ -6,7 +6,6 @@
     DisplayHardware/DisplayHardware.cpp \
     DisplayHardware/DisplayHardwareBase.cpp \
     GPUHardware/GPUHardware.cpp \
-    BootAnimation.cpp \
     BlurFilter.cpp.arm \
     CPUGauge.cpp \
     Layer.cpp \
@@ -16,7 +15,6 @@
     LayerBitmap.cpp \
     LayerDim.cpp \
     LayerOrientationAnim.cpp \
-    LayerOrientationAnimRotate.cpp \
     OrientationAnimation.cpp \
     SurfaceFlinger.cpp \
     Tokenizer.cpp \
diff --git a/libs/surfaceflinger/BootAnimation.cpp b/libs/surfaceflinger/BootAnimation.cpp
deleted file mode 100644
index db40385..0000000
--- a/libs/surfaceflinger/BootAnimation.cpp
+++ /dev/null
@@ -1,246 +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 "BootAnimation"
-
-#include <stdint.h>
-#include <sys/types.h>
-#include <math.h>
-#include <fcntl.h>
-#include <utils/misc.h>
-
-#include <utils/threads.h>
-#include <utils/Atomic.h>
-#include <utils/Errors.h>
-#include <utils/Log.h>
-#include <utils/AssetManager.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 <ui/EGLNativeWindowSurface.h>
-
-#include <core/SkBitmap.h>
-#include <images/SkImageDecoder.h>
-
-#include <GLES/gl.h>
-#include <GLES/glext.h>
-#include <EGL/eglext.h>
-
-#include "BootAnimation.h"
-
-namespace android {
-
-// ---------------------------------------------------------------------------
-
-BootAnimation::BootAnimation(const sp<ISurfaceComposer>& composer) :
-    Thread(false) {
-    mSession = SurfaceComposerClient::clientForConnection(
-            composer->createConnection()->asBinder());
-}
-
-BootAnimation::~BootAnimation() {
-}
-
-void BootAnimation::onFirstRef() {
-    run("BootAnimation", PRIORITY_DISPLAY);
-}
-
-const sp<SurfaceComposerClient>& BootAnimation::session() const {
-    return mSession;
-}
-
-status_t BootAnimation::initTexture(Texture* texture, AssetManager& assets,
-        const char* name) {
-    Asset* asset = assets.open(name, Asset::ACCESS_BUFFER);
-    if (!asset)
-        return NO_INIT;
-    SkBitmap bitmap;
-    SkImageDecoder::DecodeMemory(asset->getBuffer(false), asset->getLength(),
-            &bitmap, SkBitmap::kNo_Config, SkImageDecoder::kDecodePixels_Mode);
-    asset->close();
-    delete asset;
-
-    // ensure we can call getPixels(). No need to call unlock, since the
-    // bitmap will go out of scope when we return from this method.
-    bitmap.lockPixels();
-
-    const int w = bitmap.width();
-    const int h = bitmap.height();
-    const void* p = bitmap.getPixels();
-
-    GLint crop[4] = { 0, h, w, -h };
-    texture->w = w;
-    texture->h = h;
-
-    glGenTextures(1, &texture->name);
-    glBindTexture(GL_TEXTURE_2D, texture->name);
-
-    switch (bitmap.getConfig()) {
-        case SkBitmap::kA8_Config:
-            glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_ALPHA,
-                    GL_UNSIGNED_BYTE, p);
-            break;
-        case SkBitmap::kARGB_4444_Config:
-            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA,
-                    GL_UNSIGNED_SHORT_4_4_4_4, p);
-            break;
-        case SkBitmap::kARGB_8888_Config:
-            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA,
-                    GL_UNSIGNED_BYTE, p);
-            break;
-        case SkBitmap::kRGB_565_Config:
-            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB,
-                    GL_UNSIGNED_SHORT_5_6_5, p);
-            break;
-        default:
-            break;
-    }
-
-    glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop);
-    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
-    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
-    return NO_ERROR;
-}
-
-status_t BootAnimation::readyToRun() {
-    mAssets.addDefaultAssets();
-
-    DisplayInfo dinfo;
-    status_t status = session()->getDisplayInfo(0, &dinfo);
-    if (status)
-        return -1;
-
-    // create the native surface
-    sp<Surface> s = session()->createSurface(getpid(), 0, dinfo.w, dinfo.h,
-            PIXEL_FORMAT_RGB_565);
-    session()->openTransaction();
-    s->setLayer(0x40000000);
-    session()->closeTransaction();
-
-    // initialize opengl and egl
-    const EGLint attribs[] = { EGL_RED_SIZE, 5, EGL_GREEN_SIZE, 6,
-            EGL_BLUE_SIZE, 5, EGL_DEPTH_SIZE, 0, EGL_NONE };
-    EGLint w, h, dummy;
-    EGLint numConfigs;
-    EGLConfig config;
-    EGLSurface surface;
-    EGLContext context;
-    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
-    eglChooseConfig(display, attribs, &config, 1, &numConfigs);
-
-    mNativeWindowSurface = new EGLNativeWindowSurface(s);
-    surface = eglCreateWindowSurface(display, config, 
-            mNativeWindowSurface.get(), NULL);
-
-    context = eglCreateContext(display, config, NULL, NULL);
-    eglQuerySurface(display, surface, EGL_WIDTH, &w);
-    eglQuerySurface(display, surface, EGL_HEIGHT, &h);
-    eglMakeCurrent(display, surface, surface, context);
-    mDisplay = display;
-    mContext = context;
-    mSurface = surface;
-    mWidth = w;
-    mHeight = h;
-    mFlingerSurface = s;
-
-    // initialize GL
-    glShadeModel(GL_FLAT);
-    glEnable(GL_TEXTURE_2D);
-    glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
-
-    return NO_ERROR;
-}
-
-void BootAnimation::requestExit() {
-    mBarrier.open();
-    Thread::requestExit();
-}
-
-bool BootAnimation::threadLoop() {
-    bool r = android();
-    eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
-    eglDestroyContext(mDisplay, mContext);
-    eglDestroySurface(mDisplay, mSurface);
-    mNativeWindowSurface.clear();
-    return r;
-}
-
-bool BootAnimation::android() {
-    initTexture(&mAndroid[0], mAssets, "images/android-logo-mask.png");
-    initTexture(&mAndroid[1], mAssets, "images/android-logo-shine.png");
-
-    // clear screen
-    glDisable(GL_DITHER);
-    glDisable(GL_SCISSOR_TEST);
-    glClear(GL_COLOR_BUFFER_BIT);
-    eglSwapBuffers(mDisplay, mSurface);
-
-    const GLint xc = (mWidth  - mAndroid[0].w) / 2;
-    const GLint yc = (mHeight - mAndroid[0].h) / 2;
-    const Rect updateRect(xc, yc, xc + mAndroid[0].w, yc + mAndroid[0].h);
-
-    // draw and update only what we need
-    mNativeWindowSurface->setSwapRectangle(updateRect.left,
-            updateRect.top, updateRect.width(), updateRect.height());
-
-    glEnable(GL_SCISSOR_TEST);
-    glScissor(updateRect.left, mHeight - updateRect.bottom, updateRect.width(),
-            updateRect.height());
-
-    // Blend state
-    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-    glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
-
-    const nsecs_t startTime = systemTime();
-    do {
-        nsecs_t now = systemTime();
-        double time = now - startTime;
-        float t = 4.0f * float(time / us2ns(16667)) / mAndroid[1].w;
-        GLint offset = (1 - (t - floorf(t))) * mAndroid[1].w;
-        GLint x = xc - offset;
-
-        glDisable(GL_BLEND);
-        glBindTexture(GL_TEXTURE_2D, mAndroid[1].name);
-        glDrawTexiOES(x,                 yc, 0, mAndroid[1].w, mAndroid[1].h);
-        glDrawTexiOES(x + mAndroid[1].w, yc, 0, mAndroid[1].w, mAndroid[1].h);
-
-        glEnable(GL_BLEND);
-        glBindTexture(GL_TEXTURE_2D, mAndroid[0].name);
-        glDrawTexiOES(xc, yc, 0, mAndroid[0].w, mAndroid[0].h);
-
-        eglSwapBuffers(mDisplay, mSurface);
-        
-        // 12fps: don't animate too fast to preserve CPU
-        const nsecs_t sleepTime = 83333 - ns2us(systemTime() - now);
-        if (sleepTime > 0)
-            usleep(sleepTime); 
-    } while (!exitPending());
-
-    glDeleteTextures(1, &mAndroid[0].name);
-    glDeleteTextures(1, &mAndroid[1].name);
-    return false;
-}
-
-// ---------------------------------------------------------------------------
-
-}
-; // namespace android
diff --git a/libs/surfaceflinger/BootAnimation.h b/libs/surfaceflinger/BootAnimation.h
deleted file mode 100644
index 3fb6670..0000000
--- a/libs/surfaceflinger/BootAnimation.h
+++ /dev/null
@@ -1,83 +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_BOOTANIMATION_H
-#define ANDROID_BOOTANIMATION_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <utils/threads.h>
-#include <utils/AssetManager.h>
-
-#include <ui/ISurfaceComposer.h>
-#include <ui/SurfaceComposerClient.h>
-
-#include <EGL/egl.h>
-#include <GLES/gl.h>
-
-#include "Barrier.h"
-
-class SkBitmap;
-
-namespace android {
-
-class AssetManager;
-class EGLNativeWindowSurface;
-
-// ---------------------------------------------------------------------------
-
-class BootAnimation : public Thread
-{
-public:
-                BootAnimation(const sp<ISurfaceComposer>& composer);
-    virtual     ~BootAnimation();
-
-    const sp<SurfaceComposerClient>& session() const;
-    virtual void        requestExit();
-
-private:
-    virtual bool        threadLoop();
-    virtual status_t    readyToRun();
-    virtual void        onFirstRef();
-
-    struct Texture {
-        GLint   w;
-        GLint   h;
-        GLuint  name;
-    };
-
-    status_t initTexture(Texture* texture, AssetManager& asset, const char* name);
-    bool android();
-
-    sp<SurfaceComposerClient>       mSession;
-    AssetManager mAssets;
-    Texture     mAndroid[2];
-    int         mWidth;
-    int         mHeight;
-    EGLDisplay  mDisplay;
-    EGLDisplay  mContext;
-    EGLDisplay  mSurface;
-    sp<Surface> mFlingerSurface;
-    sp<EGLNativeWindowSurface> mNativeWindowSurface;
-    Barrier mBarrier;
-};
-
-// ---------------------------------------------------------------------------
-
-}; // namespace android
-
-#endif // ANDROID_BOOTANIMATION_H
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
index f14d7e9..ab02fa0 100644
--- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
+++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
@@ -189,9 +189,17 @@
     
     
     char property[PROPERTY_VALUE_MAX];
-    if (property_get("ro.sf.lcd_density", property, NULL) <= 0) {
-        LOGW("ro.sf.lcd_density not defined, using 160 dpi by default.");
-        strcpy(property, "160");
+    /* Read density from build-specific ro.sf.lcd_density property
+     * except if it is overriden 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) {
+            LOGW("ro.sf.lcd_density not defined, using 160 dpi by default.");
+            strcpy(property, "160");
+        }
+    } else {
+        /* for the emulator case, reset the dpi values too */
+        mDpiX = mDpiY = atoi(property);
     }
     mDensity = atoi(property) * (1.0f/160.0f);
 
diff --git a/libs/surfaceflinger/GPUHardware/GPUHardware.cpp b/libs/surfaceflinger/GPUHardware/GPUHardware.cpp
index eb75f99..7168bf2 100644
--- a/libs/surfaceflinger/GPUHardware/GPUHardware.cpp
+++ b/libs/surfaceflinger/GPUHardware/GPUHardware.cpp
@@ -573,7 +573,11 @@
 
 sp<GPUHardwareInterface> GPUFactory::getGPU()
 {
-    return new GPUHardware();
+    sp<GPUHardwareInterface> gpu;
+    if (access("/dev/hw3d", F_OK) == 0) {
+        gpu = new GPUHardware();
+    }
+    return gpu;
 }
 
 // ---------------------------------------------------------------------------
diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp
index f65d669..96395a8 100644
--- a/libs/surfaceflinger/Layer.cpp
+++ b/libs/surfaceflinger/Layer.cpp
@@ -108,7 +108,7 @@
     // we always force a 4-byte aligned bpr.
     uint32_t alignment = 1;
 
-    if (flags & ISurfaceComposer::eGPU) {
+    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
diff --git a/libs/surfaceflinger/LayerBitmap.cpp b/libs/surfaceflinger/LayerBitmap.cpp
index e844350..397ddc8 100644
--- a/libs/surfaceflinger/LayerBitmap.cpp
+++ b/libs/surfaceflinger/LayerBitmap.cpp
@@ -114,7 +114,9 @@
     }
 
     if (mBitsMemory==0 || mSurface.data==0) {
-        LOGE("not enough memory for layer bitmap size=%u", size);
+        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;
diff --git a/libs/surfaceflinger/LayerOrientationAnim.cpp b/libs/surfaceflinger/LayerOrientationAnim.cpp
index 3e4035e..79e5328 100644
--- a/libs/surfaceflinger/LayerOrientationAnim.cpp
+++ b/libs/surfaceflinger/LayerOrientationAnim.cpp
@@ -46,10 +46,7 @@
 // Animation...
 const float DURATION = ms2ns(200);
 const float BOUNCES_PER_SECOND = 0.5f;
-//const float BOUNCES_AMPLITUDE = 1.0f/16.0f;
-const float BOUNCES_AMPLITUDE = 0;
 const float DIM_TARGET = 0.40f;
-//#define INTERPOLATED_TIME(_t)   ((_t)*(_t))
 #define INTERPOLATED_TIME(_t)   (_t)
 
 // ---------------------------------------------------------------------------
@@ -64,14 +61,8 @@
       mTextureName(-1), mTextureNameIn(-1)
 {
     // blur that texture. 
-    mStartTime = systemTime();
-    mFinishTime = 0;
     mOrientationCompleted = false;
-    mFirstRedraw = false;
-    mLastNormalizedTime = 0;
     mNeedsBlending = false;
-    mAlphaInLerp.set(1.0f, DIM_TARGET);
-    mAlphaOutLerp.set(0.5f, 1.0f);
 }
 
 LayerOrientationAnim::~LayerOrientationAnim()
@@ -117,108 +108,37 @@
 
 void LayerOrientationAnim::onOrientationCompleted()
 {
-    mFinishTime = systemTime();
-    mOrientationCompleted = true;
-    mFirstRedraw = true;
-    mNeedsBlending = true;
-    mFlinger->invalidateLayerVisibility(this);
+    mAnim->onAnimationFinished();
 }
 
 void LayerOrientationAnim::onDraw(const Region& clip) const
 {
-    const nsecs_t now = systemTime();
-    float alphaIn, alphaOut;
+    float alphaIn =  DIM_TARGET;
     
-    if (mOrientationCompleted) {
-        if (mFirstRedraw) {
-            mFirstRedraw = false;
-            
-            // make a copy of what's on screen
-            copybit_image_t image;
-            mBitmapOut.getBitmapSurface(&image);
-            const DisplayHardware& hw(graphicPlane(0).displayHardware());
-            hw.copyBackToImage(image);
-
-            // and erase the screen for this round
-            glDisable(GL_BLEND);
-            glDisable(GL_DITHER);
-            glDisable(GL_SCISSOR_TEST);
-            glClearColor(0,0,0,0);
-            glClear(GL_COLOR_BUFFER_BIT);
-            
-            // FIXME: code below is gross
-            mNeedsBlending = false;
-            LayerOrientationAnim* self(const_cast<LayerOrientationAnim*>(this));
-            mFlinger->invalidateLayerVisibility(self);
-        }
-
-        // make sure pick-up where we left off
-        const float duration = DURATION * mLastNormalizedTime;
-        const float normalizedTime = (float(now - mFinishTime) / duration);
-        if (normalizedTime <= 1.0f) {
-            const float interpolatedTime = INTERPOLATED_TIME(normalizedTime);
-            alphaIn = mAlphaInLerp.getOut();
-            alphaOut = mAlphaOutLerp(interpolatedTime);
-        } else {
-            mAnim->onAnimationFinished();
-            alphaIn = mAlphaInLerp.getOut();
-            alphaOut = mAlphaOutLerp.getOut();
-        }
-    } else {
-        const float normalizedTime = float(now - mStartTime) / DURATION;
-        if (normalizedTime <= 1.0f) {
-            mLastNormalizedTime = normalizedTime;
-            const float interpolatedTime = INTERPOLATED_TIME(normalizedTime);
-            alphaIn = mAlphaInLerp(interpolatedTime);
-            alphaOut = 0.0f;
-        } else {
-            mLastNormalizedTime = 1.0f;
-            const float to_seconds = DURATION / seconds(1);
-            alphaIn = mAlphaInLerp.getOut();
-            if (BOUNCES_AMPLITUDE > 0.0f) {
-                const float phi = BOUNCES_PER_SECOND * 
-                        (((normalizedTime - 1.0f) * to_seconds)*M_PI*2);
-                if (alphaIn > 1.0f) alphaIn = 1.0f;
-                else if (alphaIn < 0.0f) alphaIn = 0.0f;
-                alphaIn += BOUNCES_AMPLITUDE * (1.0f - cosf(phi));
-            }
-            alphaOut = 0.0f;
-        }
-        mAlphaOutLerp.setIn(alphaIn);
+    // 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);
     }
-    drawScaled(1.0f, alphaIn, alphaOut);
-}
-
-void LayerOrientationAnim::drawScaled(float scale, float alphaIn, float alphaOut) const
-{
+    
     copybit_image_t dst;
     const GraphicPlane& plane(graphicPlane(0));
     const DisplayHardware& hw(plane.displayHardware());
     hw.getDisplaySurface(&dst);
 
-    // clear screen
-    // TODO: with update on demand, we may be able 
-    // to not erase the screen at all during the animation 
-    if (!mOrientationCompleted) {
-        if (scale==1.0f && (alphaIn>=1.0f || alphaOut>=1.0f)) {
-            // we don't need to erase the screen in that case
-        } else {
-            glDisable(GL_BLEND);
-            glDisable(GL_DITHER);
-            glDisable(GL_SCISSOR_TEST);
-            glClearColor(0,0,0,0);
-            glClear(GL_COLOR_BUFFER_BIT);
-        }
-    }
-    
     copybit_image_t src;
     mBitmapIn.getBitmapSurface(&src);
 
     copybit_image_t srcOut;
     mBitmapOut.getBitmapSurface(&srcOut);
 
-    const int w = dst.w*scale; 
-    const int h = dst.h*scale; 
+    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 }; 
@@ -237,13 +157,7 @@
             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);
-        }
-
-        if (!err && alphaOut > 0.0f) {
-            region_iterator it(reg);
             copybit->set_parameter(copybit, COPYBIT_BLUR, COPYBIT_DISABLE);
-            copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, int(alphaOut*255));
-            err = copybit->stretch(copybit, &dst, &srcOut, &drect, &srect, &it);
         }
         LOGE_IF(err != NO_ERROR, "copybit failed (%s)", strerror(err));
     }
@@ -258,7 +172,6 @@
         t.data = (GGLubyte*)(intptr_t(src.base) + src.offset);
 
         Transform tr;
-        tr.set(scale,0,0,scale);
         tr.set(xc, yc);
         
         // FIXME: we should not access mVertices and mDrawingState like that,
@@ -285,18 +198,6 @@
             self.mDrawingState.alpha = int(alphaIn*255);
             drawWithOpenGL(reg, mTextureNameIn, t);
         }
-
-        if (alphaOut > 0.0f) {
-            t.data = (GGLubyte*)(intptr_t(srcOut.base) + srcOut.offset);
-            if (UNLIKELY(mTextureName == -1LU)) {
-                mTextureName = createTexture();
-                GLuint w=0, h=0;
-                const Region dirty(Rect(t.width, t.height));
-                loadTexture(dirty, mTextureName, t, w, h);
-            }
-            self.mDrawingState.alpha = int(alphaOut*255);
-            drawWithOpenGL(reg, mTextureName, t);
-        }
     }
 }
 
diff --git a/libs/surfaceflinger/LayerOrientationAnim.h b/libs/surfaceflinger/LayerOrientationAnim.h
index 365c6ae..12b6f1c 100644
--- a/libs/surfaceflinger/LayerOrientationAnim.h
+++ b/libs/surfaceflinger/LayerOrientationAnim.h
@@ -64,45 +64,13 @@
     virtual bool needsBlending() const;
     virtual bool isSecure() const       { return false; }
 private:
-    void drawScaled(float scale, float alphaIn, float alphaOut) const;
-
-    class Lerp {
-        float in;
-        float outMinusIn;
-    public:
-        Lerp() : in(0), outMinusIn(0) { }
-        Lerp(float in, float out) : in(in), outMinusIn(out-in) { }
-        float getIn() const { return in; };
-        float getOut() const { return in + outMinusIn; }
-        void set(float in, float out) { 
-            this->in = in; 
-            this->outMinusIn = out-in; 
-        }
-        void setIn(float in) { 
-            this->in = in; 
-        }
-        void setOut(float out) { 
-            this->outMinusIn = out - this->in; 
-        }
-        float operator()(float t) const { 
-            return outMinusIn*t + in; 
-        }
-    };
-    
     OrientationAnimation* mAnim;
     LayerBitmap mBitmapIn;
     LayerBitmap mBitmapOut;
-    nsecs_t mStartTime;
-    nsecs_t mFinishTime;
     bool mOrientationCompleted;
-    mutable bool mFirstRedraw;
-    mutable float mLastNormalizedTime;
     mutable GLuint  mTextureName;
     mutable GLuint  mTextureNameIn;
     mutable bool mNeedsBlending;
-    
-    mutable Lerp mAlphaInLerp;
-    mutable Lerp mAlphaOutLerp;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/libs/surfaceflinger/LayerOrientationAnimRotate.cpp b/libs/surfaceflinger/LayerOrientationAnimRotate.cpp
deleted file mode 100644
index 89ffb19..0000000
--- a/libs/surfaceflinger/LayerOrientationAnimRotate.cpp
+++ /dev/null
@@ -1,274 +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 <core/SkBitmap.h>
-
-#include <ui/EGLDisplaySurface.h>
-
-#include "LayerBase.h"
-#include "LayerOrientationAnim.h"
-#include "LayerOrientationAnimRotate.h"
-#include "SurfaceFlinger.h"
-#include "DisplayHardware/DisplayHardware.h"
-#include "OrientationAnimation.h"
-
-namespace android {
-// ---------------------------------------------------------------------------
-
-const uint32_t LayerOrientationAnimRotate::typeInfo = LayerBase::typeInfo | 0x100;
-const char* const LayerOrientationAnimRotate::typeID = "LayerOrientationAnimRotate";
-
-// ---------------------------------------------------------------------------
-
-const float ROTATION = M_PI * 0.5f;
-const float ROTATION_FACTOR = 1.0f; // 1.0 or 2.0
-const float DURATION = ms2ns(200);
-const float BOUNCES_PER_SECOND = 0.8;
-const float BOUNCES_AMPLITUDE = (5.0f/180.f) * M_PI;
-
-LayerOrientationAnimRotate::LayerOrientationAnimRotate(
-        SurfaceFlinger* flinger, DisplayID display, 
-        OrientationAnimation* anim, 
-        const LayerBitmap& bitmap,
-        const LayerBitmap& bitmapIn)
-    : LayerOrientationAnimBase(flinger, display), mAnim(anim), 
-      mBitmap(bitmap), mBitmapIn(bitmapIn), 
-      mTextureName(-1), mTextureNameIn(-1)
-{
-    mStartTime = systemTime();
-    mFinishTime = 0;
-    mOrientationCompleted = false;
-    mFirstRedraw = false;
-    mLastNormalizedTime = 0;
-    mLastAngle = 0;
-    mLastScale = 0;
-    mNeedsBlending = false;
-    const GraphicPlane& plane(graphicPlane(0));
-    mOriginalTargetOrientation = plane.getOrientation(); 
-}
-
-LayerOrientationAnimRotate::~LayerOrientationAnimRotate()
-{
-    if (mTextureName != -1U) {
-        LayerBase::deletedTextures.add(mTextureName);
-    }
-    if (mTextureNameIn != -1U) {
-        LayerBase::deletedTextures.add(mTextureNameIn);
-    }
-}
-
-bool LayerOrientationAnimRotate::needsBlending() const 
-{
-    return mNeedsBlending; 
-}
-
-Point LayerOrientationAnimRotate::getPhysicalSize() const
-{
-    const GraphicPlane& plane(graphicPlane(0));
-    const DisplayHardware& hw(plane.displayHardware());
-    return Point(hw.getWidth(), hw.getHeight());
-}
-
-void LayerOrientationAnimRotate::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;
-}
-
-void LayerOrientationAnimRotate::onOrientationCompleted()
-{
-    mFinishTime = systemTime();
-    mOrientationCompleted = true;
-    mFirstRedraw = true;
-    mNeedsBlending = true;
-    mFlinger->invalidateLayerVisibility(this);
-}
-
-void LayerOrientationAnimRotate::onDraw(const Region& clip) const
-{
-    // Animation...
-
-    const nsecs_t now = systemTime();
-    float angle, scale, alpha;
-    
-    if (mOrientationCompleted) {
-        if (mFirstRedraw) {
-            // make a copy of what's on screen
-            copybit_image_t image;
-            mBitmapIn.getBitmapSurface(&image);
-            const DisplayHardware& hw(graphicPlane(0).displayHardware());
-            hw.copyBackToImage(image);
-            
-            // FIXME: code below is gross
-            mFirstRedraw = false; 
-            mNeedsBlending = false;
-            LayerOrientationAnimRotate* self(const_cast<LayerOrientationAnimRotate*>(this));
-            mFlinger->invalidateLayerVisibility(self);
-        }
-
-        // make sure pick-up where we left off
-        const float duration = DURATION * mLastNormalizedTime;
-        const float normalizedTime = (float(now - mFinishTime) / duration);
-        if (normalizedTime <= 1.0f) {
-            const float squaredTime = normalizedTime*normalizedTime;
-            angle = (ROTATION*ROTATION_FACTOR - mLastAngle)*squaredTime + mLastAngle;
-            scale = (1.0f - mLastScale)*squaredTime + mLastScale;
-            alpha = normalizedTime;
-        } else {
-            mAnim->onAnimationFinished();
-            angle = ROTATION;
-            alpha = 1.0f;
-            scale = 1.0f;
-        }
-    } else {
-        // FIXME: works only for portrait framebuffers
-        const Point size(getPhysicalSize());
-        const float TARGET_SCALE = size.x * (1.0f / size.y);
-        const float normalizedTime = float(now - mStartTime) / DURATION;
-        if (normalizedTime <= 1.0f) {
-            mLastNormalizedTime = normalizedTime;
-            const float squaredTime = normalizedTime*normalizedTime;
-            angle = ROTATION * squaredTime;
-            scale = (TARGET_SCALE - 1.0f)*squaredTime + 1.0f;
-            alpha = 0;
-        } else {
-            mLastNormalizedTime = 1.0f;
-            angle = ROTATION;
-            if (BOUNCES_AMPLITUDE) {
-                const float to_seconds = DURATION / seconds(1);
-                const float phi = BOUNCES_PER_SECOND * 
-                (((normalizedTime - 1.0f) * to_seconds)*M_PI*2);
-                angle += BOUNCES_AMPLITUDE * sinf(phi);
-            }
-            scale = TARGET_SCALE;
-            alpha = 0;
-        }
-        mLastAngle = angle;
-        mLastScale = scale;
-    }
-    drawScaled(angle, scale, alpha);
-}
-
-void LayerOrientationAnimRotate::drawScaled(float f, float s, float alpha) const
-{
-    copybit_image_t dst;
-    const GraphicPlane& plane(graphicPlane(0));
-    const DisplayHardware& hw(plane.displayHardware());
-    hw.getDisplaySurface(&dst);
-
-    // clear screen
-    // TODO: with update on demand, we may be able 
-    // to not erase the screen at all during the animation 
-    glDisable(GL_BLEND);
-    glDisable(GL_DITHER);
-    glDisable(GL_SCISSOR_TEST);
-    glClearColor(0,0,0,0);
-    glClear(GL_COLOR_BUFFER_BIT);
-    
-    const int w = dst.w; 
-    const int h = dst.h; 
-
-    copybit_image_t src;
-    mBitmap.getBitmapSurface(&src);
-    const copybit_rect_t srect = { 0, 0, src.w, src.h };
-
-
-    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);
-
-    if (!mOriginalTargetOrientation) {
-        f = -f;
-    }
-
-    Transform tr;
-    tr.set(f, w*0.5f, h*0.5f);
-    tr.scale(s, w*0.5f, h*0.5f);
-
-    // 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.
-    LayerOrientationAnimRotate& self(const_cast<LayerOrientationAnimRotate&>(*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 (UNLIKELY(mTextureName == -1LU)) {
-        mTextureName = createTexture();
-        GLuint w=0, h=0;
-        const Region dirty(Rect(t.width, t.height));
-        loadTexture(dirty, mTextureName, t, w, h);
-    }
-    self.mDrawingState.alpha = 255; //-int(alpha*255);
-    const Region clip(Rect( srect.l, srect.t, srect.r, srect.b ));
-    drawWithOpenGL(clip, mTextureName, t);
-    
-    if (alpha > 0) {
-        const float sign = (!mOriginalTargetOrientation) ? 1.0f : -1.0f;
-        tr.set(f + sign*(M_PI * 0.5f * ROTATION_FACTOR), w*0.5f, h*0.5f);
-        tr.scale(s, w*0.5f, h*0.5f);
-        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);
-
-        copybit_image_t src;
-        mBitmapIn.getBitmapSurface(&src);
-        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(alpha*255);
-        const Region clip(Rect( srect.l, srect.t, srect.r, srect.b ));
-        drawWithOpenGL(clip, mTextureNameIn, t);
-    }
-}
-
-// ---------------------------------------------------------------------------
-
-}; // namespace android
diff --git a/libs/surfaceflinger/LayerOrientationAnimRotate.h b/libs/surfaceflinger/LayerOrientationAnimRotate.h
deleted file mode 100644
index 5fbbd42..0000000
--- a/libs/surfaceflinger/LayerOrientationAnimRotate.h
+++ /dev/null
@@ -1,77 +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_ROTATE_H
-#define ANDROID_LAYER_ORIENTATION_ANIM_ROTATE_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 LayerOrientationAnimRotate : 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; }
-    
-    LayerOrientationAnimRotate(SurfaceFlinger* flinger, DisplayID display,
-                        OrientationAnimation* anim, 
-                        const LayerBitmap& zoomOut,
-                        const LayerBitmap& zoomIn);
-        virtual ~LayerOrientationAnimRotate();
-
-            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:
-    void drawScaled(float angle, float scale, float alpha) const;
-    
-    OrientationAnimation* mAnim;
-    LayerBitmap mBitmap;
-    LayerBitmap mBitmapIn;
-    nsecs_t mStartTime;
-    nsecs_t mFinishTime;
-    bool mOrientationCompleted;
-    int mOriginalTargetOrientation;
-    mutable bool mFirstRedraw;
-    mutable float mLastNormalizedTime;
-    mutable float mLastAngle;
-    mutable float mLastScale;
-    mutable GLuint  mTextureName;
-    mutable GLuint  mTextureNameIn;
-    mutable bool mNeedsBlending;
-};
-
-// ---------------------------------------------------------------------------
-
-}; // namespace android
-
-#endif // ANDROID_LAYER_ORIENTATION_ANIM_ROTATE_H
diff --git a/libs/surfaceflinger/OrientationAnimation.cpp b/libs/surfaceflinger/OrientationAnimation.cpp
index 70eec8d..12c0eef 100644
--- a/libs/surfaceflinger/OrientationAnimation.cpp
+++ b/libs/surfaceflinger/OrientationAnimation.cpp
@@ -21,7 +21,6 @@
 #include <limits.h>
 
 #include "LayerOrientationAnim.h"
-#include "LayerOrientationAnimRotate.h"
 #include "OrientationAnimation.h"
 #include "SurfaceFlinger.h"
 #include "VRamHeap.h"
@@ -112,13 +111,8 @@
 
     LayerOrientationAnimBase* l;
     
-    if (mType & 0x80) {
-        l = new LayerOrientationAnimRotate(
-                mFlinger.get(), 0, this, bitmap, bitmapIn);
-    } else {
-        l = new LayerOrientationAnim(
-                mFlinger.get(), 0, this, bitmap, bitmapIn);
-    }
+    l = new LayerOrientationAnim(
+            mFlinger.get(), 0, this, bitmap, bitmapIn);
 
     l->initStates(w, h, 0);
     l->setLayer(INT_MAX-1);
@@ -137,7 +131,7 @@
         return true;
         
     }
-    mLayerOrientationAnim->invalidate();
+    //mLayerOrientationAnim->invalidate();
     return false;
 }
 
diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp
index c2adf07..7a277fe 100644
--- a/libs/surfaceflinger/SurfaceFlinger.cpp
+++ b/libs/surfaceflinger/SurfaceFlinger.cpp
@@ -62,6 +62,13 @@
 #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
+ */
+#ifndef AID_GRAPHICS
+#define AID_GRAPHICS 1003
+#endif
+
 #define DISPLAY_COUNT       1
 
 namespace android {
@@ -185,7 +192,6 @@
         mDebugCpu(0),
         mDebugFps(0),
         mDebugBackground(0),
-        mDebugNoBootAnimation(0),
         mSyncObject(),
         mDeplayedTransactionPending(0),
         mConsoleSignals(0),
@@ -208,14 +214,11 @@
     mDebugBackground = atoi(value);
     property_get("debug.sf.showfps", value, "0");
     mDebugFps = atoi(value);
-    property_get("debug.sf.nobootanimation", value, "0");
-    mDebugNoBootAnimation = atoi(value);
 
     LOGI_IF(mDebugRegion,           "showupdates enabled");
     LOGI_IF(mDebugCpu,              "showcpu enabled");
     LOGI_IF(mDebugBackground,       "showbackground enabled");
     LOGI_IF(mDebugFps,              "showfps enabled");
-    LOGI_IF(mDebugNoBootAnimation,  "boot animation disabled");
 }
 
 SurfaceFlinger::~SurfaceFlinger()
@@ -242,6 +245,9 @@
 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);
@@ -250,6 +256,9 @@
 
 status_t SurfaceFlinger::revokeGPU()
 {
+    if (mGPU == 0)
+        return INVALID_OPERATION;
+
     return mGPU->friendlyRevoke();
 }
 
@@ -319,11 +328,8 @@
 {
     const nsecs_t now = systemTime();
     const nsecs_t duration = now - mBootTime;
-    LOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) );
-    if (mBootAnimation != 0) {
-        mBootAnimation->requestExit();
-        mBootAnimation.clear();
-    }
+    LOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) );  
+    property_set("ctl.stop", "bootanim");
 }
 
 void SurfaceFlinger::onFirstRef()
@@ -451,10 +457,10 @@
     if (mDebugCpu)
         mCpuGauge = new CPUGauge(this, ms2ns(500));
 
-    // the boot animation!
-    if (mDebugNoBootAnimation == false)
-        mBootAnimation = new BootAnimation(this);
-
+    
+    // start boot animation
+    property_set("ctl.start", "bootanim");
+    
     return NO_ERROR;
 }
 
@@ -686,9 +692,14 @@
 
         // some layers might have been removed, so
         // we need to update the regions they're exposing.
-        size_t c = mRemovedLayers.size();
+        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;
@@ -728,17 +739,15 @@
         layer->validateVisibility(planeTransform);
 
         // start with the whole surface at its current location
-        const Layer::State& s = layer->drawingState();
-        const Rect bounds(layer->visibleBounds());
+        const Layer::State& s(layer->drawingState());
 
         // handle hidden surfaces by setting the visible region to empty
         Region opaqueRegion;
         Region visibleRegion;
         Region coveredRegion;
-        if (UNLIKELY((s.flags & ISurfaceComposer::eLayerHidden) || !s.alpha)) {
-            visibleRegion.clear();
-        } else {
+        if (LIKELY(!(s.flags & ISurfaceComposer::eLayerHidden) && s.alpha)) {
             const bool translucent = layer->needsBlending();
+            const Rect bounds(layer->visibleBounds());
             visibleRegion.set(bounds);
             coveredRegion = visibleRegion;
 
@@ -766,10 +775,11 @@
             dirty.orSelf(layer->visibleRegionScreen);
             layer->contentDirty = false;
         } else {
-            // compute the exposed region
-            // dirty = what's visible now - what's wasn't covered before
-            //       = what's visible now & what's was covered before
-            dirty = visibleRegion.intersect(layer->coveredRegionScreen);            
+            /* compute the exposed region:
+             *    exposed = what's VISIBLE and NOT COVERED now 
+             *    but was COVERED before
+             */
+            dirty = (visibleRegion - coveredRegion) & layer->coveredRegionScreen;
         }
         dirty.subtractSelf(aboveOpaqueLayers);
 
@@ -778,18 +788,22 @@
 
         // updade aboveOpaqueLayers/aboveCoveredLayers for next (lower) layer
         aboveOpaqueLayers.orSelf(opaqueRegion);
-        aboveCoveredLayers.orSelf(bounds);
+        aboveCoveredLayers.orSelf(visibleRegion);
         
         // Store the visible region is screen space
         layer->setVisibleRegion(visibleRegion);
         layer->setCoveredRegion(coveredRegion);
 
-        // If a secure layer is partially visible, lockdown the screen!
+        // If a secure layer is partially visible, lock-down the screen!
         if (layer->isSecure() && !visibleRegion.isEmpty()) {
             secureFrameBuffer = true;
         }
     }
 
+    // invalidate the areas where a layer was removed
+    dirtyRegion.orSelf(mDirtyRegionRemovedLayer);
+    mDirtyRegionRemovedLayer.clear();
+
     mSecureFrameBuffer = secureFrameBuffer;
     opaqueRegion = aboveOpaqueLayers;
 }
@@ -1230,6 +1244,13 @@
 {
     LayerBaseClient* layer = 0;
     sp<LayerBaseClient::Surface> surfaceHandle;
+
+    if (int32_t(w|h) < 0) {
+        LOGE("createSurface() failed, w or h is negative (w=%d, h=%d)",
+                int(w), int(h));
+        return surfaceHandle;
+    }
+    
     Mutex::Autolock _l(mStateLock);
     Client* const c = mClientsMap.valueFor(clientId);
     if (UNLIKELY(!c)) {
@@ -1538,13 +1559,13 @@
             // 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)) {
+            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")))
                 {
-                    const int uid = ipc->getCallingUid();
                     LOGE("Permission Denial: "
                             "can't access SurfaceFlinger pid=%d, uid=%d", pid, uid);
                     return PERMISSION_DENIED;
@@ -1601,10 +1622,14 @@
             }
             return NO_ERROR;
             case 1005: // ask GPU revoke
-                mGPU->friendlyRevoke();
+                if (mGPU != 0) {
+                    mGPU->friendlyRevoke();
+                }
                 return NO_ERROR;
             case 1006: // revoke GPU
-                mGPU->unconditionalRevoke();
+                if (mGPU != 0) {
+                    mGPU->unconditionalRevoke();
+                }
                 return NO_ERROR;
             case 1007: // set mFreezeCount
                 mFreezeCount = data.readInt32();
diff --git a/libs/surfaceflinger/SurfaceFlinger.h b/libs/surfaceflinger/SurfaceFlinger.h
index e023182..0d63e1d 100644
--- a/libs/surfaceflinger/SurfaceFlinger.h
+++ b/libs/surfaceflinger/SurfaceFlinger.h
@@ -36,7 +36,6 @@
 #include <private/ui/SurfaceFlingerSynchro.h>
 
 #include "Barrier.h"
-#include "BootAnimation.h"
 #include "CPUGauge.h"
 #include "Layer.h"
 #include "Tokenizer.h"
@@ -347,12 +346,12 @@
                 sp<SurfaceHeapManager>      mSurfaceHeapManager;
                 sp<GPUHardwareInterface>    mGPU;
                 GLuint                      mWormholeTexName;
-                sp<BootAnimation>           mBootAnimation;
                 nsecs_t                     mBootTime;
                 
                 // Can only accessed from the main thread, these members
                 // don't need synchronization
                 Region                      mDirtyRegion;
+                Region                      mDirtyRegionRemovedLayer;
                 Region                      mInvalidRegion;
                 Region                      mWormholeRegion;
                 Client*                     mLastScheduledBroadcast;
@@ -374,7 +373,6 @@
                 int                         mDebugCpu;
                 int                         mDebugFps;
                 int                         mDebugBackground;
-                int                         mDebugNoBootAnimation;
 
                 // these are thread safe
     mutable     Barrier                     mReadyToRunBarrier;
diff --git a/libs/surfaceflinger/VRamHeap.cpp b/libs/surfaceflinger/VRamHeap.cpp
index 0ccd71f..5f633bd 100644
--- a/libs/surfaceflinger/VRamHeap.cpp
+++ b/libs/surfaceflinger/VRamHeap.cpp
@@ -35,6 +35,8 @@
 #include <utils/MemoryHeapPmem.h>
 #include <utils/MemoryHeapBase.h>
 
+#include <EGL/eglnatives.h>
+
 #include "GPUHardware/GPUHardware.h"
 #include "SurfaceFlinger.h"
 #include "VRamHeap.h"
@@ -98,7 +100,7 @@
         }
     }
 
-    if (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
diff --git a/libs/ui/Android.mk b/libs/ui/Android.mk
index f944357..7bbe38b 100644
--- a/libs/ui/Android.mk
+++ b/libs/ui/Android.mk
@@ -20,13 +20,11 @@
 	LayerState.cpp \
 	Overlay.cpp \
 	PixelFormat.cpp \
-	Point.cpp \
 	Rect.cpp \
 	Region.cpp \
 	Surface.cpp \
 	SurfaceComposerClient.cpp \
-	SurfaceFlingerSynchro.cpp \
-	Time.cpp
+	SurfaceFlingerSynchro.cpp 
 
 LOCAL_SHARED_LIBRARIES := \
 	libcorecg \
diff --git a/libs/ui/Camera.cpp b/libs/ui/Camera.cpp
index b3cbda1..5015379 100644
--- a/libs/ui/Camera.cpp
+++ b/libs/ui/Camera.cpp
@@ -64,34 +64,27 @@
     init();
 }
 
-Camera::Camera(const sp<ICamera>& camera)
+// construct a camera client from an existing camera remote
+sp<Camera> Camera::create(const sp<ICamera>& camera)
 {
-    init();
-    // connect this client to existing camera remote
-    if (camera->connect(this) == NO_ERROR) {
-        mStatus = NO_ERROR;
-        mCamera = camera;
-        camera->asBinder()->linkToDeath(this);
+     LOGV("create");
+     if (camera == 0) {
+         LOGE("camera remote is a NULL pointer");
+         return 0;
+     }
+
+    sp<Camera> c = new Camera();
+    if (camera->connect(c) == NO_ERROR) {
+        c->mStatus = NO_ERROR;
+        c->mCamera = camera;
+        camera->asBinder()->linkToDeath(c);
     }
+    return c;
 }
 
 void Camera::init()
 {
     mStatus = UNKNOWN_ERROR;
-    mShutterCallback = 0;
-    mShutterCallbackCookie = 0;
-    mRawCallback = 0;
-    mRawCallbackCookie = 0;
-    mJpegCallback = 0;
-    mJpegCallbackCookie = 0;
-    mPreviewCallback = 0;
-    mPreviewCallbackCookie = 0;
-    mRecordingCallback = 0;
-    mRecordingCallbackCookie = 0;
-    mErrorCallback = 0;
-    mErrorCallbackCookie = 0;
-    mAutoFocusCallback = 0;
-    mAutoFocusCallbackCookie = 0;
 }
 
 Camera::~Camera()
@@ -120,7 +113,6 @@
 {
     LOGV("disconnect");
     if (mCamera != 0) {
-        mErrorCallback = 0;
         mCamera->disconnect();
         mCamera = 0;
     }
@@ -157,21 +149,21 @@
 status_t Camera::setPreviewDisplay(const sp<Surface>& surface)
 {
     LOGV("setPreviewDisplay");
-    if (surface == 0) {
-        LOGE("app passed NULL surface");
-        return NO_INIT;
-    }
     sp <ICamera> c = mCamera;
     if (c == 0) return NO_INIT;
-    return c->setPreviewDisplay(surface->getISurface());
+    if (surface != 0) {
+        return c->setPreviewDisplay(surface->getISurface());
+    } else {
+        LOGD("app passed NULL surface");
+        return c->setPreviewDisplay(0);
+    }
 }
 
 status_t Camera::setPreviewDisplay(const sp<ISurface>& surface)
 {
     LOGV("setPreviewDisplay");
     if (surface == 0) {
-        LOGE("app passed NULL surface");
-        return NO_INIT;
+        LOGD("app passed NULL surface");
     }
     sp <ICamera> c = mCamera;
     if (c == 0) return NO_INIT;
@@ -179,7 +171,7 @@
 }
 
 
-// start preview mode, must call setPreviewDisplay first
+// start preview mode
 status_t Camera::startPreview()
 {
     LOGV("startPreview");
@@ -278,123 +270,62 @@
     return params;
 }
 
-void Camera::setAutoFocusCallback(autofocus_callback cb, void *cookie)
+void Camera::setListener(const sp<CameraListener>& listener)
 {
-    LOGV("setAutoFocusCallback");
-    mAutoFocusCallback = cb;
-    mAutoFocusCallbackCookie = cookie;
+    Mutex::Autolock _l(mLock);
+    mListener = listener;
 }
 
-void Camera::setShutterCallback(shutter_callback cb, void *cookie)
+void Camera::setPreviewCallbackFlags(int flag)
 {
-    LOGV("setShutterCallback");
-    mShutterCallback = cb;
-    mShutterCallbackCookie = cookie;
-}
-
-void Camera::setRawCallback(frame_callback cb, void *cookie)
-{
-    LOGV("setRawCallback");
-    mRawCallback = cb;
-    mRawCallbackCookie = cookie;
-}
-
-void Camera::setJpegCallback(frame_callback cb, void *cookie)
-{
-    LOGV("setJpegCallback");
-    mJpegCallback = cb;
-    mJpegCallbackCookie = cookie;
-}
-
-void Camera::setPreviewCallback(frame_callback cb, void *cookie, int flag)
-{
-    LOGV("setPreviewCallback");
-    mPreviewCallback = cb;
-    mPreviewCallbackCookie = cookie;
+    LOGV("setPreviewCallbackFlags");
     sp <ICamera> c = mCamera;
     if (c == 0) return;
     mCamera->setPreviewCallbackFlag(flag);
 }
 
-void Camera::setRecordingCallback(frame_callback cb, void *cookie)
+// callback from camera service
+void Camera::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2)
 {
-    LOGV("setRecordingCallback");
-    mRecordingCallback = cb;
-    mRecordingCallbackCookie = cookie;
-}
-
-void Camera::setErrorCallback(error_callback cb, void *cookie)
-{
-    LOGV("setErrorCallback");
-    mErrorCallback = cb;
-    mErrorCallbackCookie = cookie;
-}
-
-void Camera::autoFocusCallback(bool focused)
-{
-    LOGV("autoFocusCallback");
-    if (mAutoFocusCallback) {
-        mAutoFocusCallback(focused, mAutoFocusCallbackCookie);
+    sp<CameraListener> listener;
+    {
+        Mutex::Autolock _l(mLock);
+        listener = mListener;
+    }
+    if (listener != NULL) {
+        listener->notify(msgType, ext1, ext2);
     }
 }
 
-void Camera::shutterCallback()
+// callback from camera service when frame or image is ready
+void Camera::dataCallback(int32_t msgType, const sp<IMemory>& dataPtr)
 {
-    LOGV("shutterCallback");
-    if (mShutterCallback) {
-        mShutterCallback(mShutterCallbackCookie);
+    sp<CameraListener> listener;
+    {
+        Mutex::Autolock _l(mLock);
+        listener = mListener;
+    }
+    if (listener != NULL) {
+        listener->postData(msgType, dataPtr);
     }
 }
 
-void Camera::rawCallback(const sp<IMemory>& picture)
+// callback from camera service when timestamped frame is ready
+void Camera::dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr)
 {
-    LOGV("rawCallback");
-    if (mRawCallback) {
-        mRawCallback(picture, mRawCallbackCookie);
+    sp<CameraListener> listener;
+    {
+        Mutex::Autolock _l(mLock);
+        listener = mListener;
     }
-}
-
-// callback from camera service when image is ready
-void Camera::jpegCallback(const sp<IMemory>& picture)
-{
-    LOGV("jpegCallback");
-    if (mJpegCallback) {
-        mJpegCallback(picture, mJpegCallbackCookie);
-    }
-}
-
-// callback from camera service when preview frame is ready
-void Camera::previewCallback(const sp<IMemory>& frame)
-{
-    LOGV("frameCallback");
-    if (mPreviewCallback) {
-        mPreviewCallback(frame, mPreviewCallbackCookie);
-    }
-}
-
-// callback from camera service when a recording frame is ready
-void Camera::recordingCallback(const sp<IMemory>& frame)
-{
-    LOGV("recordingCallback");
-    if (mRecordingCallback) {
-        mRecordingCallback(frame, mRecordingCallbackCookie);
-    }
-}
-
-// callback from camera service when an error occurs in preview or takePicture
-void Camera::errorCallback(status_t error)
-{
-    LOGV("errorCallback");
-    if (mErrorCallback) {
-        mErrorCallback(error, mErrorCallbackCookie);
+    if (listener != NULL) {
+        listener->postDataTimestamp(timestamp, msgType, dataPtr);
     }
 }
 
 void Camera::binderDied(const wp<IBinder>& who) {
     LOGW("ICamera died");
-    if (mErrorCallback) {
-        mErrorCallback(DEAD_OBJECT, mErrorCallbackCookie);
-    }
+    notifyCallback(CAMERA_MSG_ERROR, CAMERA_ERROR_SERVER_DIED, 0);
 }
 
 void Camera::DeathNotifier::binderDied(const wp<IBinder>& who) {
diff --git a/libs/ui/ICameraClient.cpp b/libs/ui/ICameraClient.cpp
index 4bec9d2..59a6cf2 100644
--- a/libs/ui/ICameraClient.cpp
+++ b/libs/ui/ICameraClient.cpp
@@ -25,13 +25,9 @@
 namespace android {
 
 enum {
-    SHUTTER_CALLBACK = IBinder::FIRST_CALL_TRANSACTION,
-    RAW_CALLBACK,
-    JPEG_CALLBACK,
-    PREVIEW_CALLBACK,
-    ERROR_CALLBACK,
-    AUTOFOCUS_CALLBACK,
-    RECORDING_CALLBACK,
+    NOTIFY_CALLBACK = IBinder::FIRST_CALL_TRANSACTION,
+    DATA_CALLBACK,
+    DATA_CALLBACK_TIMESTAMP,
 };
 
 class BpCameraClient: public BpInterface<ICameraClient>
@@ -42,73 +38,39 @@
     {
     }
 
-    // callback to let the app know the shutter has closed, ideal for playing the shutter sound
-    void shutterCallback()
+    // generic callback from camera service to app
+    void notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2)
     {
-        LOGV("shutterCallback");
+        LOGV("notifyCallback");
         Parcel data, reply;
         data.writeInterfaceToken(ICameraClient::getInterfaceDescriptor());
-        remote()->transact(SHUTTER_CALLBACK, data, &reply, IBinder::FLAG_ONEWAY);
+        data.writeInt32(msgType);
+        data.writeInt32(ext1);
+        data.writeInt32(ext2);
+        remote()->transact(NOTIFY_CALLBACK, data, &reply, IBinder::FLAG_ONEWAY);
     }
 
-    // callback from camera service to app with picture data
-    void rawCallback(const sp<IMemory>& picture)
+    // generic data callback from camera service to app with image data
+    void dataCallback(int32_t msgType, const sp<IMemory>& imageData)
     {
-        LOGV("rawCallback");
+        LOGV("dataCallback");
         Parcel data, reply;
         data.writeInterfaceToken(ICameraClient::getInterfaceDescriptor());
-        data.writeStrongBinder(picture->asBinder());
-        remote()->transact(RAW_CALLBACK, data, &reply, IBinder::FLAG_ONEWAY);
+        data.writeInt32(msgType);
+        data.writeStrongBinder(imageData->asBinder());
+        remote()->transact(DATA_CALLBACK, data, &reply, IBinder::FLAG_ONEWAY);
     }
 
-    // callback from camera service to app with picture data
-    void jpegCallback(const sp<IMemory>& picture)
+    // generic data callback from camera service to app with image data
+    void dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& imageData)
     {
-        LOGV("jpegCallback");
+        LOGV("dataCallback");
         Parcel data, reply;
         data.writeInterfaceToken(ICameraClient::getInterfaceDescriptor());
-        data.writeStrongBinder(picture->asBinder());
-        remote()->transact(JPEG_CALLBACK, data, &reply, IBinder::FLAG_ONEWAY);
-    }
-
-    // callback from camera service to app with preview frame data
-    void previewCallback(const sp<IMemory>& frame)
-    {
-        LOGV("previewCallback");
-        Parcel data, reply;
-        data.writeInterfaceToken(ICameraClient::getInterfaceDescriptor());
-        data.writeStrongBinder(frame->asBinder());
-        remote()->transact(PREVIEW_CALLBACK, data, &reply, IBinder::FLAG_ONEWAY);
-    }
-
-    // callback from camera service to app with recording frame data
-    void recordingCallback(const sp<IMemory>& frame)
-    {
-        LOGV("recordingCallback");
-        Parcel data, reply;
-        data.writeInterfaceToken(ICameraClient::getInterfaceDescriptor());
-        data.writeStrongBinder(frame->asBinder());
-        remote()->transact(RECORDING_CALLBACK, data, &reply, IBinder::FLAG_ONEWAY);
-    }
-
-    // callback from camera service to app to report error
-    void errorCallback(status_t error)
-    {
-        LOGV("errorCallback");
-        Parcel data, reply;
-        data.writeInterfaceToken(ICameraClient::getInterfaceDescriptor());
-        data.writeInt32(error);
-        remote()->transact(ERROR_CALLBACK, data, &reply, IBinder::FLAG_ONEWAY);
-    }
-
-    // callback from camera service to app to report autofocus completion
-    void autoFocusCallback(bool focused)
-    {
-        LOGV("autoFocusCallback");
-        Parcel data, reply;
-        data.writeInterfaceToken(ICameraClient::getInterfaceDescriptor());
-        data.writeInt32(focused);
-        remote()->transact(AUTOFOCUS_CALLBACK, data, &reply, IBinder::FLAG_ONEWAY);
+        data.writeInt64(timestamp);
+        data.writeInt32(msgType);
+        data.writeStrongBinder(imageData->asBinder());
+        remote()->transact(DATA_CALLBACK_TIMESTAMP, data, &reply, IBinder::FLAG_ONEWAY);
     }
 };
 
@@ -126,52 +88,30 @@
     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
 {
     switch(code) {
-        case SHUTTER_CALLBACK: {
-            LOGV("SHUTTER_CALLBACK");
+        case NOTIFY_CALLBACK: {
+            LOGV("NOTIFY_CALLBACK");
             CHECK_INTERFACE(ICameraClient, data, reply);
-            shutterCallback();
+            int32_t msgType = data.readInt32();
+            int32_t ext1 = data.readInt32();
+            int32_t ext2 = data.readInt32();
+            notifyCallback(msgType, ext1, ext2);
             return NO_ERROR;
         } break;
-        case RAW_CALLBACK: {
-            LOGV("RAW_CALLBACK");
+        case DATA_CALLBACK: {
+            LOGV("DATA_CALLBACK");
             CHECK_INTERFACE(ICameraClient, data, reply);
-            sp<IMemory> picture = interface_cast<IMemory>(data.readStrongBinder());
-            rawCallback(picture);
+            int32_t msgType = data.readInt32();
+            sp<IMemory> imageData = interface_cast<IMemory>(data.readStrongBinder());
+            dataCallback(msgType, imageData);
             return NO_ERROR;
         } break;
-        case JPEG_CALLBACK: {
-            LOGV("JPEG_CALLBACK");
+        case DATA_CALLBACK_TIMESTAMP: {
+            LOGV("DATA_CALLBACK_TIMESTAMP");
             CHECK_INTERFACE(ICameraClient, data, reply);
-            sp<IMemory> picture = interface_cast<IMemory>(data.readStrongBinder());
-            jpegCallback(picture);
-            return NO_ERROR;
-        } break;
-        case PREVIEW_CALLBACK: {
-            LOGV("PREVIEW_CALLBACK");
-            CHECK_INTERFACE(ICameraClient, data, reply);
-            sp<IMemory> frame = interface_cast<IMemory>(data.readStrongBinder());
-            previewCallback(frame);
-            return NO_ERROR;
-        } break;
-        case RECORDING_CALLBACK: {
-            LOGV("RECORDING_CALLBACK");
-            CHECK_INTERFACE(ICameraClient, data, reply);
-            sp<IMemory> frame = interface_cast<IMemory>(data.readStrongBinder());
-            recordingCallback(frame);
-            return NO_ERROR;
-        } break;
-        case ERROR_CALLBACK: {
-            LOGV("ERROR_CALLBACK");
-            CHECK_INTERFACE(ICameraClient, data, reply);
-            status_t error = data.readInt32();
-            errorCallback(error);
-            return NO_ERROR;
-        } break;
-        case AUTOFOCUS_CALLBACK: {
-            LOGV("AUTOFOCUS_CALLBACK");
-            CHECK_INTERFACE(ICameraClient, data, reply);
-            bool focused = (bool)data.readInt32();
-            autoFocusCallback(focused);
+            nsecs_t timestamp = data.readInt64();
+            int32_t msgType = data.readInt32();
+            sp<IMemory> imageData = interface_cast<IMemory>(data.readStrongBinder());
+            dataCallbackTimestamp(timestamp, msgType, imageData);
             return NO_ERROR;
         } break;
         default:
diff --git a/libs/ui/ISurfaceFlingerClient.cpp b/libs/ui/ISurfaceFlingerClient.cpp
index dd6a798..dab5f71 100644
--- a/libs/ui/ISurfaceFlingerClient.cpp
+++ b/libs/ui/ISurfaceFlingerClient.cpp
@@ -35,6 +35,13 @@
 
 // ---------------------------------------------------------------------------
 
+/* 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
+ */
+#ifndef AID_GRAPHICS
+#define AID_GRAPHICS 1003
+#endif
+
 #define LIKELY( exp )       (__builtin_expect( (exp) != 0, true  ))
 #define UNLIKELY( exp )     (__builtin_expect( (exp) != 0, false ))
 
@@ -136,13 +143,13 @@
      
      IPCThreadState* ipc = IPCThreadState::self();
      const int pid = ipc->getCallingPid();
-     const int self_pid    = getpid();
-     if (UNLIKELY(pid != self_pid)) {
+     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")))
          {
-             const int uid = ipc->getCallingUid();
              LOGE("Permission Denial: "
                      "can't openGlobalTransaction pid=%d, uid=%d", pid, uid);
              return PERMISSION_DENIED;
diff --git a/libs/ui/Overlay.cpp b/libs/ui/Overlay.cpp
index b236edc..59c6514 100644
--- a/libs/ui/Overlay.cpp
+++ b/libs/ui/Overlay.cpp
@@ -129,12 +129,8 @@
 OverlayRef::~OverlayRef()
 {
     if (mOwnHandle) {
-        /* FIXME: handles should be promoted to "real" API and be handled by 
-         * the framework */
-        for (int i=0 ; i<mOverlayHandle->numFds ; i++) {
-            close(mOverlayHandle->data[i]);
-        }
-        free((void*)mOverlayHandle);
+        native_handle_close(mOverlayHandle);
+        native_handle_delete(const_cast<native_handle*>(mOverlayHandle));
     }
 }
 
@@ -147,7 +143,7 @@
         uint32_t f = data.readInt32();
         uint32_t ws = data.readInt32();
         uint32_t hs = data.readInt32();
-        native_handle* handle = data.readNativeHandle(NULL, NULL);
+        native_handle* handle = data.readNativeHandle();
 
         result = new OverlayRef();
         result->mOverlayHandle = handle;
@@ -169,7 +165,7 @@
         reply->writeInt32(o->mFormat);
         reply->writeInt32(o->mWidthStride);
         reply->writeInt32(o->mHeightStride);
-        reply->writeNativeHandle(*(o->mOverlayHandle));
+        reply->writeNativeHandle(o->mOverlayHandle);
     } else {
         reply->writeStrongBinder(NULL);
     }
diff --git a/libs/ui/Point.cpp b/libs/ui/Point.cpp
deleted file mode 100644
index 438d49f..0000000
--- a/libs/ui/Point.cpp
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- *  Point.cpp
- *  Android
- *
- *  Created on 11/16/2006.
- *  Copyright 2005 The Android Open Source Project
- *
- */
-
-#include <ui/Point.h>
-
diff --git a/libs/ui/Rect.cpp b/libs/ui/Rect.cpp
index 99e68bb..66b9576 100644
--- a/libs/ui/Rect.cpp
+++ b/libs/ui/Rect.cpp
@@ -1,21 +1,28 @@
 /*
- *  Rect.cpp
- *  Android
+ * Copyright (C) 2009 The Android Open Source Project
  *
- *  Created on 10/14/05.
- *  Copyright 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.
  */
 
 #include <ui/Rect.h>
 
 namespace android {
 
-inline int min(int a, int b) {
+static inline int min(int a, int b) {
     return (a<b) ? a : b;
 }
 
-inline int max(int a, int b) {
+static inline int max(int a, int b) {
     return (a>b) ? a : b;
 }
 
@@ -64,14 +71,16 @@
     return *this;
 }
 
-Rect Rect::operator + (const Point& rhs) const
+const Rect Rect::operator + (const Point& rhs) const
 {
-    return Rect(left+rhs.x, top+rhs.y, right+rhs.x, bottom+rhs.y); 
+    const Rect result(left+rhs.x, top+rhs.y, right+rhs.x, bottom+rhs.y);
+    return result;
 }
 
-Rect Rect::operator - (const Point& rhs) const
+const Rect Rect::operator - (const Point& rhs) const
 {
-    return Rect(left-rhs.x, top-rhs.y, right-rhs.x, bottom-rhs.y); 
+    const Rect result(left-rhs.x, top-rhs.y, right-rhs.x, bottom-rhs.y);
+    return result;
 }
 
 bool Rect::intersect(const Rect& with, Rect* result) const
diff --git a/libs/ui/Time.cpp b/libs/ui/Time.cpp
deleted file mode 100644
index b553913..0000000
--- a/libs/ui/Time.cpp
+++ /dev/null
@@ -1,199 +0,0 @@
-#include <utils/TimeUtils.h>
-#include <stdio.h>
-#include <cutils/tztime.h>
-
-namespace android {
-
-static void
-dump(const Time& t)
-{
-    #ifdef HAVE_TM_GMTOFF
-        long tm_gmtoff = t.t.tm_gmtoff;
-    #else
-        long tm_gmtoff = 0;
-    #endif
-    printf("%04d-%02d-%02d %02d:%02d:%02d (%d,%ld,%d,%d)\n",
-            t.t.tm_year+1900, t.t.tm_mon+1, t.t.tm_mday,
-            t.t.tm_hour, t.t.tm_min, t.t.tm_sec,
-            t.t.tm_isdst, tm_gmtoff, t.t.tm_wday, t.t.tm_yday);
-}
-
-Time::Time()
-{
-    t.tm_sec = 0;
-    t.tm_min = 0;
-    t.tm_hour = 0;
-    t.tm_mday = 0;
-    t.tm_mon = 0;
-    t.tm_year = 0;
-    t.tm_wday = 0;
-    t.tm_yday = 0;
-    t.tm_isdst = -1; // we don't know, so let the C library determine
-    #ifdef HAVE_TM_GMTOFF
-        t.tm_gmtoff = 0;
-    #endif
-}
-
-
-#define COMPARE_FIELD(field) do { \
-        int diff = a.t.field - b.t.field; \
-        if (diff != 0) return diff; \
-    } while(0)
-
-int
-Time::compare(Time& a, Time& b)
-{
-    if (0 == strcmp(a.timezone, b.timezone)) {
-        // if the timezones are the same, we can easily compare the two
-        // times.  Otherwise, convert to milliseconds and compare that.
-        // This requires that object be normalized.
-        COMPARE_FIELD(tm_year);
-        COMPARE_FIELD(tm_mon);
-        COMPARE_FIELD(tm_mday);
-        COMPARE_FIELD(tm_hour);
-        COMPARE_FIELD(tm_min);
-        COMPARE_FIELD(tm_sec);
-        return 0;
-    } else {
-        int64_t am = a.toMillis(false /* use isDst */);
-        int64_t bm = b.toMillis(false /* use isDst */);
-        int64_t diff = am-bm;
-        return (diff < 0) ? -1 : ((diff > 0) ? 1 : 0);
-    }
-}
-
-static const int DAYS_PER_MONTH[] = {
-                        31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
-                    };
-
-static inline int days_this_month(int year, int month)
-{
-    int n = DAYS_PER_MONTH[month];
-    if (n != 28) {
-        return n;
-    } else {
-        int y = year;
-        return ((y%4)==0&&((y%100)!=0||(y%400)==0)) ? 29 : 28;
-    }
-}
-
-void 
-Time::switchTimezone(const char* timezone)
-{
-    time_t seconds = mktime_tz(&(this->t), this->timezone);
-    localtime_tz(&seconds, &(this->t), timezone);
-}
-
-String8 
-Time::format(const char *format, const struct strftime_locale *locale) const
-{
-    char buf[257];
-    int n = strftime_tz(buf, 257, format, &(this->t), locale);
-    if (n > 0) {
-        return String8(buf);
-    } else {
-        return String8();
-    }
-}
-
-static inline short
-tochar(int n)
-{
-    return (n >= 0 && n <= 9) ? ('0'+n) : ' ';
-}
-
-static inline short
-next_char(int *m, int k)
-{
-    int n = *m / k;
-    *m = *m % k;
-    return tochar(n);
-}
-
-void
-Time::format2445(short* buf, bool hasTime) const
-{
-    int n;
-
-    n = t.tm_year+1900;
-    buf[0] = next_char(&n, 1000);
-    buf[1] = next_char(&n, 100);
-    buf[2] = next_char(&n, 10);
-    buf[3] = tochar(n);
-
-    n = t.tm_mon+1;
-    buf[4] = next_char(&n, 10);
-    buf[5] = tochar(n);
-
-    n = t.tm_mday;
-    buf[6] = next_char(&n, 10);
-    buf[7] = tochar(n);
-
-    if (hasTime) {
-      buf[8] = 'T';
-
-      n = t.tm_hour;
-      buf[9] = next_char(&n, 10);
-      buf[10] = tochar(n);
-      
-      n = t.tm_min;
-      buf[11] = next_char(&n, 10);
-      buf[12] = tochar(n);
-      
-      n = t.tm_sec;
-      buf[13] = next_char(&n, 10);
-      buf[14] = tochar(n);
-      bool inUtc = strcmp("UTC", timezone) == 0;
-      if (inUtc) {
-          buf[15] = 'Z';
-      }
-    }
-}
-
-String8 
-Time::toString() const
-{
-    String8 str;
-    char* s = str.lockBuffer(150);
-    #ifdef HAVE_TM_GMTOFF
-        long tm_gmtoff = t.tm_gmtoff;
-    #else
-        long tm_gmtoff = 0;
-    #endif
-    sprintf(s, "%04d%02d%02dT%02d%02d%02d%s(%d,%d,%ld,%d,%d)", 
-            t.tm_year+1900, t.tm_mon+1, t.tm_mday, t.tm_hour, t.tm_min,
-            t.tm_sec, timezone, t.tm_wday, t.tm_yday, tm_gmtoff, t.tm_isdst,
-            (int)(((Time*)this)->toMillis(false /* use isDst */)/1000));
-    str.unlockBuffer();
-    return str;
-}
-
-void 
-Time::setToNow()
-{
-    time_t seconds;
-    time(&seconds);
-    localtime_tz(&seconds, &(this->t), this->timezone);
-}
-
-int64_t 
-Time::toMillis(bool ignoreDst)
-{
-    if (ignoreDst) {
-        this->t.tm_isdst = -1;
-    }
-    int64_t r = mktime_tz(&(this->t), this->timezone);
-    if (r == -1)
-        return -1;
-    return r * 1000;
-}
-
-void 
-Time::set(int64_t millis)
-{
-    time_t seconds = millis / 1000;
-    localtime_tz(&seconds, &(this->t), this->timezone);
-}
-
-}; // namespace android
-
diff --git a/libs/utils/Android.mk b/libs/utils/Android.mk
index cdb8ca2..9bdd64a 100644
--- a/libs/utils/Android.mk
+++ b/libs/utils/Android.mk
@@ -116,7 +116,9 @@
 	ProcessState.cpp \
 	IPermissionController.cpp \
 	IServiceManager.cpp \
-	Unicode.cpp
+	Unicode.cpp \
+    BackupData.cpp \
+	BackupHelpers.cpp
 
 ifeq ($(TARGET_SIMULATOR),true)
 LOCAL_SRC_FILES += $(hostSources)
diff --git a/libs/utils/Asset.cpp b/libs/utils/Asset.cpp
index 91203dd..4295123 100644
--- a/libs/utils/Asset.cpp
+++ b/libs/utils/Asset.cpp
@@ -27,6 +27,7 @@
 #include <utils/ZipUtils.h>
 #include <utils/ZipFileRO.h>
 #include <utils/Log.h>
+#include <utils/threads.h>
 
 #include <string.h>
 #include <memory.h>
@@ -40,24 +41,71 @@
 # define O_BINARY 0
 #endif
 
-static volatile int32_t gCount = 0;
+static Mutex gAssetLock;
+static int32_t gCount = 0;
+static Asset* gHead = NULL;
+static Asset* gTail = NULL;
 
 int32_t Asset::getGlobalCount()
 {
+    AutoMutex _l(gAssetLock);
     return gCount;
 }
 
+String8 Asset::getAssetAllocations()
+{
+    AutoMutex _l(gAssetLock);
+    String8 res;
+    Asset* cur = gHead;
+    while (cur != NULL) {
+        if (cur->isAllocated()) {
+            res.append("    ");
+            res.append(cur->getAssetSource());
+            off_t size = (cur->getLength()+512)/1024;
+            char buf[64];
+            sprintf(buf, ": %dK\n", (int)size);
+            res.append(buf);
+        }
+        cur = cur->mNext;
+    }
+    
+    return res;
+}
+
 Asset::Asset(void)
     : mAccessMode(ACCESS_UNKNOWN)
 {
-    int count = android_atomic_inc(&gCount)+1;
-    //LOGI("Creating Asset %p #%d\n", this, count);
+    AutoMutex _l(gAssetLock);
+    gCount++;
+    mNext = mPrev = NULL;
+    if (gTail == NULL) {
+        gHead = gTail = this;
+  	} else {
+  	    mPrev = gTail;
+  	    gTail->mNext = this;
+  	    gTail = this;
+  	}
+    //LOGI("Creating Asset %p #%d\n", this, gCount);
 }
 
 Asset::~Asset(void)
 {
-    int count = android_atomic_dec(&gCount);
-    //LOGI("Destroying Asset in %p #%d\n", this, count);
+    AutoMutex _l(gAssetLock);
+	gCount--;
+    if (gHead == this) {
+        gHead = mNext;
+    }
+    if (gTail == this) {
+        gTail = mPrev;
+    }
+    if (mNext != NULL) {
+        mNext->mPrev = mPrev;
+    }
+    if (mPrev != NULL) {
+        mPrev->mNext = mNext;
+    }
+    mNext = mPrev = NULL;
+    //LOGI("Destroying Asset in %p #%d\n", this, gCount);
 }
 
 /*
@@ -582,11 +630,14 @@
     if ((((size_t)data)&0x3) == 0) {
         // We can return this directly if it is aligned on a word
         // boundary.
+        LOGV("Returning aligned FileAsset %p (%s).", this,
+                getAssetSource());
         return data;
     }
     // If not aligned on a word boundary, then we need to copy it into
     // our own buffer.
-    LOGV("Copying FileAsset %p to buffer size %d to make it aligned.", this, (int)mLength);
+    LOGV("Copying FileAsset %p (%s) to buffer size %d to make it aligned.", this,
+            getAssetSource(), (int)mLength);
     unsigned char* buf = new unsigned char[mLength];
     if (buf == NULL) {
         LOGE("alloc of %ld bytes failed\n", (long) mLength);
diff --git a/libs/utils/AssetManager.cpp b/libs/utils/AssetManager.cpp
index 447b801..5a05e6a 100644
--- a/libs/utils/AssetManager.cpp
+++ b/libs/utils/AssetManager.cpp
@@ -395,21 +395,41 @@
     const size_t N = mAssetPaths.size();
     for (size_t i=0; i<N; i++) {
         Asset* ass = NULL;
+        ResTable* sharedRes = NULL;
         bool shared = true;
         const asset_path& ap = mAssetPaths.itemAt(i);
         LOGV("Looking for resource asset in '%s'\n", ap.path.string());
         if (ap.type != kFileTypeDirectory) {
-            ass = const_cast<AssetManager*>(this)->
-                mZipSet.getZipResourceTable(ap.path);
-            if (ass == NULL) {
-                LOGV("loading resource table %s\n", ap.path.string());
+            if (i == 0) {
+                // The first item is typically the framework resources,
+                // which we want to avoid parsing every time.
+                sharedRes = const_cast<AssetManager*>(this)->
+                    mZipSet.getZipResourceTable(ap.path);
+            }
+            if (sharedRes == NULL) {
                 ass = const_cast<AssetManager*>(this)->
-                    openNonAssetInPathLocked("resources.arsc",
-                                             Asset::ACCESS_BUFFER,
-                                             ap);
-                if (ass != NULL && ass != kExcludedAsset) {
+                    mZipSet.getZipResourceTableAsset(ap.path);
+                if (ass == NULL) {
+                    LOGV("loading resource table %s\n", ap.path.string());
                     ass = const_cast<AssetManager*>(this)->
-                        mZipSet.setZipResourceTable(ap.path, ass);
+                        openNonAssetInPathLocked("resources.arsc",
+                                                 Asset::ACCESS_BUFFER,
+                                                 ap);
+                    if (ass != NULL && ass != kExcludedAsset) {
+                        ass = const_cast<AssetManager*>(this)->
+                            mZipSet.setZipResourceTableAsset(ap.path, ass);
+                    }
+                }
+                
+                if (i == 0 && ass != NULL) {
+                    // If this is the first resource table in the asset
+                    // manager, then we are going to cache it so that we
+                    // can quickly copy it out for others.
+                    LOGV("Creating shared resources for %s", ap.path.string());
+                    sharedRes = new ResTable();
+                    sharedRes->add(ass, (void*)(i+1), false);
+                    sharedRes = const_cast<AssetManager*>(this)->
+                        mZipSet.setZipResourceTable(ap.path, sharedRes);
                 }
             }
         } else {
@@ -420,13 +440,19 @@
                                          ap);
             shared = false;
         }
-        if (ass != NULL && ass != kExcludedAsset) {
+        if ((ass != NULL || sharedRes != NULL) && ass != kExcludedAsset) {
             if (rt == NULL) {
                 mResources = rt = new ResTable();
                 updateResourceParamsLocked();
             }
             LOGV("Installing resource asset %p in to table %p\n", ass, mResources);
-            rt->add(ass, (void*)(i+1), !shared);
+            if (sharedRes != NULL) {
+                LOGV("Copying existing resources for %s", ap.path.string());
+                rt->add(sharedRes);
+            } else {
+                LOGV("Parsing resources for %s", ap.path.string());
+                rt->add(ass, (void*)(i+1), !shared);
+            }
 
             if (!shared) {
                 delete ass;
@@ -901,6 +927,60 @@
 }
 
 /*
+ * Open a directory in the non-asset namespace.
+ *
+ * An "asset directory" is simply the combination of all files in all
+ * locations, with ".gz" stripped for loose files.  With app, locale, and
+ * vendor defined, we have 8 directories and 2 Zip archives to scan.
+ *
+ * Pass in "" for the root dir.
+ */
+AssetDir* AssetManager::openNonAssetDir(void* cookie, const char* dirName)
+{
+    AutoMutex _l(mLock);
+
+    AssetDir* pDir = NULL;
+    SortedVector<AssetDir::FileInfo>* pMergedInfo = NULL;
+
+    LOG_FATAL_IF(mAssetPaths.size() == 0, "No assets added to AssetManager");
+    assert(dirName != NULL);
+
+    //printf("+++ openDir(%s) in '%s'\n", dirName, (const char*) mAssetBase);
+
+    if (mCacheMode != CACHE_OFF && !mCacheValid)
+        loadFileNameCacheLocked();
+
+    pDir = new AssetDir;
+
+    pMergedInfo = new SortedVector<AssetDir::FileInfo>;
+
+    const size_t which = ((size_t)cookie)-1;
+
+    if (which < mAssetPaths.size()) {
+        const asset_path& ap = mAssetPaths.itemAt(which);
+        if (ap.type == kFileTypeRegular) {
+            LOGV("Adding directory %s from zip %s", dirName, ap.path.string());
+            scanAndMergeZipLocked(pMergedInfo, ap, NULL, dirName);
+        } else {
+            LOGV("Adding directory %s from dir %s", dirName, ap.path.string());
+            scanAndMergeDirLocked(pMergedInfo, ap, NULL, dirName);
+        }
+    }
+
+#if 0
+    printf("FILE LIST:\n");
+    for (i = 0; i < (size_t) pMergedInfo->size(); i++) {
+        printf(" %d: (%d) '%s'\n", i,
+            pMergedInfo->itemAt(i).getFileType(),
+            (const char*) pMergedInfo->itemAt(i).getFileName());
+    }
+#endif
+
+    pDir->setFileList(pMergedInfo);
+    return pDir;
+}
+
+/*
  * Scan the contents of the specified directory and merge them into the
  * "pMergedInfo" vector, removing previous entries if we find "exclude"
  * directives.
@@ -1143,6 +1223,7 @@
             LOGE("ARGH: name too long?\n");
             continue;
         }
+        //printf("Comparing %s in %s?\n", nameBuf, dirName.string());
         if (dirNameLen == 0 ||
             (strncmp(nameBuf, dirName.string(), dirNameLen) == 0 &&
              nameBuf[dirNameLen] == '/'))
@@ -1165,7 +1246,7 @@
                     createZipSourceNameLocked(zipName, dirName, info.getFileName()));
 
                 contents.add(info);
-                //printf("FOUND: file '%s'\n", (const char*) info.mFileName);
+                //printf("FOUND: file '%s'\n", info.getFileName().string());
             } else {
                 /* this is a subdir; add it if we don't already have it*/
                 String8 subdirName(cp, nextSlash - cp);
@@ -1181,7 +1262,7 @@
                     dirs.add(subdirName);
                 }
 
-                //printf("FOUND: dir '%s'\n", (const char*) subdirName);
+                //printf("FOUND: dir '%s'\n", subdirName.string());
             }
         }
     }
@@ -1455,7 +1536,8 @@
 DefaultKeyedVector<String8, wp<AssetManager::SharedZip> > AssetManager::SharedZip::gOpen;
 
 AssetManager::SharedZip::SharedZip(const String8& path, time_t modWhen)
-    : mPath(path), mZipFile(NULL), mModWhen(modWhen), mResourceTableAsset(NULL)
+    : mPath(path), mZipFile(NULL), mModWhen(modWhen),
+      mResourceTableAsset(NULL), mResourceTable(NULL)
 {
     //LOGI("Creating SharedZip %p %s\n", this, (const char*)mPath);
     mZipFile = new ZipFileRO;
@@ -1508,6 +1590,25 @@
     return mResourceTableAsset;
 }
 
+ResTable* AssetManager::SharedZip::getResourceTable()
+{
+    LOGV("Getting from SharedZip %p resource table %p\n", this, mResourceTable);
+    return mResourceTable;
+}
+
+ResTable* AssetManager::SharedZip::setResourceTable(ResTable* res)
+{
+    {
+        AutoMutex _l(gLock);
+        if (mResourceTable == NULL) {
+            mResourceTable = res;
+            return res;
+        }
+    }
+    delete res;
+    return mResourceTable;
+}
+
 bool AssetManager::SharedZip::isUpToDate()
 {
     time_t modWhen = getFileModDate(mPath.string());
@@ -1517,6 +1618,9 @@
 AssetManager::SharedZip::~SharedZip()
 {
     //LOGI("Destroying SharedZip %p %s\n", this, (const char*)mPath);
+    if (mResourceTable != NULL) {
+        delete mResourceTable;
+    }
     if (mResourceTableAsset != NULL) {
         delete mResourceTableAsset;
     }
@@ -1572,7 +1676,7 @@
     return zip->getZip();
 }
 
-Asset* AssetManager::ZipSet::getZipResourceTable(const String8& path)
+Asset* AssetManager::ZipSet::getZipResourceTableAsset(const String8& path)
 {
     int idx = getIndex(path);
     sp<SharedZip> zip = mZipFile[idx];
@@ -1583,7 +1687,7 @@
     return zip->getResourceTableAsset();
 }
 
-Asset* AssetManager::ZipSet::setZipResourceTable(const String8& path,
+Asset* AssetManager::ZipSet::setZipResourceTableAsset(const String8& path,
                                                  Asset* asset)
 {
     int idx = getIndex(path);
@@ -1592,6 +1696,26 @@
     return zip->setResourceTableAsset(asset);
 }
 
+ResTable* AssetManager::ZipSet::getZipResourceTable(const String8& path)
+{
+    int idx = getIndex(path);
+    sp<SharedZip> zip = mZipFile[idx];
+    if (zip == NULL) {
+        zip = SharedZip::get(path);
+        mZipFile.editItemAt(idx) = zip;
+    }
+    return zip->getResourceTable();
+}
+
+ResTable* AssetManager::ZipSet::setZipResourceTable(const String8& path,
+                                                    ResTable* res)
+{
+    int idx = getIndex(path);
+    sp<SharedZip> zip = mZipFile[idx];
+    // doesn't make sense to call before previously accessing.
+    return zip->setResourceTable(res);
+}
+
 /*
  * Generate the partial pathname for the specified archive.  The caller
  * gets to prepend the asset root directory.
diff --git a/libs/utils/BackupData.cpp b/libs/utils/BackupData.cpp
new file mode 100644
index 0000000..cce754a
--- /dev/null
+++ b/libs/utils/BackupData.cpp
@@ -0,0 +1,349 @@
+/*
+ * 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 "backup_data"
+
+#include <utils/BackupHelpers.h>
+#include <utils/ByteOrder.h>
+
+#include <stdio.h>
+#include <unistd.h>
+
+#include <cutils/log.h>
+
+namespace android {
+
+/*
+ * File Format (v1):
+ *
+ * All ints are stored little-endian.
+ *
+ *  - An app_header_v1 struct.
+ *  - The name of the package, utf-8, null terminated, padded to 4-byte boundary.
+ *  - A sequence of zero or more key/value paires (entities), each with
+ *      - A entity_header_v1 struct
+ *      - The key, utf-8, null terminated, padded to 4-byte boundary.
+ *      - The value, padded to 4 byte boundary
+ */
+
+const static int ROUND_UP[4] = { 0, 3, 2, 1 };
+
+static inline size_t
+round_up(size_t n)
+{
+    return n + ROUND_UP[n % 4];
+}
+
+static inline size_t
+padding_extra(size_t n)
+{
+    return ROUND_UP[n % 4];
+}
+
+BackupDataWriter::BackupDataWriter(int fd)
+    :m_fd(fd),
+     m_status(NO_ERROR),
+     m_pos(0),
+     m_entityCount(0)
+{
+}
+
+BackupDataWriter::~BackupDataWriter()
+{
+}
+
+// Pad out anything they've previously written to the next 4 byte boundary.
+status_t
+BackupDataWriter::write_padding_for(int n)
+{
+    ssize_t amt;
+    ssize_t paddingSize;
+
+    paddingSize = padding_extra(n);
+    if (paddingSize > 0) {
+        uint32_t padding = 0xbcbcbcbc;
+        amt = write(m_fd, &padding, paddingSize);
+        if (amt != paddingSize) {
+            m_status = errno;
+            return m_status;
+        }
+        m_pos += amt;
+    }
+    return NO_ERROR;
+}
+
+status_t
+BackupDataWriter::WriteEntityHeader(const String8& key, size_t dataSize)
+{
+    if (m_status != NO_ERROR) {
+        return m_status;
+    }
+
+    ssize_t amt;
+
+    amt = write_padding_for(m_pos);
+    if (amt != 0) {
+        return amt;
+    }
+
+    String8 k;
+    if (m_keyPrefix.length() > 0) {
+        k = m_keyPrefix;
+        k += ":";
+        k += key;
+    } else {
+        k = key;
+    }
+    if (true) {
+        LOGD("Writing entity: prefix='%s' key='%s' dataSize=%d", m_keyPrefix.string(), key.string(),
+                dataSize);
+    }
+
+    entity_header_v1 header;
+    ssize_t keyLen;
+
+    keyLen = k.length();
+
+    header.type = tolel(BACKUP_HEADER_ENTITY_V1);
+    header.keyLen = tolel(keyLen);
+    header.dataSize = tolel(dataSize);
+
+    amt = write(m_fd, &header, sizeof(entity_header_v1));
+    if (amt != sizeof(entity_header_v1)) {
+        m_status = errno;
+        return m_status;
+    }
+    m_pos += amt;
+
+    amt = write(m_fd, k.string(), keyLen+1);
+    if (amt != keyLen+1) {
+        m_status = errno;
+        return m_status;
+    }
+    m_pos += amt;
+
+    amt = write_padding_for(keyLen+1);
+
+    m_entityCount++;
+
+    return amt;
+}
+
+status_t
+BackupDataWriter::WriteEntityData(const void* data, size_t size)
+{
+    if (m_status != NO_ERROR) {
+        return m_status;
+    }
+
+    // We don't write padding here, because they're allowed to call this several
+    // times with smaller buffers.  We write it at the end of WriteEntityHeader
+    // instead.
+    ssize_t amt = write(m_fd, data, size);
+    if (amt != (ssize_t)size) {
+        m_status = errno;
+        return m_status;
+    }
+    m_pos += amt;
+    return NO_ERROR;
+}
+
+void
+BackupDataWriter::SetKeyPrefix(const String8& keyPrefix)
+{
+    m_keyPrefix = keyPrefix;
+}
+
+
+BackupDataReader::BackupDataReader(int fd)
+    :m_fd(fd),
+     m_done(false),
+     m_status(NO_ERROR),
+     m_pos(0),
+     m_entityCount(0)
+{
+    memset(&m_header, 0, sizeof(m_header));
+}
+
+BackupDataReader::~BackupDataReader()
+{
+}
+
+status_t
+BackupDataReader::Status()
+{
+    return m_status;
+}
+
+#define CHECK_SIZE(actual, expected) \
+    do { \
+        if ((actual) != (expected)) { \
+            if ((actual) == 0) { \
+                m_status = EIO; \
+            } else { \
+                m_status = errno; \
+            } \
+            return m_status; \
+        } \
+    } while(0)
+#define SKIP_PADDING() \
+    do { \
+        status_t err = skip_padding(); \
+        if (err != NO_ERROR) { \
+            m_status = err; \
+            return err; \
+        } \
+    } while(0)
+
+status_t
+BackupDataReader::ReadNextHeader(bool* done, int* type)
+{
+    *done = m_done;
+    if (m_status != NO_ERROR) {
+        return m_status;
+    }
+
+    int amt;
+
+    // No error checking here, in case we're at the end of the stream.  Just let read() fail.
+    skip_padding();
+    amt = read(m_fd, &m_header, sizeof(m_header));
+    *done = m_done = (amt == 0);
+    CHECK_SIZE(amt, sizeof(m_header));
+    m_pos += sizeof(m_header);
+    if (type) {
+        *type = m_header.type;
+    }
+
+    // validate and fix up the fields.
+    m_header.type = fromlel(m_header.type);
+    switch (m_header.type)
+    {
+        case BACKUP_HEADER_ENTITY_V1:
+        {
+            m_header.entity.keyLen = fromlel(m_header.entity.keyLen);
+            if (m_header.entity.keyLen <= 0) {
+                LOGD("Entity header at %d has keyLen<=0: 0x%08x\n", (int)m_pos,
+                        (int)m_header.entity.keyLen);
+                m_status = EINVAL;
+            }
+            m_header.entity.dataSize = fromlel(m_header.entity.dataSize);
+            m_entityCount++;
+
+            // read the rest of the header (filename)
+            size_t size = m_header.entity.keyLen;
+            char* buf = m_key.lockBuffer(size);
+            if (buf == NULL) {
+                m_status = ENOMEM;
+                return m_status;
+            }
+            int amt = read(m_fd, buf, size+1);
+            CHECK_SIZE(amt, (int)size+1);
+            m_key.unlockBuffer(size);
+            m_pos += size+1;
+            SKIP_PADDING();
+            m_dataEndPos = m_pos + m_header.entity.dataSize;
+
+            break;
+        }
+        default:
+            LOGD("Chunk header at %d has invalid type: 0x%08x", (int)m_pos, (int)m_header.type);
+            m_status = EINVAL;
+    }
+    
+    return m_status;
+}
+
+bool
+BackupDataReader::HasEntities()
+{
+    return m_status == NO_ERROR && m_header.type == BACKUP_HEADER_ENTITY_V1;
+}
+
+status_t
+BackupDataReader::ReadEntityHeader(String8* key, size_t* dataSize)
+{
+    if (m_status != NO_ERROR) {
+        return m_status;
+    }
+    if (m_header.type != BACKUP_HEADER_ENTITY_V1) {
+        return EINVAL;
+    }
+    *key = m_key;
+    *dataSize = m_header.entity.dataSize;
+    return NO_ERROR;
+}
+
+status_t
+BackupDataReader::SkipEntityData()
+{
+    if (m_status != NO_ERROR) {
+        return m_status;
+    }
+    if (m_header.type != BACKUP_HEADER_ENTITY_V1) {
+        return EINVAL;
+    }
+    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;
+    }
+}
+
+ssize_t
+BackupDataReader::ReadEntityData(void* data, size_t size)
+{
+    if (m_status != NO_ERROR) {
+        return -1;
+    }
+    int remaining = m_dataEndPos - m_pos;
+    //LOGD("ReadEntityData size=%d m_pos=0x%x m_dataEndPos=0x%x remaining=%d\n",
+    //        size, m_pos, m_dataEndPos, remaining);
+    if (remaining <= 0) {
+        return 0;
+    }
+    if (((int)size) > remaining) {
+        size = remaining;
+    }
+    //LOGD("   reading %d bytes", size);
+    int amt = read(m_fd, data, size);
+    if (amt < 0) {
+        m_status = errno;
+        return -1;
+    }
+    m_pos += amt;
+    return amt;
+}
+
+status_t
+BackupDataReader::skip_padding()
+{
+    ssize_t amt;
+    ssize_t paddingSize;
+
+    paddingSize = padding_extra(m_pos);
+    if (paddingSize > 0) {
+        uint32_t padding;
+        amt = read(m_fd, &padding, paddingSize);
+        CHECK_SIZE(amt, paddingSize);
+        m_pos += amt;
+    }
+    return NO_ERROR;
+}
+
+
+} // namespace android
diff --git a/libs/utils/BackupHelpers.cpp b/libs/utils/BackupHelpers.cpp
new file mode 100644
index 0000000..4ad9b51
--- /dev/null
+++ b/libs/utils/BackupHelpers.cpp
@@ -0,0 +1,1314 @@
+/*
+ * 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 "file_backup_helper"
+
+#include <utils/BackupHelpers.h>
+
+#include <utils/KeyedVector.h>
+#include <utils/ByteOrder.h>
+#include <utils/String8.h>
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <sys/stat.h>
+#include <sys/time.h>  // for utimes
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <utime.h>
+#include <fcntl.h>
+#include <zlib.h>
+
+#include <cutils/log.h>
+
+namespace android {
+
+#define MAGIC0 0x70616e53 // Snap
+#define MAGIC1 0x656c6946 // File
+
+/*
+ * File entity data format (v1):
+ *
+ *   - 4-byte version number of the metadata, little endian (0x00000001 for v1)
+ *   - 12 bytes of metadata
+ *   - the file data itself
+ *
+ * i.e. a 16-byte metadata header followed by the raw file data.  If the
+ * restore code does not recognize the metadata version, it can still
+ * interpret the file data itself correctly.
+ *
+ * file_metadata_v1:
+ *
+ *   - 4 byte version number === 0x00000001 (little endian)
+ *   - 4-byte access mode (little-endian)
+ *   - undefined (8 bytes)
+ */
+
+struct file_metadata_v1 {
+    int version;
+    int mode;
+    int undefined_1;
+    int undefined_2;
+};
+
+const static int CURRENT_METADATA_VERSION = 1;
+
+#if 1
+#define LOGP(f, x...)
+#else
+#if TEST_BACKUP_HELPERS
+#define LOGP(f, x...) printf(f "\n", x)
+#else
+#define LOGP(x...) LOGD(x)
+#endif
+#endif
+
+const static int ROUND_UP[4] = { 0, 3, 2, 1 };
+
+static inline int
+round_up(int n)
+{
+    return n + ROUND_UP[n % 4];
+}
+
+static int
+read_snapshot_file(int fd, KeyedVector<String8,FileState>* snapshot)
+{
+    int bytesRead = 0;
+    int amt;
+    SnapshotHeader header;
+
+    amt = read(fd, &header, sizeof(header));
+    if (amt != sizeof(header)) {
+        return errno;
+    }
+    bytesRead += amt;
+
+    if (header.magic0 != MAGIC0 || header.magic1 != MAGIC1) {
+        LOGW("read_snapshot_file header.magic0=0x%08x magic1=0x%08x", header.magic0, header.magic1);
+        return 1;
+    }
+
+    for (int i=0; i<header.fileCount; i++) {
+        FileState file;
+        char filenameBuf[128];
+
+        amt = read(fd, &file, sizeof(FileState));
+        if (amt != sizeof(FileState)) {
+            LOGW("read_snapshot_file FileState truncated/error with read at %d bytes\n", bytesRead);
+            return 1;
+        }
+        bytesRead += amt;
+
+        // filename is not NULL terminated, but it is padded
+        int nameBufSize = round_up(file.nameLen);
+        char* filename = nameBufSize <= (int)sizeof(filenameBuf)
+                ? filenameBuf
+                : (char*)malloc(nameBufSize);
+        amt = read(fd, filename, nameBufSize);
+        if (amt == nameBufSize) {
+            snapshot->add(String8(filename, file.nameLen), file);
+        }
+        bytesRead += amt;
+        if (filename != filenameBuf) {
+            free(filename);
+        }
+        if (amt != nameBufSize) {
+            LOGW("read_snapshot_file filename truncated/error with read at %d bytes\n", bytesRead);
+            return 1;
+        }
+    }
+
+    if (header.totalSize != bytesRead) {
+        LOGW("read_snapshot_file length mismatch: header.totalSize=%d bytesRead=%d\n",
+                header.totalSize, bytesRead);
+        return 1;
+    }
+
+    return 0;
+}
+
+static int
+write_snapshot_file(int fd, const KeyedVector<String8,FileRec>& snapshot)
+{
+    int fileCount = 0;
+    int bytesWritten = sizeof(SnapshotHeader);
+    // preflight size
+    const int N = snapshot.size();
+    for (int i=0; i<N; i++) {
+        const FileRec& g = snapshot.valueAt(i);
+        if (!g.deleted) {
+            const String8& name = snapshot.keyAt(i);
+            bytesWritten += sizeof(FileState) + round_up(name.length());
+            fileCount++;
+        }
+    }
+
+    LOGP("write_snapshot_file fd=%d\n", fd);
+
+    int amt;
+    SnapshotHeader header = { MAGIC0, fileCount, MAGIC1, bytesWritten };
+
+    amt = write(fd, &header, sizeof(header));
+    if (amt != sizeof(header)) {
+        LOGW("write_snapshot_file error writing header %s", strerror(errno));
+        return errno;
+    }
+
+    for (int i=0; i<N; i++) {
+        FileRec r = snapshot.valueAt(i);
+        if (!r.deleted) {
+            const String8& name = snapshot.keyAt(i);
+            int nameLen = r.s.nameLen = name.length();
+
+            amt = write(fd, &r.s, sizeof(FileState));
+            if (amt != sizeof(FileState)) {
+                LOGW("write_snapshot_file error writing header %s", strerror(errno));
+                return 1;
+            }
+
+            // filename is not NULL terminated, but it is padded
+            amt = write(fd, name.string(), nameLen);
+            if (amt != nameLen) {
+                LOGW("write_snapshot_file error writing filename %s", strerror(errno));
+                return 1;
+            }
+            int paddingLen = ROUND_UP[nameLen % 4];
+            if (paddingLen != 0) {
+                int padding = 0xabababab;
+                amt = write(fd, &padding, paddingLen);
+                if (amt != paddingLen) {
+                    LOGW("write_snapshot_file error writing %d bytes of filename padding %s",
+                            paddingLen, strerror(errno));
+                    return 1;
+                }
+            }
+        }
+    }
+
+    return 0;
+}
+
+static int
+write_delete_file(BackupDataWriter* dataStream, const String8& key)
+{
+    LOGP("write_delete_file %s\n", key.string());
+    return dataStream->WriteEntityHeader(key, -1);
+}
+
+static int
+write_update_file(BackupDataWriter* dataStream, int fd, int mode, const String8& key,
+        char const* realFilename)
+{
+    LOGP("write_update_file %s (%s) : mode 0%o\n", realFilename, key.string(), mode);
+
+    const int bufsize = 4*1024;
+    int err;
+    int amt;
+    int fileSize;
+    int bytesLeft;
+    file_metadata_v1 metadata;
+
+    char* buf = (char*)malloc(bufsize);
+    int crc = crc32(0L, Z_NULL, 0);
+
+
+    fileSize = lseek(fd, 0, SEEK_END);
+    lseek(fd, 0, SEEK_SET);
+
+    if (sizeof(metadata) != 16) {
+        LOGE("ERROR: metadata block is the wrong size!");
+    }
+
+    bytesLeft = fileSize + sizeof(metadata);
+    err = dataStream->WriteEntityHeader(key, bytesLeft);
+    if (err != 0) {
+        free(buf);
+        return err;
+    }
+
+    // store the file metadata first
+    metadata.version = tolel(CURRENT_METADATA_VERSION);
+    metadata.mode = tolel(mode);
+    metadata.undefined_1 = metadata.undefined_2 = 0;
+    err = dataStream->WriteEntityData(&metadata, sizeof(metadata));
+    if (err != 0) {
+        free(buf);
+        return err;
+    }
+    bytesLeft -= sizeof(metadata); // bytesLeft should == fileSize now
+
+    // now store the file content
+    while ((amt = read(fd, buf, bufsize)) != 0 && bytesLeft > 0) {
+        bytesLeft -= amt;
+        if (bytesLeft < 0) {
+            amt += bytesLeft; // Plus a negative is minus.  Don't write more than we promised.
+        }
+        err = dataStream->WriteEntityData(buf, amt);
+        if (err != 0) {
+            free(buf);
+            return err;
+        }
+    }
+    if (bytesLeft != 0) {
+        if (bytesLeft > 0) {
+            // Pad out the space we promised in the buffer.  We can't corrupt the buffer,
+            // even though the data we're sending is probably bad.
+            memset(buf, 0, bufsize);
+            while (bytesLeft > 0) {
+                amt = bytesLeft < bufsize ? bytesLeft : bufsize;
+                bytesLeft -= amt;
+                err = dataStream->WriteEntityData(buf, amt);
+                if (err != 0) {
+                    free(buf);
+                    return err;
+                }
+            }
+        }
+        LOGE("write_update_file size mismatch for %s. expected=%d actual=%d."
+                " You aren't doing proper locking!", realFilename, fileSize, fileSize-bytesLeft);
+    }
+
+    free(buf);
+    return NO_ERROR;
+}
+
+static int
+write_update_file(BackupDataWriter* dataStream, const String8& key, char const* realFilename)
+{
+    int err;
+    struct stat st;
+
+    err = stat(realFilename, &st);
+    if (err < 0) {
+        return errno;
+    }
+
+    int fd = open(realFilename, O_RDONLY);
+    if (fd == -1) {
+        return errno;
+    }
+
+    err = write_update_file(dataStream, fd, st.st_mode, key, realFilename);
+    close(fd);
+    return err;
+}
+
+static int
+compute_crc32(int fd)
+{
+    const int bufsize = 4*1024;
+    int amt;
+
+    char* buf = (char*)malloc(bufsize);
+    int crc = crc32(0L, Z_NULL, 0);
+
+    lseek(fd, 0, SEEK_SET);
+
+    while ((amt = read(fd, buf, bufsize)) != 0) {
+        crc = crc32(crc, (Bytef*)buf, amt);
+    }
+
+    free(buf);
+    return crc;
+}
+
+int
+back_up_files(int oldSnapshotFD, BackupDataWriter* dataStream, int newSnapshotFD,
+        char const* const* files, char const* const* keys, int fileCount)
+{
+    int err;
+    KeyedVector<String8,FileState> oldSnapshot;
+    KeyedVector<String8,FileRec> newSnapshot;
+
+    if (oldSnapshotFD != -1) {
+        err = read_snapshot_file(oldSnapshotFD, &oldSnapshot);
+        if (err != 0) {
+            // On an error, treat this as a full backup.
+            oldSnapshot.clear();
+        }
+    }
+
+    for (int i=0; i<fileCount; i++) {
+        String8 key(keys[i]);
+        FileRec r;
+        char const* file = files[i];
+        r.file = file;
+        struct stat st;
+
+        err = stat(file, &st);
+        if (err != 0) {
+            r.deleted = true;
+        } else {
+            r.deleted = false;
+            r.s.modTime_sec = st.st_mtime;
+            r.s.modTime_nsec = 0; // workaround sim breakage
+            //r.s.modTime_nsec = st.st_mtime_nsec;
+            r.s.mode = st.st_mode;
+            r.s.size = st.st_size;
+            // we compute the crc32 later down below, when we already have the file open.
+
+            if (newSnapshot.indexOfKey(key) >= 0) {
+                LOGP("back_up_files key already in use '%s'", key.string());
+                return -1;
+            }
+        }
+        newSnapshot.add(key, r);
+    }
+
+    int n = 0;
+    int N = oldSnapshot.size();
+    int m = 0;
+
+    while (n<N && m<fileCount) {
+        const String8& p = oldSnapshot.keyAt(n);
+        const String8& q = newSnapshot.keyAt(m);
+        FileRec& g = newSnapshot.editValueAt(m);
+        int cmp = p.compare(q);
+        if (g.deleted || cmp < 0) {
+            // file removed
+            LOGP("file removed: %s", p.string());
+            g.deleted = true; // They didn't mention the file, but we noticed that it's gone.
+            dataStream->WriteEntityHeader(p, -1);
+            n++;
+        }
+        else if (cmp > 0) {
+            // file added
+            LOGP("file added: %s", g.file.string());
+            write_update_file(dataStream, q, g.file.string());
+            m++;
+        }
+        else {
+            // both files exist, check them
+            const FileState& f = oldSnapshot.valueAt(n);
+
+            int fd = open(g.file.string(), O_RDONLY);
+            if (fd < 0) {
+                // We can't open the file.  Don't report it as a delete either.  Let the
+                // server keep the old version.  Maybe they'll be able to deal with it
+                // on restore.
+                LOGP("Unable to open file %s - skipping", g.file.string());
+            } else {
+                g.s.crc32 = compute_crc32(fd);
+
+                LOGP("%s", q.string());
+                LOGP("  new: modTime=%d,%d mode=%04o size=%-3d crc32=0x%08x",
+                        f.modTime_sec, f.modTime_nsec, f.mode, f.size, f.crc32);
+                LOGP("  old: modTime=%d,%d mode=%04o size=%-3d crc32=0x%08x",
+                        g.s.modTime_sec, g.s.modTime_nsec, g.s.mode, g.s.size, g.s.crc32);
+                if (f.modTime_sec != g.s.modTime_sec || f.modTime_nsec != g.s.modTime_nsec
+                        || f.mode != g.s.mode || f.size != g.s.size || f.crc32 != g.s.crc32) {
+                    write_update_file(dataStream, fd, g.s.mode, p, g.file.string());
+                }
+
+                close(fd);
+            }
+            n++;
+            m++;
+        }
+    }
+
+    // these were deleted
+    while (n<N) {
+        dataStream->WriteEntityHeader(oldSnapshot.keyAt(n), -1);
+        n++;
+    }
+
+    // these were added
+    while (m<fileCount) {
+        const String8& q = newSnapshot.keyAt(m);
+        FileRec& g = newSnapshot.editValueAt(m);
+        write_update_file(dataStream, q, g.file.string());
+        m++;
+    }
+
+    err = write_snapshot_file(newSnapshotFD, newSnapshot);
+
+    return 0;
+}
+
+#define RESTORE_BUF_SIZE (8*1024)
+
+RestoreHelperBase::RestoreHelperBase()
+{
+    m_buf = malloc(RESTORE_BUF_SIZE);
+    m_loggedUnknownMetadata = false;
+}
+
+RestoreHelperBase::~RestoreHelperBase()
+{
+    free(m_buf);
+}
+
+status_t
+RestoreHelperBase::WriteFile(const String8& filename, BackupDataReader* in)
+{
+    ssize_t err;
+    size_t dataSize;
+    String8 key;
+    int fd;
+    void* buf = m_buf;
+    ssize_t amt;
+    int mode;
+    int crc;
+    struct stat st;
+    FileRec r;
+
+    err = in->ReadEntityHeader(&key, &dataSize);
+    if (err != NO_ERROR) {
+        return err;
+    }
+
+    // Get the metadata block off the head of the file entity and use that to
+    // set up the output file
+    file_metadata_v1 metadata;
+    amt = in->ReadEntityData(&metadata, sizeof(metadata));
+    if (amt != sizeof(metadata)) {
+        LOGW("Could not read metadata for %s -- %ld / %s", filename.string(),
+                (long)amt, strerror(errno));
+        return EIO;
+    }
+    metadata.version = fromlel(metadata.version);
+    metadata.mode = fromlel(metadata.mode);
+    if (metadata.version > CURRENT_METADATA_VERSION) {
+        if (!m_loggedUnknownMetadata) {
+            m_loggedUnknownMetadata = true;
+            LOGW("Restoring file with unsupported metadata version %d (currently %d)",
+                    metadata.version, CURRENT_METADATA_VERSION);
+        }
+    }
+    mode = metadata.mode;
+
+    // Write the file and compute the crc
+    crc = crc32(0L, Z_NULL, 0);
+    fd = open(filename.string(), O_CREAT|O_RDWR|O_TRUNC, mode);
+    if (fd == -1) {
+        LOGW("Could not open file %s -- %s", filename.string(), strerror(errno));
+        return errno;
+    }
+    
+    while ((amt = in->ReadEntityData(buf, RESTORE_BUF_SIZE)) > 0) {
+        err = write(fd, buf, amt);
+        if (err != amt) {
+            close(fd);
+            LOGW("Error '%s' writing '%s'", strerror(errno), filename.string());
+            return errno;
+        }
+        crc = crc32(crc, (Bytef*)buf, amt);
+    }
+
+    close(fd);
+
+    // Record for the snapshot
+    err = stat(filename.string(), &st);
+    if (err != 0) {
+        LOGW("Error stating file that we just created %s", filename.string());
+        return errno;
+    }
+
+    r.file = filename;
+    r.deleted = false;
+    r.s.modTime_sec = st.st_mtime;
+    r.s.modTime_nsec = 0; // workaround sim breakage
+    //r.s.modTime_nsec = st.st_mtime_nsec;
+    r.s.mode = st.st_mode;
+    r.s.size = st.st_size;
+    r.s.crc32 = crc;
+
+    m_files.add(key, r);
+
+    return NO_ERROR;
+}
+
+status_t
+RestoreHelperBase::WriteSnapshot(int fd)
+{
+    return write_snapshot_file(fd, m_files);;
+}
+
+#if TEST_BACKUP_HELPERS
+
+#define SCRATCH_DIR "/data/backup_helper_test/"
+
+static int
+write_text_file(const char* path, const char* data)
+{
+    int amt;
+    int fd;
+    int len;
+
+    fd = creat(path, 0666);
+    if (fd == -1) {
+        fprintf(stderr, "creat %s failed\n", path);
+        return errno;
+    }
+
+    len = strlen(data);
+    amt = write(fd, data, len);
+    if (amt != len) {
+        fprintf(stderr, "error (%s) writing to file %s\n", strerror(errno), path);
+        return errno;
+    }
+
+    close(fd);
+
+    return 0;
+}
+
+static int
+compare_file(const char* path, const unsigned char* data, int len)
+{
+    int fd;
+    int amt;
+
+    fd = open(path, O_RDONLY);
+    if (fd == -1) {
+        fprintf(stderr, "compare_file error (%s) opening %s\n", strerror(errno), path);
+        return errno;
+    }
+
+    unsigned char* contents = (unsigned char*)malloc(len);
+    if (contents == NULL) {
+        fprintf(stderr, "malloc(%d) failed\n", len);
+        return ENOMEM;
+    }
+
+    bool sizesMatch = true;
+    amt = lseek(fd, 0, SEEK_END);
+    if (amt != len) {
+        fprintf(stderr, "compare_file file length should be %d, was %d\n", len, amt);
+        sizesMatch = false;
+    }
+    lseek(fd, 0, SEEK_SET);
+
+    int readLen = amt < len ? amt : len;
+    amt = read(fd, contents, readLen);
+    if (amt != readLen) {
+        fprintf(stderr, "compare_file read expected %d bytes but got %d\n", len, amt);
+    }
+
+    bool contentsMatch = true;
+    for (int i=0; i<readLen; i++) {
+        if (data[i] != contents[i]) {
+            if (contentsMatch) {
+                fprintf(stderr, "compare_file contents are different: (index, expected, actual)\n");
+                contentsMatch = false;
+            }
+            fprintf(stderr, "  [%-2d] %02x %02x\n", i, data[i], contents[i]);
+        }
+    }
+
+    free(contents);
+    return contentsMatch && sizesMatch ? 0 : 1;
+}
+
+int
+backup_helper_test_empty()
+{
+    int err;
+    int fd;
+    KeyedVector<String8,FileRec> snapshot;
+    const char* filename = SCRATCH_DIR "backup_helper_test_empty.snap";
+
+    system("rm -r " SCRATCH_DIR);
+    mkdir(SCRATCH_DIR, 0777);
+
+    // write
+    fd = creat(filename, 0666);
+    if (fd == -1) {
+        fprintf(stderr, "error creating %s\n", filename);
+        return 1;
+    }
+
+    err = write_snapshot_file(fd, snapshot);
+
+    close(fd);
+
+    if (err != 0) {
+        fprintf(stderr, "write_snapshot_file reported error %d (%s)\n", err, strerror(err));
+        return err;
+    }
+
+    static const unsigned char correct_data[] = {
+        0x53, 0x6e, 0x61, 0x70,  0x00, 0x00, 0x00, 0x00,
+        0x46, 0x69, 0x6c, 0x65,  0x10, 0x00, 0x00, 0x00
+    };
+
+    err = compare_file(filename, correct_data, sizeof(correct_data));
+    if (err != 0) {
+        return err;
+    }
+
+    // read
+    fd = open(filename, O_RDONLY);
+    if (fd == -1) {
+        fprintf(stderr, "error opening for read %s\n", filename);
+        return 1;
+    }
+
+    KeyedVector<String8,FileState> readSnapshot;
+    err = read_snapshot_file(fd, &readSnapshot);
+    if (err != 0) {
+        fprintf(stderr, "read_snapshot_file failed %d\n", err);
+        return err;
+    }
+
+    if (readSnapshot.size() != 0) {
+        fprintf(stderr, "readSnapshot should be length 0\n");
+        return 1;
+    }
+
+    return 0;
+}
+
+int
+backup_helper_test_four()
+{
+    int err;
+    int fd;
+    KeyedVector<String8,FileRec> snapshot;
+    const char* filename = SCRATCH_DIR "backup_helper_test_four.snap";
+
+    system("rm -r " SCRATCH_DIR);
+    mkdir(SCRATCH_DIR, 0777);
+
+    // write
+    fd = creat(filename, 0666);
+    if (fd == -1) {
+        fprintf(stderr, "error opening %s\n", filename);
+        return 1;
+    }
+
+    String8 filenames[4];
+    FileState states[4];
+    FileRec r;
+    r.deleted = false;
+
+    states[0].modTime_sec = 0xfedcba98;
+    states[0].modTime_nsec = 0xdeadbeef;
+    states[0].mode = 0777; // decimal 511, hex 0x000001ff
+    states[0].size = 0xababbcbc;
+    states[0].crc32 = 0x12345678;
+    states[0].nameLen = -12;
+    r.s = states[0];
+    filenames[0] = String8("bytes_of_padding");
+    snapshot.add(filenames[0], r);
+
+    states[1].modTime_sec = 0x93400031;
+    states[1].modTime_nsec = 0xdeadbeef;
+    states[1].mode = 0666; // decimal 438, hex 0x000001b6
+    states[1].size = 0x88557766;
+    states[1].crc32 = 0x22334422;
+    states[1].nameLen = -1;
+    r.s = states[1];
+    filenames[1] = String8("bytes_of_padding3");
+    snapshot.add(filenames[1], r);
+
+    states[2].modTime_sec = 0x33221144;
+    states[2].modTime_nsec = 0xdeadbeef;
+    states[2].mode = 0744; // decimal 484, hex 0x000001e4
+    states[2].size = 0x11223344;
+    states[2].crc32 = 0x01122334;
+    states[2].nameLen = 0;
+    r.s = states[2];
+    filenames[2] = String8("bytes_of_padding_2");
+    snapshot.add(filenames[2], r);
+
+    states[3].modTime_sec = 0x33221144;
+    states[3].modTime_nsec = 0xdeadbeef;
+    states[3].mode = 0755; // decimal 493, hex 0x000001ed
+    states[3].size = 0x11223344;
+    states[3].crc32 = 0x01122334;
+    states[3].nameLen = 0;
+    r.s = states[3];
+    filenames[3] = String8("bytes_of_padding__1");
+    snapshot.add(filenames[3], r);
+
+    err = write_snapshot_file(fd, snapshot);
+
+    close(fd);
+
+    if (err != 0) {
+        fprintf(stderr, "write_snapshot_file reported error %d (%s)\n", err, strerror(err));
+        return err;
+    }
+
+    static const unsigned char correct_data[] = {
+        // header
+        0x53, 0x6e, 0x61, 0x70,  0x04, 0x00, 0x00, 0x00,
+        0x46, 0x69, 0x6c, 0x65,  0xbc, 0x00, 0x00, 0x00,
+
+        // bytes_of_padding
+        0x98, 0xba, 0xdc, 0xfe,  0xef, 0xbe, 0xad, 0xde,
+        0xff, 0x01, 0x00, 0x00,  0xbc, 0xbc, 0xab, 0xab,
+        0x78, 0x56, 0x34, 0x12,  0x10, 0x00, 0x00, 0x00,
+        0x62, 0x79, 0x74, 0x65,  0x73, 0x5f, 0x6f, 0x66,
+        0x5f, 0x70, 0x61, 0x64,  0x64, 0x69, 0x6e, 0x67,
+
+        // bytes_of_padding3
+        0x31, 0x00, 0x40, 0x93,  0xef, 0xbe, 0xad, 0xde,
+        0xb6, 0x01, 0x00, 0x00,  0x66, 0x77, 0x55, 0x88,
+        0x22, 0x44, 0x33, 0x22,  0x11, 0x00, 0x00, 0x00,
+        0x62, 0x79, 0x74, 0x65,  0x73, 0x5f, 0x6f, 0x66,
+        0x5f, 0x70, 0x61, 0x64,  0x64, 0x69, 0x6e, 0x67,
+        0x33, 0xab, 0xab, 0xab,
+
+        // bytes of padding2
+        0x44, 0x11, 0x22, 0x33,  0xef, 0xbe, 0xad, 0xde,
+        0xe4, 0x01, 0x00, 0x00,  0x44, 0x33, 0x22, 0x11,
+        0x34, 0x23, 0x12, 0x01,  0x12, 0x00, 0x00, 0x00,
+        0x62, 0x79, 0x74, 0x65,  0x73, 0x5f, 0x6f, 0x66,
+        0x5f, 0x70, 0x61, 0x64,  0x64, 0x69, 0x6e, 0x67,
+        0x5f, 0x32, 0xab, 0xab,
+
+        // bytes of padding3
+        0x44, 0x11, 0x22, 0x33,  0xef, 0xbe, 0xad, 0xde,
+        0xed, 0x01, 0x00, 0x00,  0x44, 0x33, 0x22, 0x11,
+        0x34, 0x23, 0x12, 0x01,  0x13, 0x00, 0x00, 0x00,
+        0x62, 0x79, 0x74, 0x65,  0x73, 0x5f, 0x6f, 0x66,
+        0x5f, 0x70, 0x61, 0x64,  0x64, 0x69, 0x6e, 0x67,
+        0x5f, 0x5f, 0x31, 0xab
+    };
+
+    err = compare_file(filename, correct_data, sizeof(correct_data));
+    if (err != 0) {
+        return err;
+    }
+
+    // read
+    fd = open(filename, O_RDONLY);
+    if (fd == -1) {
+        fprintf(stderr, "error opening for read %s\n", filename);
+        return 1;
+    }
+
+
+    KeyedVector<String8,FileState> readSnapshot;
+    err = read_snapshot_file(fd, &readSnapshot);
+    if (err != 0) {
+        fprintf(stderr, "read_snapshot_file failed %d\n", err);
+        return err;
+    }
+
+    if (readSnapshot.size() != 4) {
+        fprintf(stderr, "readSnapshot should be length 4 is %d\n", readSnapshot.size());
+        return 1;
+    }
+
+    bool matched = true;
+    for (size_t i=0; i<readSnapshot.size(); i++) {
+        const String8& name = readSnapshot.keyAt(i);
+        const FileState state = readSnapshot.valueAt(i);
+
+        if (name != filenames[i] || states[i].modTime_sec != state.modTime_sec
+                || states[i].modTime_nsec != state.modTime_nsec || states[i].mode != state.mode
+                || states[i].size != state.size || states[i].crc32 != states[i].crc32) {
+            fprintf(stderr, "state %d expected={%d/%d, 0x%08x, %04o, 0x%08x, %3d} '%s'\n"
+                            "          actual={%d/%d, 0x%08x, %04o, 0x%08x, %3d} '%s'\n", i,
+                    states[i].modTime_sec, states[i].modTime_nsec, states[i].mode, states[i].size,
+                    states[i].crc32, name.length(), filenames[i].string(),
+                    state.modTime_sec, state.modTime_nsec, state.mode, state.size, state.crc32,
+                    state.nameLen, name.string());
+            matched = false;
+        }
+    }
+
+    return matched ? 0 : 1;
+}
+
+// hexdump -v -e '"    " 8/1 " 0x%02x," "\n"' data_writer.data
+const unsigned char DATA_GOLDEN_FILE[] = {
+     0x44, 0x61, 0x74, 0x61, 0x0b, 0x00, 0x00, 0x00,
+     0x0c, 0x00, 0x00, 0x00, 0x6e, 0x6f, 0x5f, 0x70,
+     0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x00,
+     0x6e, 0x6f, 0x5f, 0x70, 0x61, 0x64, 0x64, 0x69,
+     0x6e, 0x67, 0x5f, 0x00, 0x44, 0x61, 0x74, 0x61,
+     0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
+     0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74,
+     0x6f, 0x5f, 0x5f, 0x33, 0x00, 0xbc, 0xbc, 0xbc,
+     0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74,
+     0x6f, 0x5f, 0x5f, 0x33, 0x00, 0xbc, 0xbc, 0xbc,
+     0x44, 0x61, 0x74, 0x61, 0x0d, 0x00, 0x00, 0x00,
+     0x0e, 0x00, 0x00, 0x00, 0x70, 0x61, 0x64, 0x64,
+     0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x32, 0x5f,
+     0x5f, 0x00, 0xbc, 0xbc, 0x70, 0x61, 0x64, 0x64,
+     0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x32, 0x5f,
+     0x5f, 0x00, 0xbc, 0xbc, 0x44, 0x61, 0x74, 0x61,
+     0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
+     0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74,
+     0x6f, 0x31, 0x00, 0xbc, 0x70, 0x61, 0x64, 0x64,
+     0x65, 0x64, 0x5f, 0x74, 0x6f, 0x31, 0x00
+
+};
+const int DATA_GOLDEN_FILE_SIZE = sizeof(DATA_GOLDEN_FILE);
+
+static int
+test_write_header_and_entity(BackupDataWriter& writer, const char* str)
+{
+    int err;
+    String8 text(str);
+
+    err = writer.WriteEntityHeader(text, text.length()+1);
+    if (err != 0) {
+        fprintf(stderr, "WriteEntityHeader failed with %s\n", strerror(err));
+        return err;
+    }
+
+    err = writer.WriteEntityData(text.string(), text.length()+1);
+    if (err != 0) {
+        fprintf(stderr, "write failed for data '%s'\n", text.string());
+        return errno;
+    }
+
+    return err;
+}
+
+int
+backup_helper_test_data_writer()
+{
+    int err;
+    int fd;
+    const char* filename = SCRATCH_DIR "data_writer.data";
+
+    system("rm -r " SCRATCH_DIR);
+    mkdir(SCRATCH_DIR, 0777);
+    mkdir(SCRATCH_DIR "data", 0777);
+
+    fd = creat(filename, 0666);
+    if (fd == -1) {
+        fprintf(stderr, "error creating: %s\n", strerror(errno));
+        return errno;
+    }
+
+    BackupDataWriter writer(fd);
+
+    err = 0;
+    err |= test_write_header_and_entity(writer, "no_padding_");
+    err |= test_write_header_and_entity(writer, "padded_to__3");
+    err |= test_write_header_and_entity(writer, "padded_to_2__");
+    err |= test_write_header_and_entity(writer, "padded_to1");
+
+    close(fd);
+
+    err = compare_file(filename, DATA_GOLDEN_FILE, DATA_GOLDEN_FILE_SIZE);
+    if (err != 0) {
+        return err;
+    }
+
+    return err;
+}
+
+int
+test_read_header_and_entity(BackupDataReader& reader, const char* str)
+{
+    int err;
+    int bufSize = strlen(str)+1;
+    char* buf = (char*)malloc(bufSize);
+    String8 string;
+    int cookie = 0x11111111;
+    size_t actualSize;
+    bool done;
+    int type;
+    ssize_t nRead;
+
+    // printf("\n\n---------- test_read_header_and_entity -- %s\n\n", str);
+
+    err = reader.ReadNextHeader(&done, &type);
+    if (done) {
+        fprintf(stderr, "should not be done yet\n");
+        goto finished;
+    }
+    if (err != 0) {
+        fprintf(stderr, "ReadNextHeader (for app header) failed with %s\n", strerror(err));
+        goto finished;
+    }
+    if (type != BACKUP_HEADER_ENTITY_V1) {
+        err = EINVAL;
+        fprintf(stderr, "type=0x%08x expected 0x%08x\n", type, BACKUP_HEADER_ENTITY_V1);
+    }
+
+    err = reader.ReadEntityHeader(&string, &actualSize);
+    if (err != 0) {
+        fprintf(stderr, "ReadEntityHeader failed with %s\n", strerror(err));
+        goto finished;
+    }
+    if (string != str) {
+        fprintf(stderr, "ReadEntityHeader expected key '%s' got '%s'\n", str, string.string());
+        err = EINVAL;
+        goto finished;
+    }
+    if ((int)actualSize != bufSize) {
+        fprintf(stderr, "ReadEntityHeader expected dataSize 0x%08x got 0x%08x\n", bufSize,
+                actualSize);
+        err = EINVAL;
+        goto finished;
+    }
+
+    nRead = reader.ReadEntityData(buf, bufSize);
+    if (nRead < 0) {
+        err = reader.Status();
+        fprintf(stderr, "ReadEntityData failed with %s\n", strerror(err));
+        goto finished;
+    }
+
+    if (0 != memcmp(buf, str, bufSize)) {
+        fprintf(stderr, "ReadEntityData expected '%s' but got something starting with "
+                "%02x %02x %02x %02x  '%c%c%c%c'\n", str, buf[0], buf[1], buf[2], buf[3],
+                buf[0], buf[1], buf[2], buf[3]);
+        err = EINVAL;
+        goto finished;
+    }
+
+    // The next read will confirm whether it got the right amount of data.
+
+finished:
+    if (err != NO_ERROR) {
+        fprintf(stderr, "test_read_header_and_entity failed with %s\n", strerror(err));
+    }
+    free(buf);
+    return err;
+}
+
+int
+backup_helper_test_data_reader()
+{
+    int err;
+    int fd;
+    const char* filename = SCRATCH_DIR "data_reader.data";
+
+    system("rm -r " SCRATCH_DIR);
+    mkdir(SCRATCH_DIR, 0777);
+    mkdir(SCRATCH_DIR "data", 0777);
+
+    fd = creat(filename, 0666);
+    if (fd == -1) {
+        fprintf(stderr, "error creating: %s\n", strerror(errno));
+        return errno;
+    }
+
+    err = write(fd, DATA_GOLDEN_FILE, DATA_GOLDEN_FILE_SIZE);
+    if (err != DATA_GOLDEN_FILE_SIZE) {
+        fprintf(stderr, "Error \"%s\" writing golden file %s\n", strerror(errno), filename);
+        return errno;
+    }
+
+    close(fd);
+
+    fd = open(filename, O_RDONLY);
+    if (fd == -1) {
+        fprintf(stderr, "Error \"%s\" opening golden file %s for read\n", strerror(errno),
+                filename);
+        return errno;
+    }
+
+    {
+        BackupDataReader reader(fd);
+
+        err = 0;
+
+        if (err == NO_ERROR) {
+            err = test_read_header_and_entity(reader, "no_padding_");
+        }
+
+        if (err == NO_ERROR) {
+            err = test_read_header_and_entity(reader, "padded_to__3");
+        }
+
+        if (err == NO_ERROR) {
+            err = test_read_header_and_entity(reader, "padded_to_2__");
+        }
+
+        if (err == NO_ERROR) {
+            err = test_read_header_and_entity(reader, "padded_to1");
+        }
+    }
+
+    close(fd);
+
+    return err;
+}
+
+static int
+get_mod_time(const char* filename, struct timeval times[2])
+{
+    int err;
+    struct stat64 st;
+    err = stat64(filename, &st);
+    if (err != 0) {
+        fprintf(stderr, "stat '%s' failed: %s\n", filename, strerror(errno));
+        return errno;
+    }
+    times[0].tv_sec = st.st_atime;
+    times[1].tv_sec = st.st_mtime;
+
+    // If st_atime is a macro then struct stat64 uses struct timespec
+    // to store the access and modif time values and typically
+    // st_*time_nsec is not defined. In glibc, this is controlled by
+    // __USE_MISC.
+#ifdef __USE_MISC
+#if !defined(st_atime) || defined(st_atime_nsec)
+#error "Check if this __USE_MISC conditional is still needed."
+#endif
+    times[0].tv_usec = st.st_atim.tv_nsec / 1000;
+    times[1].tv_usec = st.st_mtim.tv_nsec / 1000;
+#else
+    times[0].tv_usec = st.st_atime_nsec / 1000;
+    times[1].tv_usec = st.st_mtime_nsec / 1000;
+#endif
+
+    return 0;
+}
+
+int
+backup_helper_test_files()
+{
+    int err;
+    int oldSnapshotFD;
+    int dataStreamFD;
+    int newSnapshotFD;
+
+    system("rm -r " SCRATCH_DIR);
+    mkdir(SCRATCH_DIR, 0777);
+    mkdir(SCRATCH_DIR "data", 0777);
+
+    write_text_file(SCRATCH_DIR "data/b", "b\nbb\n");
+    write_text_file(SCRATCH_DIR "data/c", "c\ncc\n");
+    write_text_file(SCRATCH_DIR "data/d", "d\ndd\n");
+    write_text_file(SCRATCH_DIR "data/e", "e\nee\n");
+    write_text_file(SCRATCH_DIR "data/f", "f\nff\n");
+    write_text_file(SCRATCH_DIR "data/h", "h\nhh\n");
+
+    char const* files_before[] = {
+        SCRATCH_DIR "data/b",
+        SCRATCH_DIR "data/c",
+        SCRATCH_DIR "data/d",
+        SCRATCH_DIR "data/e",
+        SCRATCH_DIR "data/f"
+    };
+
+    char const* keys_before[] = {
+        "data/b",
+        "data/c",
+        "data/d",
+        "data/e",
+        "data/f"
+    };
+
+    dataStreamFD = creat(SCRATCH_DIR "1.data", 0666);
+    if (dataStreamFD == -1) {
+        fprintf(stderr, "error creating: %s\n", strerror(errno));
+        return errno;
+    }
+
+    newSnapshotFD = creat(SCRATCH_DIR "before.snap", 0666);
+    if (newSnapshotFD == -1) {
+        fprintf(stderr, "error creating: %s\n", strerror(errno));
+        return errno;
+    }
+
+    {
+        BackupDataWriter dataStream(dataStreamFD);
+
+        err = back_up_files(-1, &dataStream, newSnapshotFD, files_before, keys_before, 5);
+        if (err != 0) {
+            return err;
+        }
+    }
+
+    close(dataStreamFD);
+    close(newSnapshotFD);
+
+    sleep(3);
+
+    struct timeval d_times[2];
+    struct timeval e_times[2];
+
+    err = get_mod_time(SCRATCH_DIR "data/d", d_times);
+    err |= get_mod_time(SCRATCH_DIR "data/e", e_times);
+    if (err != 0) {
+        return err;
+    }
+
+    write_text_file(SCRATCH_DIR "data/a", "a\naa\n");
+    unlink(SCRATCH_DIR "data/c");
+    write_text_file(SCRATCH_DIR "data/c", "c\ncc\n");
+    write_text_file(SCRATCH_DIR "data/d", "dd\ndd\n");
+    utimes(SCRATCH_DIR "data/d", d_times);
+    write_text_file(SCRATCH_DIR "data/e", "z\nzz\n");
+    utimes(SCRATCH_DIR "data/e", e_times);
+    write_text_file(SCRATCH_DIR "data/g", "g\ngg\n");
+    unlink(SCRATCH_DIR "data/f");
+
+    char const* files_after[] = {
+        SCRATCH_DIR "data/a", // added
+        SCRATCH_DIR "data/b", // same
+        SCRATCH_DIR "data/c", // different mod time
+        SCRATCH_DIR "data/d", // different size (same mod time)
+        SCRATCH_DIR "data/e", // different contents (same mod time, same size)
+        SCRATCH_DIR "data/g"  // added
+    };
+
+    char const* keys_after[] = {
+        "data/a", // added
+        "data/b", // same
+        "data/c", // different mod time
+        "data/d", // different size (same mod time)
+        "data/e", // different contents (same mod time, same size)
+        "data/g"  // added
+    };
+
+    oldSnapshotFD = open(SCRATCH_DIR "before.snap", O_RDONLY);
+    if (oldSnapshotFD == -1) {
+        fprintf(stderr, "error opening: %s\n", strerror(errno));
+        return errno;
+    }
+
+    dataStreamFD = creat(SCRATCH_DIR "2.data", 0666);
+    if (dataStreamFD == -1) {
+        fprintf(stderr, "error creating: %s\n", strerror(errno));
+        return errno;
+    }
+
+    newSnapshotFD = creat(SCRATCH_DIR "after.snap", 0666);
+    if (newSnapshotFD == -1) {
+        fprintf(stderr, "error creating: %s\n", strerror(errno));
+        return errno;
+    }
+
+    {
+        BackupDataWriter dataStream(dataStreamFD);
+
+        err = back_up_files(oldSnapshotFD, &dataStream, newSnapshotFD, files_after, keys_after, 6);
+        if (err != 0) {
+            return err;
+        }
+}
+
+    close(oldSnapshotFD);
+    close(dataStreamFD);
+    close(newSnapshotFD);
+
+    return 0;
+}
+
+int
+backup_helper_test_null_base()
+{
+    int err;
+    int oldSnapshotFD;
+    int dataStreamFD;
+    int newSnapshotFD;
+
+    system("rm -r " SCRATCH_DIR);
+    mkdir(SCRATCH_DIR, 0777);
+    mkdir(SCRATCH_DIR "data", 0777);
+
+    write_text_file(SCRATCH_DIR "data/a", "a\naa\n");
+
+    char const* files[] = {
+        SCRATCH_DIR "data/a",
+    };
+
+    char const* keys[] = {
+        "a",
+    };
+
+    dataStreamFD = creat(SCRATCH_DIR "null_base.data", 0666);
+    if (dataStreamFD == -1) {
+        fprintf(stderr, "error creating: %s\n", strerror(errno));
+        return errno;
+    }
+
+    newSnapshotFD = creat(SCRATCH_DIR "null_base.snap", 0666);
+    if (newSnapshotFD == -1) {
+        fprintf(stderr, "error creating: %s\n", strerror(errno));
+        return errno;
+    }
+
+    {
+        BackupDataWriter dataStream(dataStreamFD);
+
+        err = back_up_files(-1, &dataStream, newSnapshotFD, files, keys, 1);
+        if (err != 0) {
+            return err;
+        }
+    }
+
+    close(dataStreamFD);
+    close(newSnapshotFD);
+
+    return 0;
+}
+
+int
+backup_helper_test_missing_file()
+{
+    int err;
+    int oldSnapshotFD;
+    int dataStreamFD;
+    int newSnapshotFD;
+
+    system("rm -r " SCRATCH_DIR);
+    mkdir(SCRATCH_DIR, 0777);
+    mkdir(SCRATCH_DIR "data", 0777);
+
+    write_text_file(SCRATCH_DIR "data/b", "b\nbb\n");
+
+    char const* files[] = {
+        SCRATCH_DIR "data/a",
+        SCRATCH_DIR "data/b",
+        SCRATCH_DIR "data/c",
+    };
+
+    char const* keys[] = {
+        "a",
+        "b",
+        "c",
+    };
+
+    dataStreamFD = creat(SCRATCH_DIR "null_base.data", 0666);
+    if (dataStreamFD == -1) {
+        fprintf(stderr, "error creating: %s\n", strerror(errno));
+        return errno;
+    }
+
+    newSnapshotFD = creat(SCRATCH_DIR "null_base.snap", 0666);
+    if (newSnapshotFD == -1) {
+        fprintf(stderr, "error creating: %s\n", strerror(errno));
+        return errno;
+    }
+
+    {
+        BackupDataWriter dataStream(dataStreamFD);
+
+        err = back_up_files(-1, &dataStream, newSnapshotFD, files, keys, 1);
+        if (err != 0) {
+            return err;
+        }
+    }
+
+    close(dataStreamFD);
+    close(newSnapshotFD);
+
+    return 0;
+}
+
+
+#endif // TEST_BACKUP_HELPERS
+
+}
diff --git a/libs/utils/characterData.h b/libs/utils/CharacterData.h
similarity index 100%
rename from libs/utils/characterData.h
rename to libs/utils/CharacterData.h
diff --git a/libs/utils/Parcel.cpp b/libs/utils/Parcel.cpp
index 4225e67..b0e3750 100644
--- a/libs/utils/Parcel.cpp
+++ b/libs/utils/Parcel.cpp
@@ -409,12 +409,16 @@
             mObjects[idx++] = off;
             mObjectsSize++;
 
-            const flat_binder_object* flat
+            flat_binder_object* flat
                 = reinterpret_cast<flat_binder_object*>(mData + off);
             acquire_object(proc, *flat, this);
 
-            // take note if the object is a file descriptor
             if (flat->type == BINDER_TYPE_FD) {
+                // If this is a file descriptor, we need to dup it so the
+                // new Parcel now owns its own fd, and can declare that we
+                // officially know we have fds.
+                flat->handle = dup(flat->handle);
+                flat->cookie = (void*)1;
                 mHasFds = mFdsKnown = true;
             }
         }
@@ -650,28 +654,26 @@
     return flatten_binder(ProcessState::self(), val, this);
 }
 
-status_t Parcel::writeNativeHandle(const native_handle& handle)
+status_t Parcel::writeNativeHandle(const native_handle* handle)
 {
-    if (handle.version != sizeof(native_handle))
+    if (handle->version != sizeof(native_handle))
         return BAD_TYPE;
 
     status_t err;
-    err = writeInt32(handle.numFds);
+    err = writeInt32(handle->numFds);
     if (err != NO_ERROR) return err;
 
-    err = writeInt32(handle.numInts);
+    err = writeInt32(handle->numInts);
     if (err != NO_ERROR) return err;
 
-    for (int i=0 ; err==NO_ERROR && i<handle.numFds ; i++)
-        err = writeDupFileDescriptor(handle.data[i]);
+    for (int i=0 ; err==NO_ERROR && i<handle->numFds ; i++)
+        err = writeDupFileDescriptor(handle->data[i]);
 
     if (err != NO_ERROR) {
         LOGD("write native handle, write dup fd failed");
         return err;
     }
-
-    err = write(handle.data + handle.numFds, sizeof(int)*handle.numInts);
-
+    err = write(handle->data + handle->numFds, sizeof(int)*handle->numInts);
     return err;
 }
 
@@ -928,7 +930,7 @@
 }
 
 
-native_handle* Parcel::readNativeHandle(native_handle* (*alloc)(void*, int, int), void* cookie) const
+native_handle* Parcel::readNativeHandle() const
 {
     int numFds, numInts;
     status_t err;
@@ -937,30 +939,15 @@
     err = readInt32(&numInts);
     if (err != NO_ERROR) return 0;
 
-    native_handle* h;
-    if (alloc == 0) {
-        size_t size = sizeof(native_handle) + sizeof(int)*(numFds + numInts);
-        h = (native_handle*)malloc(size); 
-        h->version = sizeof(native_handle);
-        h->numFds = numFds;
-        h->numInts = numInts;
-    } else {
-        h = alloc(cookie, numFds, numInts);
-        if (h->version != sizeof(native_handle)) {
-            return 0;
-        }
-    }
+    native_handle* h = native_handle_create(numFds, numInts);
     for (int i=0 ; err==NO_ERROR && i<numFds ; i++) {
         h->data[i] = dup(readFileDescriptor());
         if (h->data[i] < 0) err = BAD_VALUE;
     }
-
     err = read(h->data + numFds, sizeof(int)*numInts);
-
     if (err != NO_ERROR) {
-        if (alloc == 0) {
-            free(h);
-        }
+        native_handle_close(h);
+        native_handle_delete(h);
         h = 0;
     }
     return h;
diff --git a/libs/utils/ResourceTypes.cpp b/libs/utils/ResourceTypes.cpp
index 2ad3bfe..0831f4a 100644
--- a/libs/utils/ResourceTypes.cpp
+++ b/libs/utils/ResourceTypes.cpp
@@ -544,7 +544,7 @@
     return mEventCode;
 }
 
-const int32_t ResXMLParser::getCommentID() const
+int32_t ResXMLParser::getCommentID() const
 {
     return mCurNode != NULL ? dtohl(mCurNode->comment.index) : -1;
 }
@@ -555,12 +555,12 @@
     return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : NULL;
 }
 
-const uint32_t ResXMLParser::getLineNumber() const
+uint32_t ResXMLParser::getLineNumber() const
 {
     return mCurNode != NULL ? dtohl(mCurNode->lineNumber) : -1;
 }
 
-const int32_t ResXMLParser::getTextID() const
+int32_t ResXMLParser::getTextID() const
 {
     if (mEventCode == TEXT) {
         return dtohl(((const ResXMLTree_cdataExt*)mCurExt)->data.index);
@@ -583,7 +583,7 @@
     return BAD_TYPE;
 }
 
-const int32_t ResXMLParser::getNamespacePrefixID() const
+int32_t ResXMLParser::getNamespacePrefixID() const
 {
     if (mEventCode == START_NAMESPACE || mEventCode == END_NAMESPACE) {
         return dtohl(((const ResXMLTree_namespaceExt*)mCurExt)->prefix.index);
@@ -598,7 +598,7 @@
     return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : NULL;
 }
 
-const int32_t ResXMLParser::getNamespaceUriID() const
+int32_t ResXMLParser::getNamespaceUriID() const
 {
     if (mEventCode == START_NAMESPACE || mEventCode == END_NAMESPACE) {
         return dtohl(((const ResXMLTree_namespaceExt*)mCurExt)->uri.index);
@@ -613,7 +613,7 @@
     return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : NULL;
 }
 
-const int32_t ResXMLParser::getElementNamespaceID() const
+int32_t ResXMLParser::getElementNamespaceID() const
 {
     if (mEventCode == START_TAG) {
         return dtohl(((const ResXMLTree_attrExt*)mCurExt)->ns.index);
@@ -630,7 +630,7 @@
     return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : NULL;
 }
 
-const int32_t ResXMLParser::getElementNameID() const
+int32_t ResXMLParser::getElementNameID() const
 {
     if (mEventCode == START_TAG) {
         return dtohl(((const ResXMLTree_attrExt*)mCurExt)->name.index);
@@ -655,7 +655,7 @@
     return 0;
 }
 
-const int32_t ResXMLParser::getAttributeNamespaceID(size_t idx) const
+int32_t ResXMLParser::getAttributeNamespaceID(size_t idx) const
 {
     if (mEventCode == START_TAG) {
         const ResXMLTree_attrExt* tag = (const ResXMLTree_attrExt*)mCurExt;
@@ -678,7 +678,7 @@
     return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : NULL;
 }
 
-const int32_t ResXMLParser::getAttributeNameID(size_t idx) const
+int32_t ResXMLParser::getAttributeNameID(size_t idx) const
 {
     if (mEventCode == START_TAG) {
         const ResXMLTree_attrExt* tag = (const ResXMLTree_attrExt*)mCurExt;
@@ -701,7 +701,7 @@
     return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : NULL;
 }
 
-const uint32_t ResXMLParser::getAttributeNameResID(size_t idx) const
+uint32_t ResXMLParser::getAttributeNameResID(size_t idx) const
 {
     int32_t id = getAttributeNameID(idx);
     if (id >= 0 && (size_t)id < mTree.mNumResIds) {
@@ -710,7 +710,7 @@
     return 0;
 }
 
-const int32_t ResXMLParser::getAttributeValueStringID(size_t idx) const
+int32_t ResXMLParser::getAttributeValueStringID(size_t idx) const
 {
     if (mEventCode == START_TAG) {
         const ResXMLTree_attrExt* tag = (const ResXMLTree_attrExt*)mCurExt;
@@ -1136,8 +1136,9 @@
 
 struct ResTable::Header
 {
-    Header() : ownedData(NULL), header(NULL) { }
+    Header(ResTable* _owner) : owner(_owner), ownedData(NULL), header(NULL) { }
 
+    ResTable* const                 owner;
     void*                           ownedData;
     const ResTable_header*          header;
     size_t                          size;
@@ -1163,8 +1164,8 @@
 
 struct ResTable::Package
 {
-    Package(const Header* _header, const ResTable_package* _package)
-        : header(_header), package(_package) { }
+    Package(ResTable* _owner, const Header* _header, const ResTable_package* _package)
+        : owner(_owner), header(_header), package(_package) { }
     ~Package()
     {
         size_t i = types.size();
@@ -1174,10 +1175,14 @@
         }
     }
     
+    ResTable* const                 owner;
     const Header* const             header;
     const ResTable_package* const   package;
     Vector<Type*>                   types;
 
+    ResStringPool                   typeStrings;
+    ResStringPool                   keyStrings;
+    
     const Type* getType(size_t idx) const {
         return idx < types.size() ? types[idx] : NULL;
     }
@@ -1188,13 +1193,16 @@
 // table that defined the package); the ones after are skins on top of it.
 struct ResTable::PackageGroup
 {
-    PackageGroup(const String16& _name, uint32_t _id)
-        : name(_name), id(_id), typeCount(0), bags(NULL) { }
+    PackageGroup(ResTable* _owner, const String16& _name, uint32_t _id)
+        : owner(_owner), name(_name), id(_id), typeCount(0), bags(NULL) { }
     ~PackageGroup() {
         clearBagCache();
         const size_t N = packages.size();
         for (size_t i=0; i<N; i++) {
-            delete packages[i];
+            Package* pkg = packages[i];
+            if (pkg->owner == owner) {
+                delete pkg;
+            }
         }
     }
 
@@ -1225,15 +1233,17 @@
         }
     }
     
+    ResTable* const                 owner;
     String16 const                  name;
     uint32_t const                  id;
     Vector<Package*>                packages;
+    
+    // This is for finding typeStrings and other common package stuff.
+    Package*                        basePackage;
 
-    // Taken from the root package.
-    ResStringPool                   typeStrings;
-    ResStringPool                   keyStrings;
+    // For quick access.
     size_t                          typeCount;
-
+    
     // Computed attribute bags, first indexed by the type and second
     // by the entry in that type.
     bag_set***                      bags;
@@ -1476,7 +1486,7 @@
 
 ssize_t ResTable::Theme::resolveAttributeReference(Res_value* inOutValue,
         ssize_t blockIndex, uint32_t* outLastRef,
-        uint32_t* inoutTypeSpecFlags) const
+        uint32_t* inoutTypeSpecFlags, ResTable_config* inoutConfig) const
 {
     //printf("Resolving type=0x%x\n", inOutValue->dataType);
     if (inOutValue->dataType == Res_value::TYPE_ATTRIBUTE) {
@@ -1488,7 +1498,8 @@
             return blockIndex;
         }
     }
-    return mTable.resolveReference(inOutValue, blockIndex, outLastRef);
+    return mTable.resolveReference(inOutValue, blockIndex, outLastRef,
+            inoutTypeSpecFlags, inoutConfig);
 }
 
 void ResTable::Theme::dumpToLog() const
@@ -1560,11 +1571,35 @@
     return add(data, size, cookie, asset, copyData);
 }
 
+status_t ResTable::add(ResTable* src)
+{
+    mError = src->mError;
+    
+    for (size_t i=0; i<src->mHeaders.size(); i++) {
+        mHeaders.add(src->mHeaders[i]);
+    }
+    
+    for (size_t i=0; i<src->mPackageGroups.size(); i++) {
+        PackageGroup* srcPg = src->mPackageGroups[i];
+        PackageGroup* pg = new PackageGroup(this, srcPg->name, srcPg->id);
+        for (size_t j=0; j<srcPg->packages.size(); j++) {
+            pg->packages.add(srcPg->packages[j]);
+        }
+        pg->basePackage = srcPg->basePackage;
+        pg->typeCount = srcPg->typeCount;
+        mPackageGroups.add(pg);
+    }
+    
+    memcpy(mPackageMap, src->mPackageMap, sizeof(mPackageMap));
+    
+    return mError;
+}
+
 status_t ResTable::add(const void* data, size_t size, void* cookie,
                        Asset* asset, bool copyData)
 {
     if (!data) return NO_ERROR;
-    Header* header = new Header;
+    Header* header = new Header(this);
     header->index = mHeaders.size();
     header->cookie = cookie;
     mHeaders.add(header);
@@ -1682,10 +1717,12 @@
     N = mHeaders.size();
     for (size_t i=0; i<N; i++) {
         Header* header = mHeaders[i];
-        if (header->ownedData) {
-            free(header->ownedData);
+        if (header->owner == this) {
+            if (header->ownedData) {
+                free(header->ownedData);
+            }
+            delete header;
         }
-        delete header;
     }
 
     mPackageGroups.clear();
@@ -1728,8 +1765,8 @@
 
         outName->package = grp->name.string();
         outName->packageLen = grp->name.size();
-        outName->type = grp->typeStrings.stringAt(t, &outName->typeLen);
-        outName->name = grp->keyStrings.stringAt(
+        outName->type = grp->basePackage->typeStrings.stringAt(t, &outName->typeLen);
+        outName->name = grp->basePackage->keyStrings.stringAt(
             dtohl(entry->key.index), &outName->nameLen);
         return true;
     }
@@ -1820,7 +1857,7 @@
             }
         }
         
-        if (bestPackage != NULL && bestItem.isBetterThan(thisConfig)) {
+        if (bestPackage != NULL && bestItem.isMoreSpecificThan(thisConfig)) {
             continue;
         }
         
@@ -1855,7 +1892,8 @@
 }
 
 ssize_t ResTable::resolveReference(Res_value* value, ssize_t blockIndex,
-        uint32_t* outLastRef, uint32_t* inoutTypeSpecFlags) const
+        uint32_t* outLastRef, uint32_t* inoutTypeSpecFlags,
+        ResTable_config* outConfig) const
 {
     int count=0;
     while (blockIndex >= 0 && value->dataType == value->TYPE_REFERENCE
@@ -1863,7 +1901,8 @@
         if (outLastRef) *outLastRef = value->data;
         uint32_t lastRef = value->data;
         uint32_t newFlags = 0;
-        const ssize_t newIndex = getResource(value->data, value, true, &newFlags);
+        const ssize_t newIndex = getResource(value->data, value, true, &newFlags,
+                outConfig);
         //LOGI("Resolving reference d=%p: newIndex=%d, t=0x%02x, d=%p\n",
         //     (void*)lastRef, (int)newIndex, (int)value->dataType, (void*)value->data);
         //printf("Getting reference 0x%08x: newIndex=%d\n", value->data, newIndex);
@@ -2331,13 +2370,13 @@
             continue;
         }
 
-        const ssize_t ti = group->typeStrings.indexOfString(type, typeLen);
+        const ssize_t ti = group->basePackage->typeStrings.indexOfString(type, typeLen);
         if (ti < 0) {
             TABLE_NOISY(printf("Type not found in package %s\n", String8(group->name).string()));
             continue;
         }
 
-        const ssize_t ei = group->keyStrings.indexOfString(name, nameLen);
+        const ssize_t ei = group->basePackage->keyStrings.indexOfString(name, nameLen);
         if (ei < 0) {
             TABLE_NOISY(printf("Name not found in package %s\n", String8(group->name).string()));
             continue;
@@ -3630,25 +3669,36 @@
     PackageGroup* group = NULL;
     uint32_t id = dtohl(pkg->id);
     if (id != 0 && id < 256) {
+    
+        package = new Package(this, header, pkg);
+        if (package == NULL) {
+            return (mError=NO_MEMORY);
+        }
+        
         size_t idx = mPackageMap[id];
         if (idx == 0) {
             idx = mPackageGroups.size()+1;
 
             char16_t tmpName[sizeof(pkg->name)/sizeof(char16_t)];
             strcpy16_dtoh(tmpName, pkg->name, sizeof(pkg->name)/sizeof(char16_t));
-            group = new PackageGroup(String16(tmpName), id);
+            group = new PackageGroup(this, String16(tmpName), id);
             if (group == NULL) {
+                delete package;
                 return (mError=NO_MEMORY);
             }
 
-            err = group->typeStrings.setTo(base+dtohl(pkg->typeStrings),
+            err = package->typeStrings.setTo(base+dtohl(pkg->typeStrings),
                                            header->dataEnd-(base+dtohl(pkg->typeStrings)));
             if (err != NO_ERROR) {
+                delete group;
+                delete package;
                 return (mError=err);
             }
-            err = group->keyStrings.setTo(base+dtohl(pkg->keyStrings),
+            err = package->keyStrings.setTo(base+dtohl(pkg->keyStrings),
                                           header->dataEnd-(base+dtohl(pkg->keyStrings)));
             if (err != NO_ERROR) {
+                delete group;
+                delete package;
                 return (mError=err);
             }
 
@@ -3657,6 +3707,8 @@
             if (err < NO_ERROR) {
                 return (mError=err);
             }
+            group->basePackage = package;
+            
             mPackageMap[id] = (uint8_t)idx;
         } else {
             group = mPackageGroups.itemAt(idx-1);
@@ -3664,10 +3716,6 @@
                 return (mError=UNKNOWN_ERROR);
             }
         }
-        package = new Package(header, pkg);
-        if (package == NULL) {
-            return (mError=NO_MEMORY);
-        }
         err = group->packages.add(package);
         if (err < NO_ERROR) {
             return (mError=err);
@@ -3830,9 +3878,88 @@
 #define CHAR16_ARRAY_EQ(constant, var, len) \
         ((len == (sizeof(constant)/sizeof(constant[0]))) && (0 == memcmp((var), (constant), (len))))
 
-void ResTable::print() const
+void print_complex(uint32_t complex, bool isFraction)
 {
-    printf("mError=0x%x (%s)\n", mError, strerror(mError));
+    const float MANTISSA_MULT =
+        1.0f / (1<<Res_value::COMPLEX_MANTISSA_SHIFT);
+    const float RADIX_MULTS[] = {
+        1.0f*MANTISSA_MULT, 1.0f/(1<<7)*MANTISSA_MULT,
+        1.0f/(1<<15)*MANTISSA_MULT, 1.0f/(1<<23)*MANTISSA_MULT
+    };
+
+    float value = (complex&(Res_value::COMPLEX_MANTISSA_MASK
+                   <<Res_value::COMPLEX_MANTISSA_SHIFT))
+            * RADIX_MULTS[(complex>>Res_value::COMPLEX_RADIX_SHIFT)
+                            & Res_value::COMPLEX_RADIX_MASK];
+    printf("%f", value);
+    
+    if (!isFraction) {
+        switch ((complex>>Res_value::COMPLEX_UNIT_SHIFT)&Res_value::COMPLEX_UNIT_MASK) {
+            case Res_value::COMPLEX_UNIT_PX: printf("px"); break;
+            case Res_value::COMPLEX_UNIT_DIP: printf("dp"); break;
+            case Res_value::COMPLEX_UNIT_SP: printf("sp"); break;
+            case Res_value::COMPLEX_UNIT_PT: printf("pt"); break;
+            case Res_value::COMPLEX_UNIT_IN: printf("in"); break;
+            case Res_value::COMPLEX_UNIT_MM: printf("mm"); break;
+            default: printf(" (unknown unit)"); break;
+        }
+    } else {
+        switch ((complex>>Res_value::COMPLEX_UNIT_SHIFT)&Res_value::COMPLEX_UNIT_MASK) {
+            case Res_value::COMPLEX_UNIT_FRACTION: printf("%%"); break;
+            case Res_value::COMPLEX_UNIT_FRACTION_PARENT: printf("%%p"); break;
+            default: printf(" (unknown unit)"); break;
+        }
+    }
+}
+
+void ResTable::print_value(const Package* pkg, const Res_value& value) const
+{
+    if (value.dataType == Res_value::TYPE_NULL) {
+        printf("(null)\n");
+    } else if (value.dataType == Res_value::TYPE_REFERENCE) {
+        printf("(reference) 0x%08x\n", value.data);
+    } else if (value.dataType == Res_value::TYPE_ATTRIBUTE) {
+        printf("(attribute) 0x%08x\n", value.data);
+    } else if (value.dataType == Res_value::TYPE_STRING) {
+        size_t len;
+        const char16_t* str = pkg->header->values.stringAt(
+                value.data, &len);
+        if (str == NULL) {
+            printf("(string) null\n");
+        } else {
+            printf("(string) \"%s\"\n",
+                    String8(str, len).string());
+        } 
+    } else if (value.dataType == Res_value::TYPE_FLOAT) {
+        printf("(float) %g\n", *(const float*)&value.data);
+    } else if (value.dataType == Res_value::TYPE_DIMENSION) {
+        printf("(dimension) ");
+        print_complex(value.data, false);
+        printf("\n");
+    } else if (value.dataType == Res_value::TYPE_FRACTION) {
+        printf("(fraction) ");
+        print_complex(value.data, true);
+        printf("\n");
+    } else if (value.dataType >= Res_value::TYPE_FIRST_COLOR_INT
+            || value.dataType <= Res_value::TYPE_LAST_COLOR_INT) {
+        printf("(color) #%08x\n", value.data);
+    } else if (value.dataType == Res_value::TYPE_INT_BOOLEAN) {
+        printf("(boolean) %s\n", value.data ? "true" : "false");
+    } else if (value.dataType >= Res_value::TYPE_FIRST_INT
+            || value.dataType <= Res_value::TYPE_LAST_INT) {
+        printf("(int) 0x%08x or %d\n", value.data, value.data);
+    } else {
+        printf("(unknown type) t=0x%02x d=0x%08x (s=0x%04x r=0x%02x)\n",
+               (int)value.dataType, (int)value.data,
+               (int)value.size, (int)value.res0);
+    }
+}
+
+void ResTable::print(bool inclValues) const
+{
+    if (mError != 0) {
+        printf("mError=0x%x (%s)\n", mError, strerror(mError));
+    }
 #if 0
     printf("mParams=%c%c-%c%c,\n",
             mParams.language[0], mParams.language[1],
@@ -3883,7 +4010,16 @@
                         printf("      NON-INTEGER ResTable_type ADDRESS: %p\n", type);
                         continue;
                     }
-                    printf("      config %d lang=%c%c cnt=%c%c orien=%d touch=%d density=%d key=%d infl=%d nav=%d w=%d h=%d\n",
+                    char density[16];
+                    uint16_t dval = dtohs(type->config.density);
+                    if (dval == ResTable_config::DENSITY_DEFAULT) {
+                        strcpy(density, "def");
+                    } else if (dval == ResTable_config::DENSITY_NONE) {
+                        strcpy(density, "no");
+                    } else {
+                        sprintf(density, "%d", (int)dval);
+                    }
+                    printf("      config %d lang=%c%c cnt=%c%c orien=%d touch=%d density=%s key=%d infl=%d nav=%d w=%d h=%d sz=%d lng=%d\n",
                            (int)configIndex,
                            type->config.language[0] ? type->config.language[0] : '-',
                            type->config.language[1] ? type->config.language[1] : '-',
@@ -3891,12 +4027,14 @@
                            type->config.country[1] ? type->config.country[1] : '-',
                            type->config.orientation,
                            type->config.touchscreen,
-                           dtohs(type->config.density),
+                           density,
                            type->config.keyboard,
                            type->config.inputFlags,
                            type->config.navigation,
                            dtohs(type->config.screenWidth),
-                           dtohs(type->config.screenHeight));
+                           dtohs(type->config.screenHeight),
+                           type->config.screenLayout&ResTable_config::MASK_SCREENSIZE,
+                           type->config.screenLayout&ResTable_config::MASK_SCREENLONG);
                     size_t entryCount = dtohl(type->entryCount);
                     uint32_t entriesStart = dtohl(type->entriesStart);
                     if ((entriesStart&0x3) != 0) {
@@ -3947,32 +4085,60 @@
                                  (void*)(entriesStart + thisOffset));
                             continue;
                         }
+                        
+                        uint16_t esize = dtohs(ent->size);
+                        if ((esize&0x3) != 0) {
+                            printf("NON-INTEGER ResTable_entry SIZE: %p\n", (void*)esize);
+                            continue;
+                        }
+                        if ((thisOffset+esize) > typeSize) {
+                            printf("ResTable_entry OUT OF BOUNDS: %p+%p+%p (size is %p)\n",
+                                   (void*)entriesStart, (void*)thisOffset,
+                                   (void*)esize, (void*)typeSize);
+                            continue;
+                        }
+                            
+                        const Res_value* valuePtr = NULL;
+                        const ResTable_map_entry* bagPtr = NULL;
+                        Res_value value;
                         if ((dtohs(ent->flags)&ResTable_entry::FLAG_COMPLEX) != 0) {
                             printf("<bag>");
+                            bagPtr = (const ResTable_map_entry*)ent;
                         } else {
-                            uint16_t esize = dtohs(ent->size);
-                            if ((esize&0x3) != 0) {
-                                printf("NON-INTEGER ResTable_entry SIZE: %p\n", (void*)esize);
-                                continue;
-                            }
-                            if ((thisOffset+esize) > typeSize) {
-                                printf("ResTable_entry OUT OF BOUNDS: %p+%p+%p (size is %p)\n",
-                                       (void*)entriesStart, (void*)thisOffset,
-                                       (void*)esize, (void*)typeSize);
-                                continue;
-                            }
-                            
-                            const Res_value* value = (const Res_value*)
+                            valuePtr = (const Res_value*)
                                 (((const uint8_t*)ent) + esize);
+                            value.copyFrom_dtoh(*valuePtr);
                             printf("t=0x%02x d=0x%08x (s=0x%04x r=0x%02x)",
-                                   (int)value->dataType, (int)dtohl(value->data),
-                                   (int)dtohs(value->size), (int)value->res0);
+                                   (int)value.dataType, (int)value.data,
+                                   (int)value.size, (int)value.res0);
                         }
                         
                         if ((dtohs(ent->flags)&ResTable_entry::FLAG_PUBLIC) != 0) {
                             printf(" (PUBLIC)");
                         }
                         printf("\n");
+                        
+                        if (inclValues) {
+                            if (valuePtr != NULL) {
+                                printf("          ");
+                                print_value(pkg, value);
+                            } else if (bagPtr != NULL) {
+                                const int N = dtohl(bagPtr->count);
+                                const ResTable_map* mapPtr = (const ResTable_map*)
+                                        (((const uint8_t*)ent) + esize);
+                                printf("          Parent=0x%08x, Count=%d\n",
+                                    dtohl(bagPtr->parent.ident), N);
+                                for (int i=0; i<N; i++) {
+                                    printf("          #%i (Key=0x%08x): ",
+                                        i, dtohl(mapPtr->name.ident));
+                                    value.copyFrom_dtoh(mapPtr->value);
+                                    print_value(pkg, value);
+                                    const size_t size = dtohs(mapPtr->value.size);
+                                    mapPtr = (ResTable_map*)(((const uint8_t*)mapPtr)
+                                            + size + sizeof(*mapPtr)-sizeof(mapPtr->value));
+                                }
+                            }
+                        }
                     }
                 }
             }
diff --git a/libs/utils/String8.cpp b/libs/utils/String8.cpp
index c50d343..e908ec1 100644
--- a/libs/utils/String8.cpp
+++ b/libs/utils/String8.cpp
@@ -25,25 +25,39 @@
 
 #include <ctype.h>
 
-namespace android {
+/*
+ * Functions outside android is below the namespace android, since they use
+ * functions and constants in android namespace.
+ */
 
 // ---------------------------------------------------------------------------
 
-static const uint32_t kByteMask = 0x000000BF;
-static const uint32_t kByteMark = 0x00000080;
+namespace android {
+
+static const char32_t kByteMask = 0x000000BF;
+static const char32_t kByteMark = 0x00000080;
 
 // Surrogates aren't valid for UTF-32 characters, so define some
 // constants that will let us screen them out.
-static const uint32_t kUnicodeSurrogateHighStart  = 0x0000D800;
-static const uint32_t kUnicodeSurrogateHighEnd    = 0x0000DBFF;
-static const uint32_t kUnicodeSurrogateLowStart   = 0x0000DC00;
-static const uint32_t kUnicodeSurrogateLowEnd     = 0x0000DFFF;
-static const uint32_t kUnicodeSurrogateStart      = kUnicodeSurrogateHighStart;
-static const uint32_t kUnicodeSurrogateEnd        = kUnicodeSurrogateLowEnd;
+static const char32_t kUnicodeSurrogateHighStart  = 0x0000D800;
+static const char32_t kUnicodeSurrogateHighEnd    = 0x0000DBFF;
+static const char32_t kUnicodeSurrogateLowStart   = 0x0000DC00;
+static const char32_t kUnicodeSurrogateLowEnd     = 0x0000DFFF;
+static const char32_t kUnicodeSurrogateStart      = kUnicodeSurrogateHighStart;
+static const char32_t kUnicodeSurrogateEnd        = kUnicodeSurrogateLowEnd;
+static const char32_t kUnicodeMaxCodepoint        = 0x0010FFFF;
 
 // Mask used to set appropriate bits in first byte of UTF-8 sequence,
 // indexed by number of bytes in the sequence.
-static const uint32_t kFirstByteMark[] = {
+// 0xxxxxxx
+// -> (00-7f) 7bit. Bit mask for the first byte is 0x00000000
+// 110yyyyx 10xxxxxx
+// -> (c0-df)(80-bf) 11bit. Bit mask is 0x000000C0
+// 1110yyyy 10yxxxxx 10xxxxxx
+// -> (e0-ef)(80-bf)(80-bf) 16bit. Bit mask is 0x000000E0
+// 11110yyy 10yyxxxx 10xxxxxx 10xxxxxx
+// -> (f0-f7)(80-bf)(80-bf)(80-bf) 21bit. Bit mask is 0x000000F0
+static const char32_t kFirstByteMark[] = {
     0x00000000, 0x00000000, 0x000000C0, 0x000000E0, 0x000000F0
 };
 
@@ -52,7 +66,7 @@
 #define RES_PATH_SEPARATOR '/'
 
 // Return number of utf8 bytes required for the character.
-static size_t utf32_to_utf8_bytes(uint32_t srcChar)
+static size_t utf32_to_utf8_bytes(char32_t srcChar)
 {
     size_t bytesToWrite;
 
@@ -79,7 +93,7 @@
         }
     }
     // Max code point for Unicode is 0x0010FFFF.
-    else if (srcChar < 0x00110000)
+    else if (srcChar <= kUnicodeMaxCodepoint)
     {
         bytesToWrite = 4;
     }
@@ -94,7 +108,7 @@
 
 // Write out the source character to <dstP>.
 
-static void utf32_to_utf8(uint8_t* dstP, uint32_t srcChar, size_t bytes)
+static void utf32_to_utf8(uint8_t* dstP, char32_t srcChar, size_t bytes)
 {
     dstP += bytes;
     switch (bytes)
@@ -126,7 +140,7 @@
 	  // Bite me, Darwin!
 		gDarwinIsReallyAnnoying = gDarwinCantLoadAllObjects;
 #endif
-			
+
     SharedBuffer* buf = SharedBuffer::alloc(1);
     char* str = (char*)buf->data();
     *str = 0;
@@ -160,20 +174,20 @@
     return getEmptyString();
 }
 
-// Note: not dealing with expanding surrogate pairs.
-static char* allocFromUTF16(const char16_t* in, size_t len)
+template<typename T, typename L>
+static char* allocFromUTF16OrUTF32(const T* in, L len)
 {
     if (len == 0) return getEmptyString();
-    
+
     size_t bytes = 0;
-    const char16_t* end = in+len;
-    const char16_t* p = in;
-    
+    const T* end = in+len;
+    const T* p = in;
+
     while (p < end) {
         bytes += utf32_to_utf8_bytes(*p);
         p++;
     }
-    
+
     SharedBuffer* buf = SharedBuffer::alloc(bytes+1);
     LOG_ASSERT(buf, "Unable to allocate shared buffer");
     if (buf) {
@@ -181,19 +195,30 @@
         char* str = (char*)buf->data();
         char* d = str;
         while (p < end) {
-            uint32_t c = *p++;
+            const T c = *p++;
             size_t len = utf32_to_utf8_bytes(c);
             utf32_to_utf8((uint8_t*)d, c, len);
             d += len;
         }
         *d = 0;
-        
+
         return str;
     }
-    
+
     return getEmptyString();
 }
 
+// Note: not dealing with expanding surrogate pairs.
+static char* allocFromUTF16(const char16_t* in, size_t len)
+{
+    return allocFromUTF16OrUTF32<char16_t, size_t>(in, len);
+}
+
+static char* allocFromUTF32(const char32_t* in, size_t len)
+{
+    return allocFromUTF16OrUTF32<char32_t, size_t>(in, len);
+}
+
 // ---------------------------------------------------------------------------
 
 String8::String8()
@@ -238,6 +263,16 @@
 {
 }
 
+String8::String8(const char32_t* o)
+    : mString(allocFromUTF32(o, strlen32(o)))
+{
+}
+
+String8::String8(const char32_t* o, size_t len)
+    : mString(allocFromUTF32(o, len))
+{
+}
+
 String8::~String8()
 {
     SharedBuffer::bufferFromData(mString)->release();
@@ -280,6 +315,16 @@
     return NO_MEMORY;
 }
 
+status_t String8::setTo(const char32_t* other, size_t len)
+{
+    SharedBuffer::bufferFromData(mString)->release();
+    mString = allocFromUTF32(other, len);
+    if (mString) return NO_ERROR;
+
+    mString = getEmptyString();
+    return NO_MEMORY;
+}
+
 status_t String8::append(const String8& other)
 {
     const size_t otherLen = other.bytes();
@@ -418,6 +463,21 @@
     unlockBuffer(len);
 }
 
+size_t String8::getUtf32Length() const
+{
+    return utf32_length(mString, length());
+}
+
+int32_t String8::getUtf32At(size_t index, size_t *next_index) const
+{
+    return utf32_at(mString, length(), index, next_index);
+}
+
+size_t String8::getUtf32(char32_t* dst, size_t dst_len) const
+{
+    return utf8_to_utf32(mString, length(), dst, dst_len);
+}
+
 TextOutput& operator<<(TextOutput& to, const String8& val)
 {
     to << val.string();
@@ -427,7 +487,6 @@
 // ---------------------------------------------------------------------------
 // Path functions
 
-
 void String8::setPathName(const char* name)
 {
     setPathName(name, strlen(name));
@@ -600,5 +659,192 @@
     return *this;
 }
 
-
 }; // namespace android
+
+// ---------------------------------------------------------------------------
+
+size_t strlen32(const char32_t *s)
+{
+  const char32_t *ss = s;
+  while ( *ss )
+    ss++;
+  return ss-s;
+}
+
+size_t strnlen32(const char32_t *s, size_t maxlen)
+{
+  const char32_t *ss = s;
+  while ((maxlen > 0) && *ss) {
+    ss++;
+    maxlen--;
+  }
+  return ss-s;
+}
+
+size_t utf8_length(const char *src)
+{
+    const char *cur = src;
+    size_t ret = 0;
+    while (*cur != '\0') {
+        const char first_char = *cur++;
+        if ((first_char & 0x80) == 0) { // ASCII
+            ret += 1;
+            continue;
+        }
+        // (UTF-8's character must not be like 10xxxxxx,
+        //  but 110xxxxx, 1110xxxx, ... or 1111110x)
+        if ((first_char & 0x40) == 0) {
+            return 0;
+        }
+
+        int32_t mask, to_ignore_mask;
+        size_t num_to_read = 0;
+        char32_t utf32 = 0;
+        for (num_to_read = 1, mask = 0x40, to_ignore_mask = 0x80;
+             num_to_read < 5 && (first_char & mask);
+             num_to_read++, to_ignore_mask |= mask, mask >>= 1) {
+            if ((*cur & 0xC0) != 0x80) { // must be 10xxxxxx
+                return 0;
+            }
+            // 0x3F == 00111111
+            utf32 = (utf32 << 6) + (*cur++ & 0x3F);
+        }
+        // "first_char" must be (110xxxxx - 11110xxx)
+        if (num_to_read == 5) {
+            return 0;
+        }
+        to_ignore_mask |= mask;
+        utf32 |= ((~to_ignore_mask) & first_char) << (6 * (num_to_read - 1));
+        if (utf32 > android::kUnicodeMaxCodepoint) {
+            return 0;
+        }
+
+        ret += num_to_read;
+    }
+    return ret;
+}
+
+size_t utf32_length(const char *src, size_t src_len)
+{
+    if (src == NULL || src_len == 0) {
+        return 0;
+    }
+    size_t ret = 0;
+    const char* cur;
+    const char* end;
+    size_t num_to_skip;
+    for (cur = src, end = src + src_len, num_to_skip = 1;
+         cur < end;
+         cur += num_to_skip, ret++) {
+        const char first_char = *cur;
+        num_to_skip = 1;
+        if ((first_char & 0x80) == 0) {  // ASCII
+            continue;
+        }
+        int32_t mask;
+
+        for (mask = 0x40; (first_char & mask); num_to_skip++, mask >>= 1) {
+        }
+    }
+    return ret;
+}
+
+size_t utf8_length_from_utf32(const char32_t *src, size_t src_len)
+{
+    if (src == NULL || src_len == 0) {
+        return 0;
+    }
+    size_t ret = 0;
+    const char32_t *end = src + src_len;
+    while (src < end) {
+        ret += android::utf32_to_utf8_bytes(*src++);
+    }
+    return ret;
+}
+
+static int32_t utf32_at_internal(const char* cur, size_t *num_read)
+{
+    const char first_char = *cur;
+    if ((first_char & 0x80) == 0) { // ASCII
+        *num_read = 1;
+        return *cur;
+    }
+    cur++;
+    char32_t mask, to_ignore_mask;
+    size_t num_to_read = 0;
+    char32_t utf32 = first_char;
+    for (num_to_read = 1, mask = 0x40, to_ignore_mask = 0xFFFFFF80;
+         (first_char & mask);
+         num_to_read++, to_ignore_mask |= mask, mask >>= 1) {
+        // 0x3F == 00111111
+        utf32 = (utf32 << 6) + (*cur++ & 0x3F);
+    }
+    to_ignore_mask |= mask;
+    utf32 &= ~(to_ignore_mask << (6 * (num_to_read - 1)));
+
+    *num_read = num_to_read;
+    return static_cast<int32_t>(utf32);
+}
+
+int32_t utf32_at(const char *src, size_t src_len,
+                 size_t index, size_t *next_index)
+{
+    if (index >= src_len) {
+        return -1;
+    }
+    size_t dummy_index;
+    if (next_index == NULL) {
+        next_index = &dummy_index;
+    }
+    size_t num_read;
+    int32_t ret = utf32_at_internal(src + index, &num_read);
+    if (ret >= 0) {
+        *next_index = index + num_read;
+    }
+
+    return ret;
+}
+
+size_t utf8_to_utf32(const char* src, size_t src_len,
+                     char32_t* dst, size_t dst_len)
+{
+    if (src == NULL || src_len == 0 || dst == NULL || dst_len == 0) {
+        return 0;
+    }
+
+    const char* cur = src;
+    const char* end = src + src_len;
+    char32_t* cur_utf32 = dst;
+    const char32_t* end_utf32 = dst + dst_len;
+    while (cur_utf32 < end_utf32 && cur < end) {
+        size_t num_read;
+        *cur_utf32++ =
+                static_cast<char32_t>(utf32_at_internal(cur, &num_read));
+        cur += num_read;
+    }
+    if (cur_utf32 < end_utf32) {
+        *cur_utf32 = 0;
+    }
+    return static_cast<size_t>(cur_utf32 - dst);
+}
+
+size_t utf32_to_utf8(const char32_t* src, size_t src_len,
+                     char* dst, size_t dst_len)
+{
+    if (src == NULL || src_len == 0 || dst == NULL || dst_len == 0) {
+        return 0;
+    }
+    const char32_t *cur_utf32 = src;
+    const char32_t *end_utf32 = src + src_len;
+    char *cur = dst;
+    const char *end = dst + dst_len;
+    while (cur_utf32 < end_utf32 && cur < end) {
+        size_t len = android::utf32_to_utf8_bytes(*cur_utf32);
+        android::utf32_to_utf8((uint8_t *)cur, *cur_utf32++, len);
+        cur += len;
+    }
+    if (cur < end) {
+        *cur = '\0';
+    }
+    return cur - dst;
+}
diff --git a/libs/utils/Unicode.cpp b/libs/utils/Unicode.cpp
index 33f535f..f92703e 100644
--- a/libs/utils/Unicode.cpp
+++ b/libs/utils/Unicode.cpp
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-#include "utils/AndroidUnicode.h"
-#include "characterData.h"
+#include <utils/AndroidUnicode.h>
+#include "CharacterData.h"
 
 #define LOG_TAG "Unicode"
-#include "utils/Log.h"
+#include <utils/Log.h>
 
 // ICU headers for using macros
 #include <unicode/utf16.h>
diff --git a/libs/utils/ZipEntry.cpp b/libs/utils/ZipEntry.cpp
index fbc9e67..96f9fc4 100644
--- a/libs/utils/ZipEntry.cpp
+++ b/libs/utils/ZipEntry.cpp
@@ -20,8 +20,8 @@
 
 #define LOG_TAG "zip"
 
-#include "utils/ZipEntry.h"
-#include "utils/Log.h"
+#include <utils/ZipEntry.h>
+#include <utils/Log.h>
 
 #include <stdio.h>
 #include <string.h>
diff --git a/libs/utils/ZipFile.cpp b/libs/utils/ZipFile.cpp
index 89aa874..6f27d17 100644
--- a/libs/utils/ZipFile.cpp
+++ b/libs/utils/ZipFile.cpp
@@ -20,9 +20,9 @@
 
 #define LOG_TAG "zip"
 
-#include "utils/ZipFile.h"
-#include "utils/ZipUtils.h"
-#include "utils/Log.h"
+#include <utils/ZipFile.h>
+#include <utils/ZipUtils.h>
+#include <utils/Log.h>
 
 #include <zlib.h>
 #define DEF_MEM_LEVEL 8                // normally in zutil.h?
diff --git a/libs/utils/ZipFileCRO.cpp b/libs/utils/ZipFileCRO.cpp
index d312daf..45f6c8b 100644
--- a/libs/utils/ZipFileCRO.cpp
+++ b/libs/utils/ZipFileCRO.cpp
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#include "utils/ZipFileCRO.h"
-#include "utils/ZipFileRO.h"
+#include <utils/ZipFileCRO.h>
+#include <utils/ZipFileRO.h>
 
 using namespace android;
 
diff --git a/libs/utils/ZipFileRO.cpp b/libs/utils/ZipFileRO.cpp
index ae8c719..6c701dd 100644
--- a/libs/utils/ZipFileRO.cpp
+++ b/libs/utils/ZipFileRO.cpp
@@ -19,9 +19,9 @@
 //
 #define LOG_TAG "zipro"
 //#define LOG_NDEBUG 0
-#include "utils/ZipFileRO.h"
-#include "utils/Log.h"
-#include "utils/misc.h"
+#include <utils/ZipFileRO.h>
+#include <utils/Log.h>
+#include <utils/misc.h>
 
 #include <zlib.h>
 
diff --git a/libs/utils/ZipUtils.cpp b/libs/utils/ZipUtils.cpp
index bfbacfe..9138878 100644
--- a/libs/utils/ZipUtils.cpp
+++ b/libs/utils/ZipUtils.cpp
@@ -20,9 +20,9 @@
 
 #define LOG_TAG "ziputil"
 
-#include "utils/ZipUtils.h"
-#include "utils/ZipFileRO.h"
-#include "utils/Log.h"
+#include <utils/ZipUtils.h>
+#include <utils/ZipFileRO.h>
+#include <utils/Log.h>
 
 #include <stdlib.h>
 #include <string.h>
@@ -210,7 +210,7 @@
             LOGV("+++ reading %ld bytes (%ld left)\n",
                 getSize, compRemaining);
 
-            int cc = fread(readBuf, getSize, 1, fp);
+            int cc = fread(readBuf, 1, getSize, fp);
             if (cc != (int) getSize) {
                 LOGD("inflate read failed (%d vs %ld)\n",
                     cc, getSize);
@@ -341,4 +341,3 @@
 
     return true;
 }
-
diff --git a/libs/utils/futex_synchro.c b/libs/utils/futex_synchro.c
index ba19520..ab48c69 100644
--- a/libs/utils/futex_synchro.c
+++ b/libs/utils/futex_synchro.c
@@ -28,6 +28,7 @@
 // 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
diff --git a/opengl/include/GLES/glext.h b/opengl/include/GLES/glext.h
index 4c01871..a8fe2e9 100644
--- a/opengl/include/GLES/glext.h
+++ b/opengl/include/GLES/glext.h
@@ -599,21 +599,6 @@
 #define GL_EXT_texture_filter_anisotropic 1
 #endif
 
-/*------------------------------------------------------------------------*
- * dalvik extension functions
- *------------------------------------------------------------------------*/
-#ifdef ANDROID
-void glColorPointerBounds(GLint size, GLenum type, GLsizei stride,
-        const GLvoid *ptr, GLsizei count);
-void glNormalPointerBounds(GLenum type, GLsizei stride,
-        const GLvoid *pointer, GLsizei count);
-void glTexCoordPointerBounds(GLint size, GLenum type,
-        GLsizei stride, const GLvoid *pointer, GLsizei count);
-void glVertexPointerBounds(GLint size, GLenum type,
-        GLsizei stride, const GLvoid *pointer, GLsizei count);
-#endif
-
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/opengl/include/KHR/khrplatform.h b/opengl/include/KHR/khrplatform.h
index 4cc27c5..1660bd7 100644
--- a/opengl/include/KHR/khrplatform.h
+++ b/opengl/include/KHR/khrplatform.h
@@ -91,6 +91,8 @@
 #   define KHRONOS_APICALL __declspec(dllimport)
 #elif defined (__SYMBIAN32__)
 #   define KHRONOS_APICALL IMPORT_C
+#elif defined(ANDROID)
+#   define KHRONOS_APICALL __attribute__((visibility("default")))
 #else
 #   define KHRONOS_APICALL
 #endif
diff --git a/opengl/libagl/Android.mk b/opengl/libagl/Android.mk
index 99efe4c..3ce0414 100644
--- a/opengl/libagl/Android.mk
+++ b/opengl/libagl/Android.mk
@@ -33,6 +33,8 @@
 endif
 
 LOCAL_SHARED_LIBRARIES := libcutils libutils libpixelflinger
+LOCAL_CFLAGS += -fvisibility=hidden
+
 LOCAL_LDLIBS := -lpthread -ldl
 LOCAL_MODULE:= libagl
 
diff --git a/opengl/libagl/array.cpp b/opengl/libagl/array.cpp
index 8fa7566..3e9c6a5 100644
--- a/opengl/libagl/array.cpp
+++ b/opengl/libagl/array.cpp
@@ -951,6 +951,8 @@
     v->index = first;
     first &= vertex_cache_t::INDEX_MASK;
     const GLubyte* vp = c->arrays.vertex.element(first);
+    v->obj.z = 0;
+    v->obj.w = 0x10000;
     c->arrays.vertex.fetch(c, v->obj.v, vp);
     c->arrays.mvp_transform(&c->transforms.mvp, &v->clip, &v->obj);
     c->arrays.perspective(c, v);
@@ -966,6 +968,8 @@
     do {
         v->flags = 0;
         v->index = first++;
+        v->obj.z = 0;
+        v->obj.w = 0x10000;
         c->arrays.vertex.fetch(c, v->obj.v, vp);
         c->arrays.mvp_transform(mvp, &v->clip, &v->obj);
         c->arrays.perspective(c, v);
diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp
index 3b4c041..4461567 100644
--- a/opengl/libagl/egl.cpp
+++ b/opengl/libagl/egl.cpp
@@ -1,17 +1,17 @@
-/* 
+/*
 **
 ** 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 
+** 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.
 */
 
@@ -478,22 +478,38 @@
 };
 
 static const extention_map_t gExtentionMap[] = {
-    { "glDrawTexsOES",              (void(*)())&glDrawTexsOES },
-    { "glDrawTexiOES",              (void(*)())&glDrawTexiOES },
-    { "glDrawTexfOES",              (void(*)())&glDrawTexfOES },
-    { "glDrawTexxOES",              (void(*)())&glDrawTexxOES },
-    { "glDrawTexsvOES",             (void(*)())&glDrawTexsvOES },
-    { "glDrawTexivOES",             (void(*)())&glDrawTexivOES },
-    { "glDrawTexfvOES",             (void(*)())&glDrawTexfvOES },
-    { "glDrawTexxvOES",             (void(*)())&glDrawTexxvOES },
-    { "glQueryMatrixxOES",          (void(*)())&glQueryMatrixxOES },
-    { "glClipPlanef",               (void(*)())&glClipPlanef },
-    { "glClipPlanex",               (void(*)())&glClipPlanex },
-    { "glBindBuffer",               (void(*)())&glBindBuffer },
-    { "glBufferData",               (void(*)())&glBufferData },
-    { "glBufferSubData",            (void(*)())&glBufferSubData },
-    { "glDeleteBuffers",            (void(*)())&glDeleteBuffers },
-    { "glGenBuffers",               (void(*)())&glGenBuffers },
+    { "glDrawTexsOES",
+            (__eglMustCastToProperFunctionPointerType)&glDrawTexsOES },
+    { "glDrawTexiOES",
+            (__eglMustCastToProperFunctionPointerType)&glDrawTexiOES },
+    { "glDrawTexfOES",
+            (__eglMustCastToProperFunctionPointerType)&glDrawTexfOES },
+    { "glDrawTexxOES",
+            (__eglMustCastToProperFunctionPointerType)&glDrawTexxOES },
+    { "glDrawTexsvOES",
+            (__eglMustCastToProperFunctionPointerType)&glDrawTexsvOES },
+    { "glDrawTexivOES",
+            (__eglMustCastToProperFunctionPointerType)&glDrawTexivOES },
+    { "glDrawTexfvOES",
+            (__eglMustCastToProperFunctionPointerType)&glDrawTexfvOES },
+    { "glDrawTexxvOES",
+            (__eglMustCastToProperFunctionPointerType)&glDrawTexxvOES },
+    { "glQueryMatrixxOES",
+            (__eglMustCastToProperFunctionPointerType)&glQueryMatrixxOES },
+    { "glClipPlanef",
+            (__eglMustCastToProperFunctionPointerType)&glClipPlanef },
+    { "glClipPlanex",
+            (__eglMustCastToProperFunctionPointerType)&glClipPlanex },
+    { "glBindBuffer",
+            (__eglMustCastToProperFunctionPointerType)&glBindBuffer },
+    { "glBufferData",
+            (__eglMustCastToProperFunctionPointerType)&glBufferData },
+    { "glBufferSubData",
+            (__eglMustCastToProperFunctionPointerType)&glBufferSubData },
+    { "glDeleteBuffers",
+            (__eglMustCastToProperFunctionPointerType)&glDeleteBuffers },
+    { "glGenBuffers",
+            (__eglMustCastToProperFunctionPointerType)&glGenBuffers },
 };
 
 /* 
@@ -1087,7 +1103,7 @@
         // default value
         if (binarySearch<config_pair_t>(
                 (config_pair_t const*)attrib_list,
-                0, numAttributes,
+                0, numAttributes-1,
                 config_defaults[j].key) < 0)
         {
             for (int i=0 ; i<numConfigs ; i++) {
@@ -1299,6 +1315,8 @@
         }
     }
 
+    // TODO: call connect / disconnect on the surface
+
     ogles_context_t* gl = (ogles_context_t*)ctx;
     if (makeCurrent(gl) == 0) {
         if (ctx) {
diff --git a/opengl/libagl/light.cpp b/opengl/libagl/light.cpp
index 25c41d0..f211bca 100644
--- a/opengl/libagl/light.cpp
+++ b/opengl/libagl/light.cpp
@@ -38,13 +38,14 @@
 static void lightVertexMaterial(ogles_context_t* c, vertex_t* v);
 
 static inline void vscale3(GLfixed* d, const GLfixed* m, GLfixed s);
-static inline void vsub3w(GLfixed* d, const GLfixed* a, const GLfixed* b);
 
 static __attribute__((noinline))
 void vnorm3(GLfixed* d, const GLfixed* a);
 
 static inline void vsa3(GLfixed* d,
     const GLfixed* m, GLfixed s, const GLfixed* a);
+static inline void vss3(GLfixed* d,
+    const GLfixed* m, GLfixed s, const GLfixed* a);
 static inline void vmla3(GLfixed* d,
     const GLfixed* m0, const GLfixed* m1, const GLfixed* a);
 static inline void vmul3(GLfixed* d,
@@ -151,18 +152,10 @@
 }
 
 static inline
-void vsub3w(GLfixed* d, const GLfixed* a, const GLfixed* b) {
-    const GLfixed wa = a[3];
-    const GLfixed wb = b[3];
-    if (ggl_likely(wa == wb)) {
-        d[0] = a[0] - b[0];
-        d[1] = a[1] - b[1];
-        d[2] = a[2] - b[2];
-    } else {
-        d[0] = gglMulSubx(a[0], wb, gglMulx(b[0], wa));
-        d[1] = gglMulSubx(a[1], wb, gglMulx(b[1], wa));
-        d[2] = gglMulSubx(a[2], wb, gglMulx(b[2], wa));
-    }
+void vss3(GLfixed* d, const GLfixed* m, GLfixed s, const GLfixed* a) {
+    d[0] = gglMulSubx(m[0], s, a[0]);
+    d[1] = gglMulSubx(m[1], s, a[1]);
+    d[2] = gglMulSubx(m[2], s, a[2]);
 }
 
 static inline
@@ -223,13 +216,18 @@
 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);
         light_t& l = c->lighting.lights[i];
-        c->transforms.mvui.point3(&c->transforms.mvui,
+        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);
     }
 }
 
@@ -318,6 +316,11 @@
         vmul3(l.implicitAmbient.v,  material.ambient.v,  l.ambient.v);
         vmul3(l.implicitDiffuse.v,  material.diffuse.v,  l.diffuse.v);
         vmul3(l.implicitSpecular.v, material.specular.v, l.specular.v);
+        // this is just a flag to tell if we have a specular component
+        l.implicitSpecular.v[3] =
+                l.implicitSpecular.r |
+                l.implicitSpecular.g |
+                l.implicitSpecular.b;
     }
     // emission and ambient for the whole scene
     vmla3(  c->lighting.implicitSceneEmissionAndAmbient.v,
@@ -343,7 +346,11 @@
         vec4_t n;
         c->arrays.normal.fetch(c, n.v,
             c->arrays.normal.element(v->index & vertex_cache_t::INDEX_MASK));
-        if (c->transforms.rescaleNormals == GL_NORMALIZE)
+
+        // TODO: right now we handle GL_RESCALE_NORMALS as if ti were
+        // GL_NORMALIZE. We could optimize this by  scaling mvui 
+        // appropriately instead.
+        if (c->transforms.rescaleNormals)
             vnorm3(n.v, n.v);
 
         const material_t& material = c->lighting.front;
@@ -360,7 +367,8 @@
 
             // compute vertex-to-light vector
             if (ggl_unlikely(l.position.w)) {
-                vsub3w(d.v, l.objPosition.v, v->obj.v);
+                // lightPos/1.0 - vertex/vertex.w == lightPos*vertex.w - vertex
+                vss3(d.v, l.objPosition.v, v->obj.w, v->obj.v);
                 sqDist = dot3(d.v, d.v);
                 vscale3(d.v, d.v, gglSqrtRecipx(sqDist));
             } else {
@@ -376,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 f175cda..21ef50e 100644
--- a/opengl/libagl/matrix.cpp
+++ b/opengl/libagl/matrix.cpp
@@ -55,7 +55,7 @@
 static void point2__generic(transform_t const*, vec4_t* c, vec4_t const* o);
 static void point3__generic(transform_t const*, vec4_t* c, vec4_t const* o);
 static void point4__generic(transform_t const*, vec4_t* c, vec4_t const* o);
-static void normal__generic(transform_t const*, vec4_t* c, vec4_t const* o);
+static void point4__mvui(transform_t const*, vec4_t* c, vec4_t const* o);
 
 // ----------------------------------------------------------------------------
 #if 0
@@ -209,7 +209,8 @@
 {
     flags = 0;
     ops = OP_ALL;
-    point3 = normal__generic;
+    point3 = point4__mvui;
+    point4 = point4__mvui;
 }
 
 void transform_t::dump(const char* what)
@@ -596,66 +597,19 @@
 
 void transform_state_t::update_mvui()
 {
+    GLfloat r[16];
     const GLfloat* const mv = modelview.top().elements();
-
-    /*
-    When transforming normals, we can use the upper 3x3 matrix, see:
-    http://www.opengl.org/documentation/specs/version1.1/glspec1.1/node26.html
-    */
     
-    // Also note that:
-    //      l(obj) =  tr(M).l(eye) for infinite light
-    //      l(obj) = inv(M).l(eye) for local light
-
-    const uint32_t ops = modelview.top_ops() & ~OP_TRANSLATE;
-    if (ggl_likely((!(ops & ~OP_ROTATE)) ||
-        (rescaleNormals && modelview.isRigidBody()))) {
-        // if the modelview matrix is a rigid body transformation
-        // (translation, rotation, uniform scaling), then we can bypass
-        // the inverse by transposing the matrix.
-        GLfloat rescale = 1.0f;
-        if (rescaleNormals == GL_RESCALE_NORMAL) {
-            if (!(ops & ~OP_UNIFORM_SCALE)) {
-                rescale = reciprocalf(mv[I(0,0)]);
-            } else {
-                rescale = rsqrtf(
-                        sqrf(mv[I(2,0)]) + sqrf(mv[I(2,1)]) + sqrf(mv[I(2,2)]));
-            }
-        }
-        GLfixed* const x = mvui.matrix.m;
-        for (int i=0 ; i<3 ; i++) {
-            x[I(i,0)] = gglFloatToFixed(mv[I(0,i)] * rescale);
-            x[I(i,1)] = gglFloatToFixed(mv[I(1,i)] * rescale);
-            x[I(i,2)] = gglFloatToFixed(mv[I(2,i)] * rescale);
-        }
-        mvui.picker();
-        return;
-    }
-
-    GLfloat r[3][3];
-    r[0][0] = det22(mv[I(1,1)], mv[I(2,1)], mv[I(1,2)], mv[I(2,2)]);
-    r[0][1] =ndet22(mv[I(0,1)], mv[I(2,1)], mv[I(0,2)], mv[I(2,2)]);
-    r[0][2] = det22(mv[I(0,1)], mv[I(1,1)], mv[I(0,2)], mv[I(1,2)]);
-    r[1][0] =ndet22(mv[I(1,0)], mv[I(2,0)], mv[I(1,2)], mv[I(2,2)]);
-    r[1][1] = det22(mv[I(0,0)], mv[I(2,0)], mv[I(0,2)], mv[I(2,2)]);
-    r[1][2] =ndet22(mv[I(0,0)], mv[I(1,0)], mv[I(0,2)], mv[I(1,2)]);
-    r[2][0] = det22(mv[I(1,0)], mv[I(2,0)], mv[I(1,1)], mv[I(2,1)]);
-    r[2][1] =ndet22(mv[I(0,0)], mv[I(2,0)], mv[I(0,1)], mv[I(2,1)]);
-    r[2][2] = det22(mv[I(0,0)], mv[I(1,0)], mv[I(0,1)], mv[I(1,1)]);        
-
-    GLfloat rdet;
-    if (rescaleNormals == GL_RESCALE_NORMAL) {
-        rdet = rsqrtf(sqrf(r[0][2]) + sqrf(r[1][2]) + sqrf(r[2][2]));
-    } else {
-        rdet = reciprocalf( 
-            r[0][0]*mv[I(0,0)] + r[0][1]*mv[I(1,0)] + r[0][2]*mv[I(2,0)]);
-    }
+    // TODO: we need a faster invert, especially for when the modelview
+    // is a rigid-body matrix
+    invert(r, mv);
 
     GLfixed* const x = mvui.matrix.m;
-    for (int i=0 ; i<3 ; i++) {
-        x[I(i,0)] = gglFloatToFixed(r[i][0] * rdet);
-        x[I(i,1)] = gglFloatToFixed(r[i][1] * rdet);
-        x[I(i,2)] = gglFloatToFixed(r[i][2] * rdet);
+    for (int i=0 ; i<4 ; i++) {
+        x[I(i,0)] = gglFloatToFixed(r[I(i,0)]);
+        x[I(i,1)] = gglFloatToFixed(r[I(i,1)]);
+        x[I(i,2)] = gglFloatToFixed(r[I(i,2)]);
+        x[I(i,4)] = gglFloatToFixed(r[I(i,3)]);
     }
     mvui.picker();
 }
@@ -742,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;
 }
 
 // ----------------------------------------------------------------------------
@@ -783,14 +739,19 @@
     lhs->w = mla4(rx, m[ 3], ry, m[ 7], rz, m[11], rw, m[15]);
 }
 
-void normal__generic(transform_t const* mx, vec4_t* lhs, vec4_t const* rhs) {
+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
+    // 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 = mla3(rx, m[ 0], ry, m[ 4], rz, m[ 8]); 
-    lhs->y = mla3(rx, m[ 1], ry, m[ 5], rz, m[ 9]);
-    lhs->z = mla3(rx, m[ 2], ry, m[ 6], rz, m[10]);
+    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;
 }
 
 
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/texture.cpp b/opengl/libagl/texture.cpp
index b6f534b..14a910c 100644
--- a/opengl/libagl/texture.cpp
+++ b/opengl/libagl/texture.cpp
@@ -900,7 +900,7 @@
         memcpy(textureObject->crop_rect, params, 4*sizeof(GLint));
         break;
     default:
-        ogles_error(c, GL_INVALID_ENUM);
+        texParameterx(target, pname, GLfixed(params[0]), c);
         return;
     }
 }
@@ -919,6 +919,13 @@
     texParameterx(target, pname, param, c);
 }
 
+void glTexParameteri(
+        GLenum target, GLenum pname, GLint param)
+{
+    ogles_context_t* c = ogles_context_t::get();
+    texParameterx(target, pname, GLfixed(param), c);
+}
+
 // ----------------------------------------------------------------------------
 #if 0
 #pragma mark -
diff --git a/opengl/libs/Android.mk b/opengl/libs/Android.mk
index 2ecc776..23304d5 100644
--- a/opengl/libs/Android.mk
+++ b/opengl/libs/Android.mk
@@ -23,6 +23,8 @@
     LOCAL_CFLAGS += -I$(LOCAL_PATH)/../../../../bionic/libc/private
 endif
 
+LOCAL_CFLAGS += -fvisibility=hidden
+
 include $(BUILD_SHARED_LIBRARY)
 
 
@@ -35,10 +37,9 @@
 
 LOCAL_SRC_FILES:= 	\
 	GLES_CM/gl.cpp.arm 		\
-	GLES_CM/gl_logger.cpp 	\
 #
 
-LOCAL_SHARED_LIBRARIES += libcutils libutils libui libEGL
+LOCAL_SHARED_LIBRARIES += libcutils libEGL
 LOCAL_LDLIBS := -lpthread -ldl
 LOCAL_MODULE:= libGLESv1_CM
 
@@ -50,4 +51,6 @@
     LOCAL_CFLAGS += -I$(LOCAL_PATH)/../../../../bionic/libc/private
 endif
 
+LOCAL_CFLAGS += -fvisibility=hidden
+
 include $(BUILD_SHARED_LIBRARY)
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index 0b4bcce..c6e0f50 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -14,7 +14,7 @@
  ** limitations under the License.
  */
 
-#define LOG_TAG "GLLogger"
+#define LOG_TAG "libEGL"
 
 #include <ctype.h>
 #include <string.h>
@@ -69,9 +69,9 @@
 
 struct egl_display_t : public egl_object_t<'_dpy'>
 {
-    EGLDisplay  dpys[2];
-    EGLConfig*  configs[2];
-    EGLint      numConfigs[2];
+    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;
@@ -81,7 +81,7 @@
         char const * clientApi;
         char const * extensions;
     };
-    strings_t   queryString[2];
+    strings_t   queryString[IMPL_NUM_DRIVERS_IMPLEMENTATIONS];
 };
 
 struct egl_surface_t : public egl_object_t<'_srf'>
@@ -143,6 +143,7 @@
 
 static char const * const gl_names[] = {
     #include "gl_entries.in"
+    #include "glext_entries.in"
     NULL
 };
 
@@ -156,15 +157,15 @@
 
 // ----------------------------------------------------------------------------
 
-egl_connection_t gEGLImpl[2];
+egl_connection_t gEGLImpl[IMPL_NUM_DRIVERS_IMPLEMENTATIONS];
 static egl_display_t gDisplay[NUM_DISPLAYS];
 static pthread_mutex_t gThreadLocalStorageKeyMutex = PTHREAD_MUTEX_INITIALIZER;
 static pthread_key_t gEGLThreadLocalStorageKey = -1;
 
 // ----------------------------------------------------------------------------
 
-gl_hooks_t gHooks[IMPL_NUM_IMPLEMENTATIONS];
-pthread_key_t gGLWrapperKey = -1;
+EGLAPI gl_hooks_t gHooks[IMPL_NUM_IMPLEMENTATIONS];
+EGLAPI pthread_key_t gGLWrapperKey = -1;
 
 // ----------------------------------------------------------------------------
 
@@ -272,35 +273,81 @@
 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) {
-        void** curr;
+        // 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::gl_t* gl = &hooks->gl;
-        curr = (void**)gl;
-        api = gl_names;
+
+        gl_hooks_t::egl_t* egl = &hooks->egl;
+        curr = (__eglMustCastToProperFunctionPointerType*)egl;
+        api = egl_names;
         while (*api) {
-            void* f = dlsym(dso, *api);
-            //LOGD("<%s> @ 0x%p", *api, f);
+            char const * name = *api;
+            __eglMustCastToProperFunctionPointerType f = 
+                (__eglMustCastToProperFunctionPointerType)dlsym(dso, name);
             if (f == NULL) {
-                //LOGW("<%s> not found in %s", *api, driver);
-                f = (void*)gl_unimplemented;
+                // couldn't find the entry-point, use eglGetProcAddress()
+                f = getProcAddress(name);
+                if (f == NULL) {
+                    f = (__eglMustCastToProperFunctionPointerType)0;
+                }
             }
             *curr++ = f;
             api++;
         }
-        gl_hooks_t::egl_t* egl = &hooks->egl;
-        curr = (void**)egl;
-        api = egl_names;
+
+        gl_hooks_t::gl_t* gl = &hooks->gl;
+        curr = (__eglMustCastToProperFunctionPointerType*)gl;
+        api = gl_names;
         while (*api) {
-            void* f = dlsym(dso, *api);
+            char const * name = *api;
+            __eglMustCastToProperFunctionPointerType f = 
+                (__eglMustCastToProperFunctionPointerType)dlsym(dso, name);
             if (f == NULL) {
-                //LOGW("<%s> not found in %s", *api, driver);
-                f = (void*)0;
+                // 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++;
@@ -429,18 +476,19 @@
     return (index >= NUM_DISPLAYS) ? NULL : &gDisplay[index];
 }
 
-static inline
-egl_surface_t* get_surface(EGLSurface surface)
-{
-    egl_surface_t* s = (egl_surface_t *)surface;
-    return s;
+template<typename NATIVE, typename EGL>
+static inline NATIVE* egl_to_native_cast(EGL arg) {
+    return reinterpret_cast<NATIVE*>(arg);
 }
 
 static inline
-egl_context_t* get_context(EGLContext context)
-{
-    egl_context_t* c = (egl_context_t *)context;
-    return c;
+egl_surface_t* get_surface(EGLSurface surface) {   
+    return egl_to_native_cast<egl_surface_t>(surface);
+}
+
+static inline
+egl_context_t* get_context(EGLContext context) {
+    return egl_to_native_cast<egl_context_t>(context);
 }
 
 static egl_connection_t* validate_display_config(
@@ -451,7 +499,7 @@
     if (!dp) return setError(EGL_BAD_DISPLAY, (egl_connection_t*)NULL);
 
     impl = uintptr_t(config)>>24;
-    if (uint32_t(impl) >= 2) {
+    if (uint32_t(impl) >= IMPL_NUM_DRIVERS_IMPLEMENTATIONS) {
         return setError(EGL_BAD_CONFIG, (egl_connection_t*)NULL);
     } 
     index = uintptr_t(config) & 0xFFFFFF;
@@ -491,13 +539,8 @@
     return EGL_TRUE;
 }
 
-// ----------------------------------------------------------------------------
-}; // namespace android
-// ----------------------------------------------------------------------------
 
-using namespace android;
-
-EGLDisplay eglGetDisplay(NativeDisplayType display)
+EGLDisplay egl_init_displays(NativeDisplayType display)
 {
     if (sEarlyInitState) {
         return EGL_NO_DISPLAY;
@@ -510,7 +553,7 @@
     
     EGLDisplay dpy = EGLDisplay(uintptr_t(display) + 1LU);
     egl_display_t* d = &gDisplay[index];
-        
+
     // dynamically load all our EGL implementations for that display
     // and call into the real eglGetGisplay()
     egl_connection_t* cnx = &gEGLImpl[IMPL_SOFTWARE];
@@ -573,6 +616,18 @@
     return dpy;
 }
 
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+// ----------------------------------------------------------------------------
+
+using namespace android;
+
+EGLDisplay eglGetDisplay(NativeDisplayType display)
+{
+    return egl_init_displays(display);
+}
+
 // ----------------------------------------------------------------------------
 // Initialization
 // ----------------------------------------------------------------------------
@@ -594,7 +649,7 @@
     // 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<2 ; i++) {
+    for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
         egl_connection_t* const cnx = &gEGLImpl[i];
         cnx->major = -1;
         cnx->minor = -1;
@@ -624,7 +679,7 @@
     }
 
     EGLBoolean res = EGL_FALSE;
-    for (int i=0 ; i<2 ; i++) {
+    for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso && cnx->major>=0 && cnx->minor>=0) {
             EGLint n;
@@ -663,7 +718,7 @@
         return EGL_TRUE;
         
     EGLBoolean res = EGL_FALSE;
-    for (int i=0 ; i<2 ; i++) {
+    for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso) {
             cnx->hooks->egl.eglTerminate(dp->dpys[i]);
@@ -706,7 +761,7 @@
         return EGL_TRUE;
     }
     GLint n = 0;
-    for (int j=0 ; j<2 ; j++) {
+    for (int j=0 ; j<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; j++) {
         for (int i=0 ; i<dp->numConfigs[j] && config_size ; i++) {
             *configs++ = MAKE_CONFIG(j, i);
             config_size--;
@@ -744,7 +799,7 @@
     EGLint patch_index = -1;
     GLint attr;
     size_t size = 0;
-    while ((attr=attrib_list[size])) {
+    while ((attr=attrib_list[size]) != EGL_NONE) {
         if (attr == EGL_CONFIG_ID)
             patch_index = size;
         size += 2;
@@ -794,7 +849,7 @@
         return res;
     }
 
-    for (int i=0 ; i<2 ; i++) {
+    for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso) {
             if (cnx->hooks->egl.eglChooseConfig(
@@ -997,23 +1052,25 @@
     if (!validate_display_context(dpy, ctx))
         return EGL_FALSE;    
     
+    EGLSurface impl_draw = EGL_NO_SURFACE;
+    EGLSurface impl_read = EGL_NO_SURFACE;
     egl_context_t * const c = get_context(ctx);
     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)
             return setError(EGL_BAD_MATCH, EGL_FALSE);
-        draw = d->surface;
+        impl_draw = d->surface;
     }
     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)
             return setError(EGL_BAD_MATCH, EGL_FALSE);
-        read = r->surface;
+        impl_read = r->surface;
     }
     EGLBoolean result = c->cnx->hooks->egl.eglMakeCurrent(
-            dp->dpys[c->impl], draw, read, c->context);
+            dp->dpys[c->impl], impl_draw, impl_read, c->context);
 
     if (result == EGL_TRUE) {
         setGlThreadSpecific(c->cnx->hooks);
@@ -1107,7 +1164,7 @@
 EGLint eglGetError(void)
 {
     EGLint result = EGL_SUCCESS;
-    for (int i=0 ; i<2 ; i++) {
+    for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
         EGLint err = EGL_SUCCESS;
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso)
@@ -1120,8 +1177,15 @@
     return result;
 }
 
-void (*eglGetProcAddress(const char *procname))()
+__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
 {
+    // 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;
+
     __eglMustCastToProperFunctionPointerType addr;
     addr = findProcAddress(procname, gExtentionMap, NELEM(gExtentionMap));
     if (addr) return addr;
@@ -1133,7 +1197,7 @@
     
     addr = 0;
     int slot = -1;
-    for (int i=0 ; i<2 ; i++) {
+    for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso) {
             if (cnx->hooks->egl.eglGetProcAddress) {
@@ -1266,7 +1330,7 @@
     if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
 
     EGLBoolean res = EGL_TRUE;
-    for (int i=0 ; i<2 ; i++) {
+    for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso) {
             if (cnx->hooks->egl.eglSwapInterval) {
@@ -1309,7 +1373,7 @@
 {
     // bind this API on all EGLs
     EGLBoolean res = EGL_TRUE;
-    for (int i=0 ; i<2 ; i++) {
+    for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso) {
             if (cnx->hooks->egl.eglBindAPI) {
@@ -1324,7 +1388,7 @@
 
 EGLenum eglQueryAPI(void)
 {
-    for (int i=0 ; i<2 ; i++) {
+    for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso) {
             if (cnx->hooks->egl.eglQueryAPI) {
@@ -1340,7 +1404,7 @@
 
 EGLBoolean eglReleaseThread(void)
 {
-    for (int i=0 ; i<2 ; i++) {
+    for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso) {
             if (cnx->hooks->egl.eglReleaseThread) {
diff --git a/opengl/libs/EGL/gpu.cpp b/opengl/libs/EGL/gpu.cpp
index 3f9fd63..4c902c8 100644
--- a/opengl/libs/EGL/gpu.cpp
+++ b/opengl/libs/EGL/gpu.cpp
@@ -53,7 +53,7 @@
 static Mutex                            gRegionsLock;
 static request_gpu_t                    gRegions;
 static sp<ISurfaceComposer>             gSurfaceManager;
-ISurfaceComposer*                       GLES_localSurfaceManager = 0;
+GL_API ISurfaceComposer*                GLES_localSurfaceManager = 0;
 
 extern egl_connection_t gEGLImpl[2];
 
@@ -118,6 +118,11 @@
         return 0;
     }
 
+    if (info.regs == 0) {
+        LOGD("requestGPU() failed");
+        return 0;
+    }
+
     bool failed = false;
     request_gpu_t* gpu = &gRegions;
     memset(gpu, 0, sizeof(*gpu));
diff --git a/opengl/libs/GLES_CM/gl.cpp b/opengl/libs/GLES_CM/gl.cpp
index 865cf44..384b59a 100644
--- a/opengl/libs/GLES_CM/gl.cpp
+++ b/opengl/libs/GLES_CM/gl.cpp
@@ -29,6 +29,7 @@
 #include <cutils/properties.h>
 
 #include "hooks.h"
+#include "egl_impl.h"
 
 using namespace android;
 
@@ -36,6 +37,17 @@
 // extensions for the framework
 // ----------------------------------------------------------------------------
 
+extern "C" {
+GL_API void GL_APIENTRY glColorPointerBounds(GLint size, GLenum type, GLsizei stride,
+        const GLvoid *ptr, GLsizei count);
+GL_API void GL_APIENTRY glNormalPointerBounds(GLenum type, GLsizei stride,
+        const GLvoid *pointer, GLsizei count);
+GL_API void GL_APIENTRY glTexCoordPointerBounds(GLint size, GLenum type,
+        GLsizei stride, const GLvoid *pointer, GLsizei count);
+GL_API void GL_APIENTRY glVertexPointerBounds(GLint size, GLenum type,
+        GLsizei stride, const GLvoid *pointer, GLsizei count);
+}
+
 void glColorPointerBounds(GLint size, GLenum type, GLsizei stride,
         const GLvoid *ptr, GLsizei count) {
     glColorPointer(size, type, stride, ptr);
@@ -57,13 +69,6 @@
 // Actual GL entry-points
 // ----------------------------------------------------------------------------
 
-#if GL_LOGGER
-#   include "gl_logger.h"
-#   define GL_LOGGER_IMPL(_x) _x
-#else
-#   define GL_LOGGER_IMPL(_x)
-#endif
-
 #undef API_ENTRY
 #undef CALL_GL_API
 #undef CALL_GL_API_RETURN
@@ -96,21 +101,36 @@
 
     #define CALL_GL_API(_api, ...)                                      \
         gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl; \
-        GL_LOGGER_IMPL( log_##_api(__VA_ARGS__); )                      \
         _c->_api(__VA_ARGS__)
     
     #define CALL_GL_API_RETURN(_api, ...)                               \
         gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl; \
-        GL_LOGGER_IMPL( log_##_api(__VA_ARGS__); )                      \
         return _c->_api(__VA_ARGS__)
 
 #endif
 
+
 extern "C" {
 #include "gl_api.in"
+#include "glext_api.in"
 }
 
 #undef API_ENTRY
 #undef CALL_GL_API
 #undef CALL_GL_API_RETURN
 
+
+/*
+ * These GL calls are special because they need to call into EGL to retrieve
+ * some informations before they can execute.
+ */
+
+
+void glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image)
+{
+}
+
+void glEGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
+{
+}
+
diff --git a/opengl/libs/GLES_CM/gl_api.in b/opengl/libs/GLES_CM/gl_api.in
index 9234ef2..5437d47 100644
--- a/opengl/libs/GLES_CM/gl_api.in
+++ b/opengl/libs/GLES_CM/gl_api.in
@@ -1,532 +1,285 @@
-void API_ENTRY(glActiveTexture)(GLenum texture) {
-    CALL_GL_API(glActiveTexture, texture);
-}
-
 void API_ENTRY(glAlphaFunc)(GLenum func, GLclampf ref) {
     CALL_GL_API(glAlphaFunc, func, ref);
 }
-
-void API_ENTRY(glAlphaFuncx)(GLenum func, GLclampx ref) {
-    CALL_GL_API(glAlphaFuncx, func, ref);
-}
-
-void API_ENTRY(glBindTexture)(GLenum target, GLuint texture) {
-    CALL_GL_API(glBindTexture, target, texture);
-}
-
-void API_ENTRY(glBlendFunc)(GLenum sfactor, GLenum dfactor) {
-    CALL_GL_API(glBlendFunc, sfactor, dfactor);
-}
-
-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(glClearColorx)(GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha) {
-    CALL_GL_API(glClearColorx, red, green, blue, alpha);
-}
-
 void API_ENTRY(glClearDepthf)(GLclampf depth) {
     CALL_GL_API(glClearDepthf, depth);
 }
-
-void API_ENTRY(glClearDepthx)(GLclampx depth) {
-    CALL_GL_API(glClearDepthx, depth);
-}
-
-void API_ENTRY(glClearStencil)(GLint s) {
-    CALL_GL_API(glClearStencil, s);
-}
-
-void API_ENTRY(glClientActiveTexture)(GLenum texture) {
-    CALL_GL_API(glClientActiveTexture, texture);
-}
-
-void API_ENTRY(glColor4f)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) {
-    CALL_GL_API(glColor4f, red, green, blue, alpha);
-}
-
-void API_ENTRY(glColor4x)(GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha) {
-    CALL_GL_API(glColor4x, red, green, blue, alpha);
-}
-
-void API_ENTRY(glColorMask)(GLboolean r, GLboolean g, GLboolean b, GLboolean a) {
-    CALL_GL_API(glColorMask, r, g, b, a);
-}
-
-void API_ENTRY(glColorPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr)
-{
-    CALL_GL_API(glColorPointer, size, type, stride, ptr);
-}
-
-void API_ENTRY(glCompressedTexImage2D)(GLenum target, GLint level, GLenum internalformat,
-                            GLsizei width, GLsizei height, GLint border,
-                            GLsizei imageSize, const GLvoid *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 GLvoid *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);
-}
-
-void API_ENTRY(glCullFace)(GLenum mode) {
-    CALL_GL_API(glCullFace, mode);
-}
-
-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(glDepthRangex)(GLclampx zNear, GLclampx zFar) {
-    CALL_GL_API(glDepthRangex, zNear, zFar);
-}
-
-void API_ENTRY(glDisable)(GLenum cap) {
-    CALL_GL_API(glDisable, cap);
-}
-
-void API_ENTRY(glDisableClientState)(GLenum array) {
-    CALL_GL_API(glDisableClientState, array);
-}
-
-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 GLvoid *indices) {
-    CALL_GL_API(glDrawElements, mode, count, type, indices);
-}
-
-void API_ENTRY(glEnable)(GLenum cap) {
-    CALL_GL_API(glEnable, cap);
-}
-
-void API_ENTRY(glEnableClientState)(GLenum array) {
-    CALL_GL_API(glEnableClientState, array);
-}
-
-void API_ENTRY(glFinish)(void) {
-    CALL_GL_API(glFinish);
-}
-
-void API_ENTRY(glFlush)(void) {
-    CALL_GL_API(glFlush);
-}
-
-void API_ENTRY(glFogf)(GLenum pname, GLfloat param) {
-    CALL_GL_API(glFogf, pname, param);
-}
-
-void API_ENTRY(glFogfv)(GLenum pname, const GLfloat *params) {
-    CALL_GL_API(glFogfv, pname, params);
-}
-
-void API_ENTRY(glFogx)(GLenum pname, GLfixed param) {
-    CALL_GL_API(glFogx, pname, param);
-}
-
-void API_ENTRY(glFogxv)(GLenum pname, const GLfixed *params) {
-    CALL_GL_API(glFogxv, pname, params);
-}
-
-void API_ENTRY(glFrontFace)(GLenum mode) {
-    CALL_GL_API(glFrontFace, mode);
-}
-
-void API_ENTRY(glFrustumf)(GLfloat left, GLfloat right,
-                GLfloat bottom, GLfloat top,
-                GLfloat zNear, GLfloat zFar) {
-    CALL_GL_API(glFrustumf, left, right, bottom, top, zNear, zFar);
-}
-
-void API_ENTRY(glFrustumx)(GLfixed left, GLfixed right,
-                GLfixed bottom, GLfixed top,
-                GLfixed zNear, GLfixed zFar) {
-    CALL_GL_API(glFrustumx, left, right, bottom, top, zNear, zFar);
-}
-
-void API_ENTRY(glGenTextures)(GLsizei n, GLuint *textures) {
-    CALL_GL_API(glGenTextures, n, textures);
-}
-
-GLenum API_ENTRY(glGetError)(void) {
-    CALL_GL_API_RETURN(glGetError);
-}
-
-void API_ENTRY(glGetIntegerv)(GLenum pname, GLint *params) {
-    CALL_GL_API(glGetIntegerv, pname, params);
-}
-
-const GLubyte * API_ENTRY(glGetString)(GLenum name) {
-    CALL_GL_API_RETURN(glGetString, name);
-}
-
-void API_ENTRY(glHint)(GLenum target, GLenum mode) {
-    CALL_GL_API(glHint, target, mode);
-}
-
-void API_ENTRY(glLightModelf)(GLenum pname, GLfloat param) {
-    CALL_GL_API(glLightModelf, pname, param);
-}
-
-void API_ENTRY(glLightModelfv)(GLenum pname, const GLfloat *params) {
-    CALL_GL_API(glLightModelfv, pname, params);
-}
-
-void API_ENTRY(glLightModelx)(GLenum pname, GLfixed param) {
-    CALL_GL_API(glLightModelx, pname, param);
-}
-
-void API_ENTRY(glLightModelxv)(GLenum pname, const GLfixed *params) {
-    CALL_GL_API(glLightModelxv, pname, params);
-}
-
-void API_ENTRY(glLightf)(GLenum light, GLenum pname, GLfloat param) {
-    CALL_GL_API(glLightf, light, pname, param);
-}
-
-void API_ENTRY(glLightfv)(GLenum light, GLenum pname, const GLfloat *params) {
-    CALL_GL_API(glLightfv, light, pname, params);
-}
-
-void API_ENTRY(glLightx)(GLenum light, GLenum pname, GLfixed param) {
-    CALL_GL_API(glLightx, light, pname, param);
-}
-
-void API_ENTRY(glLightxv)(GLenum light, GLenum pname, const GLfixed *params) {
-    CALL_GL_API(glLightxv, light, pname, params);
-}
-
-void API_ENTRY(glLineWidth)(GLfloat width) {
-    CALL_GL_API(glLineWidth, width);
-}
-
-void API_ENTRY(glLineWidthx)(GLfixed width) {
-    CALL_GL_API(glLineWidthx, width);
-}
-
-void API_ENTRY(glLoadIdentity)(void) {
-    CALL_GL_API(glLoadIdentity);
-}
-
-void API_ENTRY(glLoadMatrixf)(const GLfloat *m) {
-    CALL_GL_API(glLoadMatrixf, m);
-}
-
-void API_ENTRY(glLoadMatrixx)(const GLfixed *m) {
-    CALL_GL_API(glLoadMatrixx, m);
-}
-
-void API_ENTRY(glLogicOp)(GLenum opcode) {
-    CALL_GL_API(glLogicOp, opcode);
-}
-
-void API_ENTRY(glMaterialf)(GLenum face, GLenum pname, GLfloat param) {
-    CALL_GL_API(glMaterialf, face, pname, param);
-}
-
-void API_ENTRY(glMaterialfv)(GLenum face, GLenum pname, const GLfloat *params) {
-    CALL_GL_API(glMaterialfv, face, pname, params);
-}
-
-void API_ENTRY(glMaterialx)(GLenum face, GLenum pname, GLfixed param) {
-    CALL_GL_API(glMaterialx, face, pname, param);
-}
-
-void API_ENTRY(glMaterialxv)(GLenum face, GLenum pname, const GLfixed *params) {
-    CALL_GL_API(glMaterialxv, face, pname, params);
-}
-
-void API_ENTRY(glMatrixMode)(GLenum mode) {
-    CALL_GL_API(glMatrixMode, mode);
-}
-
-void API_ENTRY(glMultMatrixf)(const GLfloat *m) {
-    CALL_GL_API(glMultMatrixf, m);
-}
-
-void API_ENTRY(glMultMatrixx)(const GLfixed *m) {
-    CALL_GL_API(glMultMatrixx, m);
-}
-
-void API_ENTRY(glMultiTexCoord4f)(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q) {
-    CALL_GL_API(glMultiTexCoord4f, target, s, t, r, q);
-}
-
-void API_ENTRY(glMultiTexCoord4x)(GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q) {
-    CALL_GL_API(glMultiTexCoord4x, target, s, t, r, q);
-}
-
-void API_ENTRY(glNormal3f)(GLfloat nx, GLfloat ny, GLfloat nz) {
-    CALL_GL_API(glNormal3f, nx, ny, nz);
-}
-
-void API_ENTRY(glNormal3x)(GLfixed nx, GLfixed ny, GLfixed nz) {
-    CALL_GL_API(glNormal3x, nx, ny, nz);
-}
-
-void API_ENTRY(glNormalPointer)(GLenum type, GLsizei stride, const GLvoid *pointer) {
-    CALL_GL_API(glNormalPointer, type, stride, pointer);
-}
-
-void API_ENTRY(glOrthof)(  GLfloat left, GLfloat right,
-                GLfloat bottom, GLfloat top,
-                GLfloat zNear, GLfloat zFar) {
-    CALL_GL_API(glOrthof, left, right, bottom, top, zNear, zFar);
-}
-
-void API_ENTRY(glOrthox)(  GLfixed left, GLfixed right,
-                GLfixed bottom, GLfixed top,
-                GLfixed zNear, GLfixed zFar) {
-    CALL_GL_API(glOrthox, left, right, bottom, top, zNear, zFar);
-}
-
-void API_ENTRY(glPixelStorei)(GLenum pname, GLint param) {
-    CALL_GL_API(glPixelStorei, pname, param);
-}
-
-void API_ENTRY(glPointSize)(GLfloat size) {
-    CALL_GL_API(glPointSize, size);
-}
-
-void API_ENTRY(glPointSizex)(GLfixed size) {
-    CALL_GL_API(glPointSizex, size);
-}
-
-void API_ENTRY(glPolygonOffset)(GLfloat factor, GLfloat units) {
-    CALL_GL_API(glPolygonOffset, factor, units);
-}
-
-void API_ENTRY(glPolygonOffsetx)(GLfixed factor, GLfixed units) {
-    CALL_GL_API(glPolygonOffsetx, factor, units);
-}
-
-void API_ENTRY(glPopMatrix)(void) {
-    CALL_GL_API(glPopMatrix);
-}
-
-void API_ENTRY(glPushMatrix)(void) {
-    CALL_GL_API(glPushMatrix);
-}
-
-void API_ENTRY(glReadPixels)(  GLint x, GLint y, GLsizei width, GLsizei height,
-                    GLenum format, GLenum type, GLvoid *pixels) {
-    CALL_GL_API(glReadPixels, x, y, width, height, format, type, pixels);
-}
-
-void API_ENTRY(glRotatef)(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) {
-    CALL_GL_API(glRotatef, angle, x, y, z);
-}
-
-void API_ENTRY(glRotatex)(GLfixed angle, GLfixed x, GLfixed y, GLfixed z) {
-    CALL_GL_API(glRotatex, angle, x, y, z);
-}
-
-void API_ENTRY(glSampleCoverage)(GLclampf value, GLboolean invert) {
-    CALL_GL_API(glSampleCoverage, value, invert);
-}
-
-void API_ENTRY(glSampleCoveragex)(GLclampx value, GLboolean invert) {
-    CALL_GL_API(glSampleCoveragex, value, invert);
-}
-
-void API_ENTRY(glScalef)(GLfloat x, GLfloat y, GLfloat z) {
-    CALL_GL_API(glScalef, x, y, z);
-}
-
-void API_ENTRY(glScalex)(GLfixed x, GLfixed y, GLfixed z) {
-    CALL_GL_API(glScalex, x, y, z);
-}
-
-void API_ENTRY(glScissor)(GLint x, GLint y, GLsizei width, GLsizei height) {
-    CALL_GL_API(glScissor, x, y, width, height);
-}
-
-void API_ENTRY(glShadeModel)(GLenum mode) {
-    CALL_GL_API(glShadeModel, mode);
-}
-
-void API_ENTRY(glStencilFunc)(GLenum func, GLint ref, GLuint mask) {
-    CALL_GL_API(glStencilFunc, func, ref, mask);
-}
-
-void API_ENTRY(glStencilMask)(GLuint mask) {
-    CALL_GL_API(glStencilMask, mask);
-}
-
-void API_ENTRY(glStencilOp)(GLenum fail, GLenum zfail, GLenum zpass) {
-    CALL_GL_API(glStencilOp, fail, zfail, zpass);
-}
-
-void API_ENTRY(glTexCoordPointer)( GLint size, GLenum type,
-                        GLsizei stride, const GLvoid *pointer) {
-    CALL_GL_API(glTexCoordPointer, size, type, stride, pointer);
-}
-
-void API_ENTRY(glTexEnvf)(GLenum target, GLenum pname, GLfloat param) {
-    CALL_GL_API(glTexEnvf, target, pname, param);
-}
-
-void API_ENTRY(glTexEnvfv)(GLenum target, GLenum pname, const GLfloat *params) {
-    CALL_GL_API(glTexEnvfv, target, pname, params);
-}
-
-void API_ENTRY(glTexEnvx)(GLenum target, GLenum pname, GLfixed param) {
-    CALL_GL_API(glTexEnvx, target, pname, param);
-}
-
-void API_ENTRY(glTexEnvxv)(GLenum target, GLenum pname, const GLfixed *params) {
-    CALL_GL_API(glTexEnvxv, target, pname, params);
-}
-
-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(glTexParameterx)(GLenum target, GLenum pname, GLfixed param) {
-    CALL_GL_API(glTexParameterx, target, pname, param);
-}
-
-void API_ENTRY(glTexSubImage2D)(   GLenum target, GLint level, GLint xoffset,
-                        GLint yoffset, GLsizei width, GLsizei height,
-                        GLenum format, GLenum type, const GLvoid *pixels) {
-    CALL_GL_API(glTexSubImage2D, target, level, xoffset, yoffset,
-            width, height, format, type, pixels);
-}
-
-void API_ENTRY(glTranslatef)(GLfloat x, GLfloat y, GLfloat z) {
-    CALL_GL_API(glTranslatef, x, y, z);
-}
-
-void API_ENTRY(glTranslatex)(GLfixed x, GLfixed y, GLfixed z) {
-    CALL_GL_API(glTranslatex, x, y, z);
-}
-
-void API_ENTRY(glVertexPointer)(   GLint size, GLenum type,
-                        GLsizei stride, const GLvoid *pointer) {
-    CALL_GL_API(glVertexPointer, size, type, stride, pointer);
-}
-
-void API_ENTRY(glViewport)(GLint x, GLint y, GLsizei width, GLsizei height) {
-    CALL_GL_API(glViewport, x, y, width, height);
-}
-
-// ES 1.1
 void API_ENTRY(glClipPlanef)(GLenum plane, const GLfloat *equation) {
     CALL_GL_API(glClipPlanef, plane, equation);
 }
-void API_ENTRY(glClipPlanex)(GLenum plane, const GLfixed *equation) {
-    CALL_GL_API(glClipPlanex, plane, equation);
+void API_ENTRY(glColor4f)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) {
+    CALL_GL_API(glColor4f, red, green, blue, alpha);
 }
-void API_ENTRY(glBindBuffer)(GLenum target, GLuint buffer) {
-    CALL_GL_API(glBindBuffer, target, buffer);
+void API_ENTRY(glDepthRangef)(GLclampf zNear, GLclampf zFar) {
+    CALL_GL_API(glDepthRangef, zNear, zFar);
 }
-void API_ENTRY(glBufferData)(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) {
-    CALL_GL_API(glBufferData, target, size, data, usage);
+void API_ENTRY(glFogf)(GLenum pname, GLfloat param) {
+    CALL_GL_API(glFogf, pname, param);
 }
-void API_ENTRY(glBufferSubData)(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) {
-    CALL_GL_API(glBufferSubData, target, offset, size, data);
+void API_ENTRY(glFogfv)(GLenum pname, const GLfloat *params) {
+    CALL_GL_API(glFogfv, pname, params);
 }
-void API_ENTRY(glDeleteBuffers)(GLsizei n, const GLuint* buffers) {
-    CALL_GL_API(glDeleteBuffers, n, buffers);
-}
-void API_ENTRY(glGenBuffers)(GLsizei n, GLuint* buffers) {
-    CALL_GL_API(glGenBuffers, n, buffers);
-}
-void API_ENTRY(glGetBooleanv)(GLenum pname, GLboolean *params) {
-    CALL_GL_API(glGetBooleanv, pname, params);
-}
-void API_ENTRY(glGetFixedv)(GLenum pname, GLfixed *params) {
-    CALL_GL_API(glGetFixedv, pname, params);
-}
-void API_ENTRY(glGetFloatv)(GLenum pname, GLfloat *params) {
-    CALL_GL_API(glGetFloatv, pname, params);
-}
-void API_ENTRY(glGetPointerv)(GLenum pname, void **params) {
-    CALL_GL_API(glGetPointerv, pname, params);
-}
-void API_ENTRY(glGetBufferParameteriv)(GLenum target, GLenum pname, GLint *params) {
-    CALL_GL_API(glGetBufferParameteriv, target, pname, params);
+void API_ENTRY(glFrustumf)(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar) {
+    CALL_GL_API(glFrustumf, left, right, bottom, top, zNear, zFar);
 }
 void API_ENTRY(glGetClipPlanef)(GLenum pname, GLfloat eqn[4]) {
     CALL_GL_API(glGetClipPlanef, pname, eqn);
 }
-void API_ENTRY(glGetClipPlanex)(GLenum pname, GLfixed eqn[4]) {
-    CALL_GL_API(glGetClipPlanex, pname, eqn);
-}
-void API_ENTRY(glGetLightxv)(GLenum light, GLenum pname, GLfixed *params) {
-    CALL_GL_API(glGetLightxv, light, pname, params);
+void API_ENTRY(glGetFloatv)(GLenum pname, GLfloat *params) {
+    CALL_GL_API(glGetFloatv, pname, params);
 }
 void API_ENTRY(glGetLightfv)(GLenum light, GLenum pname, GLfloat *params) {
     CALL_GL_API(glGetLightfv, light, pname, params);
 }
-void API_ENTRY(glGetMaterialxv)(GLenum face, GLenum pname, GLfixed *params) {
-    CALL_GL_API(glGetMaterialxv, face, pname, params);
-}
 void API_ENTRY(glGetMaterialfv)(GLenum face, GLenum pname, GLfloat *params) {
     CALL_GL_API(glGetMaterialfv, face, pname, params);
 }
 void API_ENTRY(glGetTexEnvfv)(GLenum env, GLenum pname, GLfloat *params) {
     CALL_GL_API(glGetTexEnvfv, env, pname, params);
 }
+void API_ENTRY(glGetTexParameterfv)(GLenum target, GLenum pname, GLfloat *params) {
+    CALL_GL_API(glGetTexParameterfv, target, pname, params);
+}
+void API_ENTRY(glLightModelf)(GLenum pname, GLfloat param) {
+    CALL_GL_API(glLightModelf, pname, param);
+}
+void API_ENTRY(glLightModelfv)(GLenum pname, const GLfloat *params) {
+    CALL_GL_API(glLightModelfv, pname, params);
+}
+void API_ENTRY(glLightf)(GLenum light, GLenum pname, GLfloat param) {
+    CALL_GL_API(glLightf, light, pname, param);
+}
+void API_ENTRY(glLightfv)(GLenum light, GLenum pname, const GLfloat *params) {
+    CALL_GL_API(glLightfv, light, pname, params);
+}
+void API_ENTRY(glLineWidth)(GLfloat width) {
+    CALL_GL_API(glLineWidth, width);
+}
+void API_ENTRY(glLoadMatrixf)(const GLfloat *m) {
+    CALL_GL_API(glLoadMatrixf, m);
+}
+void API_ENTRY(glMaterialf)(GLenum face, GLenum pname, GLfloat param) {
+    CALL_GL_API(glMaterialf, face, pname, param);
+}
+void API_ENTRY(glMaterialfv)(GLenum face, GLenum pname, const GLfloat *params) {
+    CALL_GL_API(glMaterialfv, face, pname, params);
+}
+void API_ENTRY(glMultMatrixf)(const GLfloat *m) {
+    CALL_GL_API(glMultMatrixf, m);
+}
+void API_ENTRY(glMultiTexCoord4f)(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q) {
+    CALL_GL_API(glMultiTexCoord4f, target, s, t, r, q);
+}
+void API_ENTRY(glNormal3f)(GLfloat nx, GLfloat ny, GLfloat nz) {
+    CALL_GL_API(glNormal3f, nx, ny, nz);
+}
+void API_ENTRY(glOrthof)(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar) {
+    CALL_GL_API(glOrthof, left, right, bottom, top, zNear, zFar);
+}
+void API_ENTRY(glPointParameterf)(GLenum pname, GLfloat param) {
+    CALL_GL_API(glPointParameterf, pname, param);
+}
+void API_ENTRY(glPointParameterfv)(GLenum pname, const GLfloat *params) {
+    CALL_GL_API(glPointParameterfv, pname, params);
+}
+void API_ENTRY(glPointSize)(GLfloat size) {
+    CALL_GL_API(glPointSize, size);
+}
+void API_ENTRY(glPolygonOffset)(GLfloat factor, GLfloat units) {
+    CALL_GL_API(glPolygonOffset, factor, units);
+}
+void API_ENTRY(glRotatef)(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) {
+    CALL_GL_API(glRotatef, angle, x, y, z);
+}
+void API_ENTRY(glScalef)(GLfloat x, GLfloat y, GLfloat z) {
+    CALL_GL_API(glScalef, x, y, z);
+}
+void API_ENTRY(glTexEnvf)(GLenum target, GLenum pname, GLfloat param) {
+    CALL_GL_API(glTexEnvf, target, pname, param);
+}
+void API_ENTRY(glTexEnvfv)(GLenum target, GLenum pname, const GLfloat *params) {
+    CALL_GL_API(glTexEnvfv, target, pname, params);
+}
+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(glTranslatef)(GLfloat x, GLfloat y, GLfloat z) {
+    CALL_GL_API(glTranslatef, x, y, z);
+}
+void API_ENTRY(glActiveTexture)(GLenum texture) {
+    CALL_GL_API(glActiveTexture, texture);
+}
+void API_ENTRY(glAlphaFuncx)(GLenum func, GLclampx ref) {
+    CALL_GL_API(glAlphaFuncx, func, ref);
+}
+void API_ENTRY(glBindBuffer)(GLenum target, GLuint buffer) {
+    CALL_GL_API(glBindBuffer, target, buffer);
+}
+void API_ENTRY(glBindTexture)(GLenum target, GLuint texture) {
+    CALL_GL_API(glBindTexture, target, texture);
+}
+void API_ENTRY(glBlendFunc)(GLenum sfactor, GLenum dfactor) {
+    CALL_GL_API(glBlendFunc, sfactor, dfactor);
+}
+void API_ENTRY(glBufferData)(GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage) {
+    CALL_GL_API(glBufferData, target, size, data, usage);
+}
+void API_ENTRY(glBufferSubData)(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data) {
+    CALL_GL_API(glBufferSubData, target, offset, size, data);
+}
+void API_ENTRY(glClear)(GLbitfield mask) {
+    CALL_GL_API(glClear, mask);
+}
+void API_ENTRY(glClearColorx)(GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha) {
+    CALL_GL_API(glClearColorx, red, green, blue, alpha);
+}
+void API_ENTRY(glClearDepthx)(GLclampx depth) {
+    CALL_GL_API(glClearDepthx, depth);
+}
+void API_ENTRY(glClearStencil)(GLint s) {
+    CALL_GL_API(glClearStencil, s);
+}
+void API_ENTRY(glClientActiveTexture)(GLenum texture) {
+    CALL_GL_API(glClientActiveTexture, texture);
+}
+void API_ENTRY(glClipPlanex)(GLenum plane, const GLfixed *equation) {
+    CALL_GL_API(glClipPlanex, plane, equation);
+}
+void API_ENTRY(glColor4ub)(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha) {
+    CALL_GL_API(glColor4ub, red, green, blue, alpha);
+}
+void API_ENTRY(glColor4x)(GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha) {
+    CALL_GL_API(glColor4x, red, green, blue, alpha);
+}
+void API_ENTRY(glColorMask)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {
+    CALL_GL_API(glColorMask, red, green, blue, alpha);
+}
+void API_ENTRY(glColorPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) {
+    CALL_GL_API(glColorPointer, size, type, stride, pointer);
+}
+void API_ENTRY(glCompressedTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *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 GLvoid *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);
+}
+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(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(glDepthRangex)(GLclampx zNear, GLclampx zFar) {
+    CALL_GL_API(glDepthRangex, zNear, zFar);
+}
+void API_ENTRY(glDisable)(GLenum cap) {
+    CALL_GL_API(glDisable, cap);
+}
+void API_ENTRY(glDisableClientState)(GLenum array) {
+    CALL_GL_API(glDisableClientState, array);
+}
+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 GLvoid *indices) {
+    CALL_GL_API(glDrawElements, mode, count, type, indices);
+}
+void API_ENTRY(glEnable)(GLenum cap) {
+    CALL_GL_API(glEnable, cap);
+}
+void API_ENTRY(glEnableClientState)(GLenum array) {
+    CALL_GL_API(glEnableClientState, array);
+}
+void API_ENTRY(glFinish)(void) {
+    CALL_GL_API(glFinish);
+}
+void API_ENTRY(glFlush)(void) {
+    CALL_GL_API(glFlush);
+}
+void API_ENTRY(glFogx)(GLenum pname, GLfixed param) {
+    CALL_GL_API(glFogx, pname, param);
+}
+void API_ENTRY(glFogxv)(GLenum pname, const GLfixed *params) {
+    CALL_GL_API(glFogxv, pname, params);
+}
+void API_ENTRY(glFrontFace)(GLenum mode) {
+    CALL_GL_API(glFrontFace, mode);
+}
+void API_ENTRY(glFrustumx)(GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar) {
+    CALL_GL_API(glFrustumx, left, right, bottom, top, zNear, zFar);
+}
+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);
+}
+void API_ENTRY(glGetClipPlanex)(GLenum pname, GLfixed eqn[4]) {
+    CALL_GL_API(glGetClipPlanex, pname, eqn);
+}
+void API_ENTRY(glGenBuffers)(GLsizei n, GLuint *buffers) {
+    CALL_GL_API(glGenBuffers, n, buffers);
+}
+void API_ENTRY(glGenTextures)(GLsizei n, GLuint *textures) {
+    CALL_GL_API(glGenTextures, n, textures);
+}
+GLenum API_ENTRY(glGetError)(void) {
+    CALL_GL_API_RETURN(glGetError);
+}
+void API_ENTRY(glGetFixedv)(GLenum pname, GLfixed *params) {
+    CALL_GL_API(glGetFixedv, pname, params);
+}
+void API_ENTRY(glGetIntegerv)(GLenum pname, GLint *params) {
+    CALL_GL_API(glGetIntegerv, pname, params);
+}
+void API_ENTRY(glGetLightxv)(GLenum light, GLenum pname, GLfixed *params) {
+    CALL_GL_API(glGetLightxv, light, pname, params);
+}
+void API_ENTRY(glGetMaterialxv)(GLenum face, GLenum pname, GLfixed *params) {
+    CALL_GL_API(glGetMaterialxv, face, pname, params);
+}
+void API_ENTRY(glGetPointerv)(GLenum pname, void **params) {
+    CALL_GL_API(glGetPointerv, pname, params);
+}
+const GLubyte * API_ENTRY(glGetString)(GLenum name) {
+    CALL_GL_API_RETURN(glGetString, name);
+}
 void API_ENTRY(glGetTexEnviv)(GLenum env, GLenum pname, GLint *params) {
     CALL_GL_API(glGetTexEnviv, env, pname, params);
 }
 void API_ENTRY(glGetTexEnvxv)(GLenum env, GLenum pname, GLfixed *params) {
     CALL_GL_API(glGetTexEnvxv, env, pname, params);
 }
-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(glGetTexParameterxv)(GLenum target, GLenum pname, GLfixed *params) {
     CALL_GL_API(glGetTexParameterxv, target, pname, params);
 }
+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);
 }
@@ -536,11 +289,56 @@
 GLboolean API_ENTRY(glIsTexture)(GLuint texture) {
     CALL_GL_API_RETURN(glIsTexture, texture);
 }
-void API_ENTRY(glPointParameterf)(GLenum pname, GLfloat param) {
-    CALL_GL_API(glPointParameterf, pname, param);
+void API_ENTRY(glLightModelx)(GLenum pname, GLfixed param) {
+    CALL_GL_API(glLightModelx, pname, param);
 }
-void API_ENTRY(glPointParameterfv)(GLenum pname, const GLfloat *params) {
-    CALL_GL_API(glPointParameterfv, pname, params);
+void API_ENTRY(glLightModelxv)(GLenum pname, const GLfixed *params) {
+    CALL_GL_API(glLightModelxv, pname, params);
+}
+void API_ENTRY(glLightx)(GLenum light, GLenum pname, GLfixed param) {
+    CALL_GL_API(glLightx, light, pname, param);
+}
+void API_ENTRY(glLightxv)(GLenum light, GLenum pname, const GLfixed *params) {
+    CALL_GL_API(glLightxv, light, pname, params);
+}
+void API_ENTRY(glLineWidthx)(GLfixed width) {
+    CALL_GL_API(glLineWidthx, width);
+}
+void API_ENTRY(glLoadIdentity)(void) {
+    CALL_GL_API(glLoadIdentity);
+}
+void API_ENTRY(glLoadMatrixx)(const GLfixed *m) {
+    CALL_GL_API(glLoadMatrixx, m);
+}
+void API_ENTRY(glLogicOp)(GLenum opcode) {
+    CALL_GL_API(glLogicOp, opcode);
+}
+void API_ENTRY(glMaterialx)(GLenum face, GLenum pname, GLfixed param) {
+    CALL_GL_API(glMaterialx, face, pname, param);
+}
+void API_ENTRY(glMaterialxv)(GLenum face, GLenum pname, const GLfixed *params) {
+    CALL_GL_API(glMaterialxv, face, pname, params);
+}
+void API_ENTRY(glMatrixMode)(GLenum mode) {
+    CALL_GL_API(glMatrixMode, mode);
+}
+void API_ENTRY(glMultMatrixx)(const GLfixed *m) {
+    CALL_GL_API(glMultMatrixx, m);
+}
+void API_ENTRY(glMultiTexCoord4x)(GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q) {
+    CALL_GL_API(glMultiTexCoord4x, target, s, t, r, q);
+}
+void API_ENTRY(glNormal3x)(GLfixed nx, GLfixed ny, GLfixed nz) {
+    CALL_GL_API(glNormal3x, nx, ny, nz);
+}
+void API_ENTRY(glNormalPointer)(GLenum type, GLsizei stride, const GLvoid *pointer) {
+    CALL_GL_API(glNormalPointer, type, stride, pointer);
+}
+void API_ENTRY(glOrthox)(GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar) {
+    CALL_GL_API(glOrthox, left, right, bottom, top, zNear, zFar);
+}
+void API_ENTRY(glPixelStorei)(GLenum pname, GLint param) {
+    CALL_GL_API(glPixelStorei, pname, param);
 }
 void API_ENTRY(glPointParameterx)(GLenum pname, GLfixed param) {
     CALL_GL_API(glPointParameterx, pname, param);
@@ -548,59 +346,90 @@
 void API_ENTRY(glPointParameterxv)(GLenum pname, const GLfixed *params) {
     CALL_GL_API(glPointParameterxv, pname, params);
 }
-void API_ENTRY(glColor4ub)(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha) {
-    CALL_GL_API(glColor4ub, red, green, blue, alpha);
+void API_ENTRY(glPointSizex)(GLfixed size) {
+    CALL_GL_API(glPointSizex, size);
+}
+void API_ENTRY(glPolygonOffsetx)(GLfixed factor, GLfixed units) {
+    CALL_GL_API(glPolygonOffsetx, factor, units);
+}
+void API_ENTRY(glPopMatrix)(void) {
+    CALL_GL_API(glPopMatrix);
+}
+void API_ENTRY(glPushMatrix)(void) {
+    CALL_GL_API(glPushMatrix);
+}
+void API_ENTRY(glReadPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels) {
+    CALL_GL_API(glReadPixels, x, y, width, height, format, type, pixels);
+}
+void API_ENTRY(glRotatex)(GLfixed angle, GLfixed x, GLfixed y, GLfixed z) {
+    CALL_GL_API(glRotatex, angle, x, y, z);
+}
+void API_ENTRY(glSampleCoverage)(GLclampf value, GLboolean invert) {
+    CALL_GL_API(glSampleCoverage, value, invert);
+}
+void API_ENTRY(glSampleCoveragex)(GLclampx value, GLboolean invert) {
+    CALL_GL_API(glSampleCoveragex, value, invert);
+}
+void API_ENTRY(glScalex)(GLfixed x, GLfixed y, GLfixed z) {
+    CALL_GL_API(glScalex, x, y, z);
+}
+void API_ENTRY(glScissor)(GLint x, GLint y, GLsizei width, GLsizei height) {
+    CALL_GL_API(glScissor, x, y, width, height);
+}
+void API_ENTRY(glShadeModel)(GLenum mode) {
+    CALL_GL_API(glShadeModel, mode);
+}
+void API_ENTRY(glStencilFunc)(GLenum func, GLint ref, GLuint mask) {
+    CALL_GL_API(glStencilFunc, func, ref, mask);
+}
+void API_ENTRY(glStencilMask)(GLuint mask) {
+    CALL_GL_API(glStencilMask, mask);
+}
+void API_ENTRY(glStencilOp)(GLenum fail, GLenum zfail, GLenum zpass) {
+    CALL_GL_API(glStencilOp, fail, zfail, zpass);
+}
+void API_ENTRY(glTexCoordPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) {
+    CALL_GL_API(glTexCoordPointer, size, type, stride, pointer);
 }
 void API_ENTRY(glTexEnvi)(GLenum target, GLenum pname, GLint param) {
     CALL_GL_API(glTexEnvi, target, pname, param);
 }
+void API_ENTRY(glTexEnvx)(GLenum target, GLenum pname, GLfixed param) {
+    CALL_GL_API(glTexEnvx, target, pname, param);
+}
 void API_ENTRY(glTexEnviv)(GLenum target, GLenum pname, const GLint *params) {
     CALL_GL_API(glTexEnviv, target, pname, params);
 }
-
-void API_ENTRY(glTexParameterfv)(GLenum target, GLenum pname, const GLfloat *params) {
-    CALL_GL_API(glTexParameterfv, target, pname, params);
+void API_ENTRY(glTexEnvxv)(GLenum target, GLenum pname, const GLfixed *params) {
+    CALL_GL_API(glTexEnvxv, target, pname, params);
 }
-
-void API_ENTRY(glTexParameteriv)(GLenum target, GLenum pname, const GLint *params) {
-    CALL_GL_API(glTexParameteriv, target, pname, params);
+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(glTexParameteri)(GLenum target, GLenum pname, GLint param) {
     CALL_GL_API(glTexParameteri, target, pname, param);
 }
+void API_ENTRY(glTexParameterx)(GLenum target, GLenum pname, GLfixed param) {
+    CALL_GL_API(glTexParameterx, target, pname, param);
+}
+void API_ENTRY(glTexParameteriv)(GLenum target, GLenum pname, const GLint *params) {
+    CALL_GL_API(glTexParameteriv, target, pname, params);
+}
 void API_ENTRY(glTexParameterxv)(GLenum target, GLenum pname, const GLfixed *params) {
     CALL_GL_API(glTexParameterxv, target, pname, params);
 }
+void API_ENTRY(glTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels) {
+    CALL_GL_API(glTexSubImage2D, target, level, xoffset, yoffset, width, height, format, type, pixels);
+}
+void API_ENTRY(glTranslatex)(GLfixed x, GLfixed y, GLfixed z) {
+    CALL_GL_API(glTranslatex, x, y, z);
+}
+void API_ENTRY(glVertexPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) {
+    CALL_GL_API(glVertexPointer, size, type, stride, pointer);
+}
+void API_ENTRY(glViewport)(GLint x, GLint y, GLsizei width, GLsizei height) {
+    CALL_GL_API(glViewport, x, y, width, height);
+}
 void API_ENTRY(glPointSizePointerOES)(GLenum type, GLsizei stride, const GLvoid *pointer) {
     CALL_GL_API(glPointSizePointerOES, type, stride, pointer);
 }
-
-// Extensions
-void API_ENTRY(glDrawTexsOES)(GLshort x , GLshort y, GLshort z, GLshort w, GLshort h) {
-    CALL_GL_API(glDrawTexsOES, x, y, z, w, h);
-}
-void API_ENTRY(glDrawTexiOES)(GLint x, GLint y, GLint z, GLint w, GLint h) {
-    CALL_GL_API(glDrawTexiOES, x, y, z, w, h);
-}
-void API_ENTRY(glDrawTexfOES)(GLfloat x, GLfloat y, GLfloat z, GLfloat w, GLfloat h) {
-    CALL_GL_API(glDrawTexfOES, x, y, z, w, h);
-}
-void API_ENTRY(glDrawTexxOES)(GLfixed x, GLfixed y, GLfixed z, GLfixed w, GLfixed h) {
-    CALL_GL_API(glDrawTexxOES, x, y, z, w, h);
-}
-void API_ENTRY(glDrawTexsvOES)(const GLshort* coords) {
-    CALL_GL_API(glDrawTexsvOES, coords);
-}
-void API_ENTRY(glDrawTexivOES)(const GLint* coords) {
-    CALL_GL_API(glDrawTexivOES, coords);
-}
-void API_ENTRY(glDrawTexfvOES)(const GLfloat* coords) {
-    CALL_GL_API(glDrawTexfvOES, coords);
-}
-void API_ENTRY(glDrawTexxvOES)(const GLfixed* coords) {
-    CALL_GL_API(glDrawTexxvOES, coords);
-}
-GLbitfield API_ENTRY(glQueryMatrixxOES)(GLfixed* mantissa, GLint* exponent) {
-    CALL_GL_API_RETURN(glQueryMatrixxOES, mantissa, exponent);
-}
diff --git a/opengl/libs/GLES_CM/gl_logger.cpp b/opengl/libs/GLES_CM/gl_logger.cpp
deleted file mode 100644
index 27be5c9..0000000
--- a/opengl/libs/GLES_CM/gl_logger.cpp
+++ /dev/null
@@ -1,1060 +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 "GLLogger"
-
-#include <ctype.h>
-#include <string.h>
-#include <errno.h>
-#include <dlfcn.h>
-
-#include <sys/ioctl.h>
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-#include <GLES/gl.h>
-#include <GLES/glext.h>
-
-#include <cutils/log.h>
-#include <cutils/atomic.h>
-#include <cutils/properties.h>
-
-#include <utils/String8.h>
-
-#include "gl_logger.h"
-
-#undef NELEM
-#define NELEM(x) (sizeof(x)/sizeof(*(x)))
-
-// ----------------------------------------------------------------------------
-namespace android {
-// ----------------------------------------------------------------------------
-
-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) {
-           first = mid + 1;
-       } else if (key < sortedArray[mid].key) {
-           last = mid - 1;
-       } else {
-           return mid;
-       }
-   }
-   return -1;
-}
-
-struct pair_t {
-    const char* name;
-    int         key;
-};
-
-static const pair_t gEnumMap[] = {
-    #define GLENUM(NAME, VALUE) { #NAME, VALUE },
-    #include "gl_enums.in"
-    #undef GLENUM
-};
-
-// ----------------------------------------------------------------------------
-
-template<typename TYPE>
-class GLLogValue {
-public:
-    GLLogValue(TYPE value) : mValue(value) { }
-    const TYPE& getValue() const { return mValue; }
-    String8 toString() const {
-        return convertToString(mValue);
-    }
-private:
-    const TYPE& mValue;
-    String8 convertToString(unsigned int v) const {
-        char buf[16];
-        snprintf(buf, 16, "%u", v);
-        return String8(buf);
-    }
-    String8 convertToString(unsigned long v) const {
-        char buf[16];
-        snprintf(buf, 16, "%lu", v);
-        return String8(buf);
-    }
-    String8 convertToString(int v) const {
-        char buf[16];
-        snprintf(buf, 16, "%d", v);
-        return String8(buf);
-    }
-    String8 convertToString(long v) const {
-        char buf[16];
-        snprintf(buf, 16, "%ld", v);
-        return String8(buf);
-    }
-    String8 convertToString(float v) const {
-        char buf[16];
-        snprintf(buf, 16, "%f", v);
-        return String8(buf);
-    }
-    String8 convertToString(void const* v) const {
-        char buf[16];
-        snprintf(buf, 16, "%p", v);
-        return String8(buf);
-    }
-};
-
-class GLLogEnum : public GLLogValue<GLenum> {
-public:
-    GLLogEnum(GLenum v) : GLLogValue<GLenum>(v) { }
-    String8 toString() const {
-        GLenum v = getValue();
-        int i = binarySearch<pair_t>(gEnumMap, 0, NELEM(gEnumMap)-1, v);
-        if (i >= 0) {
-            return String8(gEnumMap[i].name);
-        } else {
-            char buf[16];
-            snprintf(buf, 16, "0x%04x", v);
-            return String8(buf);
-        }
-    }
-};
-
-class GLLogClearBitfield : public GLLogValue<GLbitfield> {
-public:
-    GLLogClearBitfield(GLbitfield v) : GLLogValue<GLbitfield>(v) { }
-    String8 toString() const {
-        char buf[16];
-        snprintf(buf, 16, "0x%08x", getValue());
-        return String8(buf);
-    }
-};
-
-class GLLogBool : public GLLogValue<GLboolean> {
-public:
-    GLLogBool(GLboolean v) : GLLogValue<GLboolean>(v) { }
-    String8 toString() const {
-        GLboolean v = getValue();
-        if (v == GL_TRUE)   return String8("GL_TRUE");
-        if (v == GL_FALSE)  return String8("GL_FALSE");
-        return GLLogValue<GLboolean>::toString();
-    }
-};
-
-class GLLogFixed : public GLLogValue<GLfixed> {
-public:
-    GLLogFixed(GLfixed v) : GLLogValue<GLfixed>(v) { }
-    String8 toString() const {
-        char buf[16];
-        snprintf(buf, 16, "0x%08x", getValue());
-        return String8(buf);
-    }
-};
-
-
-template <typename TYPE>
-class GLLogBuffer : public GLLogValue<TYPE *> {
-public:
-    GLLogBuffer(TYPE* buffer, size_t count = -1)
-        : GLLogValue<TYPE*>(buffer)
-    { // output buffer
-    }
-    GLLogBuffer(TYPE const* buffer, size_t count = -1)
-    : GLLogValue<TYPE*>(const_cast<TYPE*>(buffer))
-    { // input buffer
-    }
-};
-
-class GLLog
-{
-public:
-    GLLog(const char* name) : mNumParams(0) {
-        mString.append(name);
-        mString.append("(");
-    }
-
-    ~GLLog() {
-        LOGD("%s);", mString.string());
-    }
-
-    GLLog& operator << (unsigned char v) {
-        return *this << GLLogValue<unsigned int>(v);
-    }
-    GLLog& operator << (short v) {
-        return *this << GLLogValue<unsigned int>(v);
-    }
-    GLLog& operator << (unsigned int v) {
-        return *this << GLLogValue<unsigned int>(v);
-    }
-    GLLog& operator << (int v) {
-        return *this << GLLogValue<int>(v);
-    }
-    GLLog& operator << (long v) {
-        return *this << GLLogValue<long>(v);
-    }
-    GLLog& operator << (unsigned long v) {
-        return *this << GLLogValue<unsigned long>(v);
-    }
-    GLLog& operator << (float v) {
-        return *this << GLLogValue<float>(v);
-    }
-    GLLog& operator << (const void* v) {
-        return *this << GLLogValue<const void* >(v);
-    }
-
-    template <typename TYPE>
-    GLLog& operator << (const TYPE& rhs) {
-        if (mNumParams > 0)
-            mString.append(", ");
-        mString.append(rhs.toString());
-        mNumParams++;
-        return *this;
-    }
-
-    const String8& string() const { return mString; }
-private:
-    GLLog(const GLLog&);
-
-    String8 mString;
-    int mNumParams;
-};
-
-#define API_ENTRY(api)                      log_##api
-#define CALL_GL_API(_x, ...)
-#define CALL_GL_API_RETURN(_x, ...)         return(0);
-
-void API_ENTRY(glActiveTexture)(GLenum texture) {
-    CALL_GL_API(glActiveTexture, texture);
-    GLLog("glActiveTexture") << GLLogEnum(texture);
-}
-
-void API_ENTRY(glAlphaFunc)(GLenum func, GLclampf ref) {
-    CALL_GL_API(glAlphaFunc, func, ref);
-    GLLog("glAlphaFunc") << GLLogEnum(func) << ref;
-}
-
-void API_ENTRY(glAlphaFuncx)(GLenum func, GLclampx ref) {
-    CALL_GL_API(glAlphaFuncx, func, ref);
-    GLLog("glAlphaFuncx") << GLLogEnum(func) << GLLogFixed(ref);
-}
-
-void API_ENTRY(glBindTexture)(GLenum target, GLuint texture) {
-    CALL_GL_API(glBindTexture, target, texture);
-    GLLog("glBindTexture") << GLLogEnum(target) << texture;
-}
-
-void API_ENTRY(glBlendFunc)(GLenum sfactor, GLenum dfactor) {
-    CALL_GL_API(glBlendFunc, sfactor, dfactor);
-    GLLog("glBlendFunc") << GLLogEnum(sfactor) << GLLogEnum(dfactor);
-}
-
-void API_ENTRY(glClear)(GLbitfield mask) {
-    CALL_GL_API(glClear, mask);
-    GLLog("glClear") << GLLogClearBitfield(mask);
-}
-
-void API_ENTRY(glClearColor)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {
-    CALL_GL_API(glClearColor, red, green, blue, alpha);
-    GLLog("glClearColor") << red << green << blue << alpha;
-}
-
-void API_ENTRY(glClearColorx)(GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha) {
-    CALL_GL_API(glClearColorx, red, green, blue, alpha);
-    GLLog("glClearColorx") << GLLogFixed(red) << GLLogFixed(green) << GLLogFixed(blue) << GLLogFixed(alpha);
-}
-
-void API_ENTRY(glClearDepthf)(GLclampf depth) {
-    CALL_GL_API(glClearDepthf, depth);
-    GLLog("glClearDepthf") << depth;
-}
-
-void API_ENTRY(glClearDepthx)(GLclampx depth) {
-    CALL_GL_API(glClearDepthx, depth);
-    GLLog("glClearDepthx") << GLLogFixed(depth);
-}
-
-void API_ENTRY(glClearStencil)(GLint s) {
-    CALL_GL_API(glClearStencil, s);
-    GLLog("glClearStencil") << s;
-}
-
-void API_ENTRY(glClientActiveTexture)(GLenum texture) {
-    CALL_GL_API(glClientActiveTexture, texture);
-    GLLog("glClientActiveTexture") << GLLogEnum(texture);
-}
-
-void API_ENTRY(glColor4f)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) {
-    CALL_GL_API(glColor4f, red, green, blue, alpha);
-    GLLog("glColor4f") << red << green << blue << alpha;
-}
-
-void API_ENTRY(glColor4x)(GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha) {
-    CALL_GL_API(glColor4x, red, green, blue, alpha);
-    GLLog("glColor4x") << GLLogFixed(red) << GLLogFixed(green) << GLLogFixed(blue) << GLLogFixed(alpha);
-}
-
-void API_ENTRY(glColorMask)(GLboolean r, GLboolean g, GLboolean b, GLboolean a) {
-    CALL_GL_API(glColorMask, r, g, b, a);
-    GLLog("glColorMask") << GLLogBool(r) << GLLogBool(g) << GLLogBool(b) << GLLogBool(a);
-}
-
-void API_ENTRY(glColorPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr)
-{
-    CALL_GL_API(glColorPointer, size, type, stride, ptr);
-    GLLog("glColorPointer") << size << GLLogEnum(type) << stride << ptr;
-}
-
-void API_ENTRY(glCompressedTexImage2D)(GLenum target, GLint level, GLenum internalformat,
-                            GLsizei width, GLsizei height, GLint border,
-                            GLsizei imageSize, const GLvoid *data) {
-    CALL_GL_API(glCompressedTexImage2D, target, level, internalformat,
-            width, height, border, imageSize, data);
-    GLLog("glCompressedTexImage2D")
-                << GLLogEnum(target) << level << GLLogEnum(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 GLvoid *data) {
-    CALL_GL_API(glCompressedTexSubImage2D, target, level, xoffset, yoffset,
-            width, height, format, imageSize, data);
-    GLLog("glCompressedTexSubImage2D")
-            << GLLogEnum(target) << level << xoffset << yoffset
-            << width << height << GLLogEnum(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);
-    GLLog("glCopyTexImage2D")
-            << GLLogEnum(target) << level << GLLogEnum(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);
-    GLLog("glCopyTexSubImage2D")
-            << GLLogEnum(target) << level << xoffset << yoffset
-            << x << y << width << height;
-}
-
-void API_ENTRY(glCullFace)(GLenum mode) {
-    CALL_GL_API(glCullFace, mode);
-    GLLog("glCullFace") << GLLogEnum(mode);
-}
-
-void API_ENTRY(glDeleteTextures)(GLsizei n, const GLuint *textures) {
-    CALL_GL_API(glDeleteTextures, n, textures);
-    GLLog("glDeleteTextures") << n << GLLogBuffer<GLuint>(textures, n);
-}
-
-void API_ENTRY(glDepthFunc)(GLenum func) {
-    CALL_GL_API(glDepthFunc, func);
-    GLLog("glDepthFunc") << GLLogEnum(func);
-}
-
-void API_ENTRY(glDepthMask)(GLboolean flag) {
-    CALL_GL_API(glDepthMask, flag);
-    GLLog("glDepthMask") << GLLogBool(flag);
-}
-
-void API_ENTRY(glDepthRangef)(GLclampf zNear, GLclampf zFar) {
-    CALL_GL_API(glDepthRangef, zNear, zFar);
-    GLLog("glDepthRangef") << zNear << zFar;
-}
-
-void API_ENTRY(glDepthRangex)(GLclampx zNear, GLclampx zFar) {
-    CALL_GL_API(glDepthRangex, zNear, zFar);
-    GLLog("glDepthRangex") << GLLogFixed(zNear) << GLLogFixed(zFar);
-}
-
-void API_ENTRY(glDisable)(GLenum cap) {
-    CALL_GL_API(glDisable, cap);
-    GLLog("glDisable") << GLLogEnum(cap);
-}
-
-void API_ENTRY(glDisableClientState)(GLenum array) {
-    CALL_GL_API(glDisableClientState, array);
-    GLLog("glDisableClientState") << GLLogEnum(array);
-}
-
-void API_ENTRY(glDrawArrays)(GLenum mode, GLint first, GLsizei count) {
-    CALL_GL_API(glDrawArrays, mode, first, count);
-    GLLog("glDrawArrays") << GLLogEnum(mode) << first << count;
-}
-
-void API_ENTRY(glDrawElements)(GLenum mode, GLsizei count,
-                    GLenum type, const GLvoid *indices) {
-    CALL_GL_API(glDrawElements, mode, count, type, indices);
-    GLLog log("glDrawElements");
-    log << GLLogEnum(mode) << count << GLLogEnum(type);
-    if (type == GL_UNSIGNED_BYTE) {
-        log << GLLogBuffer<GLubyte>(static_cast<const GLubyte*>(indices), count);
-    } else {
-        log << GLLogBuffer<GLushort>(static_cast<const GLushort*>(indices), count);
-    }
-    log;
-}
-
-void API_ENTRY(glEnable)(GLenum cap) {
-    CALL_GL_API(glEnable, cap);
-    GLLog("glEnable") << GLLogEnum(cap);
-}
-
-void API_ENTRY(glEnableClientState)(GLenum array) {
-    CALL_GL_API(glEnableClientState, array);
-    GLLog("glEnableClientState") << GLLogEnum(array);
-}
-
-void API_ENTRY(glFinish)(void) {
-    CALL_GL_API(glFinish);
-    GLLog("glFinish");
-}
-
-void API_ENTRY(glFlush)(void) {
-    CALL_GL_API(glFlush);
-    GLLog("glFlush");
-}
-
-void API_ENTRY(glFogf)(GLenum pname, GLfloat param) {
-    CALL_GL_API(glFogf, pname, param);
-    GLLog("glFogf") << GLLogEnum(pname) << param;
-}
-
-void API_ENTRY(glFogfv)(GLenum pname, const GLfloat *params) {
-    CALL_GL_API(glFogfv, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glFogfv") << GLLogEnum(pname) << GLLogBuffer<GLfloat>(params);
-}
-
-void API_ENTRY(glFogx)(GLenum pname, GLfixed param) {
-    CALL_GL_API(glFogx, pname, param);
-    GLLog("glFogx") << GLLogEnum(pname) << GLLogFixed(param);
-}
-
-void API_ENTRY(glFogxv)(GLenum pname, const GLfixed *params) {
-    CALL_GL_API(glFogxv, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glFogfx") << GLLogEnum(pname) << GLLogBuffer<GLfixed>(params);
-}
-
-void API_ENTRY(glFrontFace)(GLenum mode) {
-    CALL_GL_API(glFrontFace, mode);
-    GLLog("glFrontFace") << GLLogEnum(mode);
- }
-
-void API_ENTRY(glFrustumf)(GLfloat left, GLfloat right,
-                GLfloat bottom, GLfloat top,
-                GLfloat zNear, GLfloat zFar) {
-    CALL_GL_API(glFrustumf, left, right, bottom, top, zNear, zFar);
-    GLLog("glFrustumf") << left << right << bottom << top << zNear << zFar;
-}
-
-void API_ENTRY(glFrustumx)(GLfixed left, GLfixed right,
-                GLfixed bottom, GLfixed top,
-                GLfixed zNear, GLfixed zFar) {
-    CALL_GL_API(glFrustumx, left, right, bottom, top, zNear, zFar);
-    GLLog("glFrustumx")
-            << GLLogFixed(left) << GLLogFixed(right)
-            << GLLogFixed(bottom) << GLLogFixed(top)
-            << GLLogFixed(zNear) << GLLogFixed(zFar);
-}
-
-void API_ENTRY(glGenTextures)(GLsizei n, GLuint *textures) {
-    CALL_GL_API(glGenTextures, n, textures);
-    GLLog("glGenTextures") << n << GLLogBuffer<GLuint>(textures, n);
-}
-
-GLenum API_ENTRY(glGetError)(void) {
-    GLLog("glGetError");
-    CALL_GL_API_RETURN(glGetError);
-}
-
-void API_ENTRY(glGetIntegerv)(GLenum pname, GLint *params) {
-    CALL_GL_API(glGetIntegerv, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glGetIntegerv") << GLLogEnum(pname) << GLLogBuffer<GLint>(params);
-}
-
-const GLubyte * API_ENTRY(glGetString)(GLenum name) {
-    GLLog("glGetString") << GLLogEnum(name);
-    CALL_GL_API_RETURN(glGetString, name);
-}
-
-void API_ENTRY(glHint)(GLenum target, GLenum mode) {
-    CALL_GL_API(glHint, target, mode);
-    GLLog("GLenum") << GLLogEnum(target) << GLLogEnum(mode);
-}
-
-void API_ENTRY(glLightModelf)(GLenum pname, GLfloat param) {
-    CALL_GL_API(glLightModelf, pname, param);
-    GLLog("glLightModelf") << GLLogEnum(pname) << param;
-}
-
-void API_ENTRY(glLightModelfv)(GLenum pname, const GLfloat *params) {
-    CALL_GL_API(glLightModelfv, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glLightModelfv") << GLLogEnum(pname) << GLLogBuffer<GLfloat>(params);
-}
-
-void API_ENTRY(glLightModelx)(GLenum pname, GLfixed param) {
-    CALL_GL_API(glLightModelx, pname, param);
-    GLLog("glLightModelx") << GLLogEnum(pname) << GLLogFixed(param);
-}
-
-void API_ENTRY(glLightModelxv)(GLenum pname, const GLfixed *params) {
-    CALL_GL_API(glLightModelxv, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glLightModelxv") << GLLogEnum(pname) << GLLogBuffer<GLfixed>(params);
-}
-
-void API_ENTRY(glLightf)(GLenum light, GLenum pname, GLfloat param) {
-    CALL_GL_API(glLightf, light, pname, param);
-    GLLog("glLightf") << GLLogEnum(light) << GLLogEnum(pname) << param;
-}
-
-void API_ENTRY(glLightfv)(GLenum light, GLenum pname, const GLfloat *params) {
-    CALL_GL_API(glLightfv, light, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glLightfv") << GLLogEnum(light) << GLLogEnum(pname) << GLLogBuffer<GLfloat>(params);
-}
-
-void API_ENTRY(glLightx)(GLenum light, GLenum pname, GLfixed param) {
-   CALL_GL_API(glLightx, light, pname, param);
-   GLLog("glLightx") << GLLogEnum(light) << GLLogEnum(pname) << GLLogFixed(param);
-}
-
-void API_ENTRY(glLightxv)(GLenum light, GLenum pname, const GLfixed *params) {
-    CALL_GL_API(glLightxv, light, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glLightxv") << GLLogEnum(light) << GLLogEnum(pname) << GLLogBuffer<GLfixed>(params);
-}
-
-void API_ENTRY(glLineWidth)(GLfloat width) {
-    CALL_GL_API(glLineWidth, width);
-    GLLog("glLineWidth") << width;
-}
-
-void API_ENTRY(glLineWidthx)(GLfixed width) {
-    CALL_GL_API(glLineWidthx, width);
-    GLLog("glLineWidth") << GLLogFixed(width);
-}
-
-void API_ENTRY(glLoadIdentity)(void) {
-    CALL_GL_API(glLoadIdentity);
-    GLLog("glLoadIdentity");
-}
-
-void API_ENTRY(glLoadMatrixf)(const GLfloat *m) {
-    CALL_GL_API(glLoadMatrixf, m);
-    GLLog("glLoadMatrixf") << GLLogBuffer<GLfloat>(m, 16);
-}
-
-void API_ENTRY(glLoadMatrixx)(const GLfixed *m) {
-    CALL_GL_API(glLoadMatrixx, m);
-    GLLog("glLoadMatrixx") << GLLogBuffer<GLfixed>(m, 16);
-}
-
-void API_ENTRY(glLogicOp)(GLenum opcode) {
-    CALL_GL_API(glLogicOp, opcode);
-    GLLog("glLogicOp") << GLLogEnum(opcode);
-}
-
-void API_ENTRY(glMaterialf)(GLenum face, GLenum pname, GLfloat param) {
-    CALL_GL_API(glMaterialf, face, pname, param);
-    GLLog("glMaterialf") << GLLogEnum(face) << GLLogEnum(pname) << param;
-}
-
-void API_ENTRY(glMaterialfv)(GLenum face, GLenum pname, const GLfloat *params) {
-    CALL_GL_API(glMaterialfv, face, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glMaterialfv") << GLLogEnum(face) << GLLogEnum(pname) << GLLogBuffer<GLfloat>(params);
-}
-
-void API_ENTRY(glMaterialx)(GLenum face, GLenum pname, GLfixed param) {
-    CALL_GL_API(glMaterialx, face, pname, param);
-    GLLog("glMaterialx") << GLLogEnum(face) << GLLogEnum(pname) << GLLogFixed(param);
-}
-
-void API_ENTRY(glMaterialxv)(GLenum face, GLenum pname, const GLfixed *params) {
-    CALL_GL_API(glMaterialxv, face, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glMaterialxv") << GLLogEnum(face) << GLLogEnum(pname) << GLLogBuffer<GLfixed>(params);
-}
-
-void API_ENTRY(glMatrixMode)(GLenum mode) {
-    CALL_GL_API(glMatrixMode, mode);
-    GLLog("glMatrixMode") << GLLogEnum(mode);
-}
-
-void API_ENTRY(glMultMatrixf)(const GLfloat *m) {
-    CALL_GL_API(glMultMatrixf, m);
-    GLLog("glMultMatrixf") << GLLogBuffer<GLfloat>(m, 16);
-}
-
-void API_ENTRY(glMultMatrixx)(const GLfixed *m) {
-    CALL_GL_API(glMultMatrixx, m);
-    GLLog("glMultMatrixx") << GLLogBuffer<GLfixed>(m, 16);
-}
-
-void API_ENTRY(glMultiTexCoord4f)(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q) {
-    CALL_GL_API(glMultiTexCoord4f, target, s, t, r, q);
-    GLLog("glMultiTexCoord4f") << GLLogEnum(target) << s << t << r << q;
-}
-
-void API_ENTRY(glMultiTexCoord4x)(GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q) {
-    CALL_GL_API(glMultiTexCoord4x, target, s, t, r, q);
-    GLLog("glMultiTexCoord4x") << GLLogEnum(target)
-        << GLLogFixed(s) << GLLogFixed(t) << GLLogFixed(r) << GLLogFixed(q);
-}
-
-void API_ENTRY(glNormal3f)(GLfloat nx, GLfloat ny, GLfloat nz) {
-    CALL_GL_API(glNormal3f, nx, ny, nz);
-    GLLog("glNormal3f") << nx << ny << nz;
-}
-
-void API_ENTRY(glNormal3x)(GLfixed nx, GLfixed ny, GLfixed nz) {
-    CALL_GL_API(glNormal3x, nx, ny, nz);
-    GLLog("glNormal3x") << GLLogFixed(nx) << GLLogFixed(ny) << GLLogFixed(nz);
-}
-
-void API_ENTRY(glNormalPointer)(GLenum type, GLsizei stride, const GLvoid *pointer) {
-    CALL_GL_API(glNormalPointer, type, stride, pointer);
-    GLLog("glNormalPointer") << GLLogEnum(type) << stride << pointer;
-}
-
-void API_ENTRY(glOrthof)(  GLfloat left, GLfloat right,
-                GLfloat bottom, GLfloat top,
-                GLfloat zNear, GLfloat zFar) {
-    CALL_GL_API(glOrthof, left, right, bottom, top, zNear, zFar);
-    GLLog("glOrthof") << left << right << bottom << top << zNear << zFar;
-}
-
-void API_ENTRY(glOrthox)(  GLfixed left, GLfixed right,
-                GLfixed bottom, GLfixed top,
-                GLfixed zNear, GLfixed zFar) {
-    CALL_GL_API(glOrthox, left, right, bottom, top, zNear, zFar);
-    GLLog("glOrthox") << GLLogFixed(left) << GLLogFixed(right)
-            << GLLogFixed(bottom) << GLLogFixed(top)
-            << GLLogFixed(zNear) << GLLogFixed(zFar);
-}
-
-void API_ENTRY(glPixelStorei)(GLenum pname, GLint param) {
-    CALL_GL_API(glPixelStorei, pname, param);
-    GLLog("glPixelStorei") << GLLogEnum(pname) << param;
-}
-
-void API_ENTRY(glPointSize)(GLfloat size) {
-    CALL_GL_API(glPointSize, size);
-    GLLog("glPointSize") << size;
-}
-
-void API_ENTRY(glPointSizex)(GLfixed size) {
-    CALL_GL_API(glPointSizex, size);
-    GLLog("glPointSizex") << GLLogFixed(size);
-}
-
-void API_ENTRY(glPolygonOffset)(GLfloat factor, GLfloat units) {
-    CALL_GL_API(glPolygonOffset, factor, units);
-    GLLog("glPolygonOffset") << factor << units;
-}
-
-void API_ENTRY(glPolygonOffsetx)(GLfixed factor, GLfixed units) {
-    CALL_GL_API(glPolygonOffsetx, factor, units);
-    GLLog("glPolygonOffsetx") << GLLogFixed(factor) << GLLogFixed(units);
-}
-
-void API_ENTRY(glPopMatrix)(void) {
-    CALL_GL_API(glPopMatrix);
-    GLLog("glPopMatrix");
-}
-
-void API_ENTRY(glPushMatrix)(void) {
-    CALL_GL_API(glPushMatrix);
-    GLLog("glPushMatrix");
-}
-
-void API_ENTRY(glReadPixels)(  GLint x, GLint y, GLsizei width, GLsizei height,
-                    GLenum format, GLenum type, GLvoid *pixels) {
-    CALL_GL_API(glReadPixels, x, y, width, height, format, type, pixels);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glReadPixels") << x << y << width << height << GLLogEnum(format) << GLLogEnum(type)
-            << GLLogBuffer<unsigned char>(static_cast<unsigned char *>(pixels));
-}
-
-void API_ENTRY(glRotatef)(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) {
-    CALL_GL_API(glRotatef, angle, x, y, z);
-    GLLog("glRotatef") << angle << x << y << z;
-}
-
-void API_ENTRY(glRotatex)(GLfixed angle, GLfixed x, GLfixed y, GLfixed z) {
-    CALL_GL_API(glRotatex, angle, x, y, z);
-    GLLog("glRotatex") << GLLogFixed(angle) << GLLogFixed(x) << GLLogFixed(y) << GLLogFixed(z);
-}
-
-void API_ENTRY(glSampleCoverage)(GLclampf value, GLboolean invert) {
-    CALL_GL_API(glSampleCoverage, value, invert);
-    GLLog("glSampleCoverage") << value << GLLogBool(invert);
-}
-
-void API_ENTRY(glSampleCoveragex)(GLclampx value, GLboolean invert) {
-    CALL_GL_API(glSampleCoveragex, value, invert);
-    GLLog("glSampleCoveragex") << GLLogFixed(value) << GLLogBool(invert);
-}
-
-void API_ENTRY(glScalef)(GLfloat x, GLfloat y, GLfloat z) {
-    CALL_GL_API(glScalef, x, y, z);
-    GLLog("glScalef") << x << y << z;
-}
-
-void API_ENTRY(glScalex)(GLfixed x, GLfixed y, GLfixed z) {
-    CALL_GL_API(glScalex, x, y, z);
-    GLLog("glScalex") << GLLogFixed(x) << GLLogFixed(y) << GLLogFixed(z);
-}
-
-void API_ENTRY(glScissor)(GLint x, GLint y, GLsizei width, GLsizei height) {
-    CALL_GL_API(glScissor, x, y, width, height);
-    GLLog("glScissor") << x << y << width << height;
-}
-
-void API_ENTRY(glShadeModel)(GLenum mode) {
-    CALL_GL_API(glShadeModel, mode);
-    GLLog("glShadeModel") << GLLogEnum(mode);
-}
-
-void API_ENTRY(glStencilFunc)(GLenum func, GLint ref, GLuint mask) {
-    CALL_GL_API(glStencilFunc, func, ref, mask);
-    GLLog("glStencilFunc") << GLLogEnum(func) << ref << mask;
-}
-
-void API_ENTRY(glStencilMask)(GLuint mask) {
-    CALL_GL_API(glStencilMask, mask);
-    GLLog("glStencilMask") << mask;
-}
-
-void API_ENTRY(glStencilOp)(GLenum fail, GLenum zfail, GLenum zpass) {
-    CALL_GL_API(glStencilOp, fail, zfail, zpass);
-    GLLog("glStencilOp") << GLLogEnum(fail) << GLLogEnum(zfail) << GLLogEnum(zpass);
-}
-
-void API_ENTRY(glTexCoordPointer)( GLint size, GLenum type,
-                        GLsizei stride, const GLvoid *pointer) {
-    CALL_GL_API(glTexCoordPointer, size, type, stride, pointer);
-    GLLog("glTexCoordPointer") << size << GLLogEnum(type) << stride << pointer;
-}
-
-void API_ENTRY(glTexEnvf)(GLenum target, GLenum pname, GLfloat param) {
-    CALL_GL_API(glTexEnvf, target, pname, param);
-    GLLog("glTexEnvf") << GLLogEnum(target) << GLLogEnum(pname) << param;
-}
-
-void API_ENTRY(glTexEnvfv)(GLenum target, GLenum pname, const GLfloat *params) {
-    CALL_GL_API(glTexEnvfv, target, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glTexEnvx") << GLLogEnum(target) << GLLogEnum(pname) << GLLogBuffer<GLfloat>(params);
-}
-
-void API_ENTRY(glTexEnvx)(GLenum target, GLenum pname, GLfixed param) {
-    CALL_GL_API(glTexEnvx, target, pname, param);
-    GLLog("glTexEnvx") << GLLogEnum(target) << GLLogEnum(pname) << GLLogFixed(param);
-}
-
-void API_ENTRY(glTexEnvxv)(GLenum target, GLenum pname, const GLfixed *params) {
-    CALL_GL_API(glTexEnvxv, target, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glTexEnvxv") << GLLogEnum(target) << GLLogEnum(pname) << GLLogBuffer<GLfixed>(params);
-}
-
-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);
-    GLLog("glTexImage2D") << GLLogEnum(target) << level << GLLogEnum(internalformat)
-            << width << height << border << GLLogEnum(format) << GLLogEnum(type)
-            << GLLogBuffer<unsigned char>( static_cast<const unsigned char *>(pixels));
-}
-
-void API_ENTRY(glTexParameterf)(GLenum target, GLenum pname, GLfloat param) {
-    CALL_GL_API(glTexParameterf, target, pname, param);
-    GLLog("glTexParameterf") << GLLogEnum(target) << GLLogEnum(pname) << param;
-}
-
-void API_ENTRY(glTexParameterx)(GLenum target, GLenum pname, GLfixed param) {
-    CALL_GL_API(glTexParameterx, target, pname, param);
-    GLLog("glTexParameterx") << GLLogEnum(target) << GLLogEnum(pname) << GLLogFixed(param);
-}
-
-void API_ENTRY(glTexSubImage2D)(   GLenum target, GLint level, GLint xoffset,
-                        GLint yoffset, GLsizei width, GLsizei height,
-                        GLenum format, GLenum type, const GLvoid *pixels) {
-    CALL_GL_API(glTexSubImage2D, target, level, xoffset, yoffset,
-            width, height, format, type, pixels);
-    GLLog("glTexSubImage2D") << GLLogEnum(target) << level << xoffset << yoffset
-            << width << height << GLLogEnum(format) << GLLogEnum(type)
-            << GLLogBuffer<unsigned char>( static_cast<const unsigned char *>(pixels));
-}
-
-void API_ENTRY(glTranslatef)(GLfloat x, GLfloat y, GLfloat z) {
-    CALL_GL_API(glTranslatef, x, y, z);
-    GLLog("glTranslatef") << x << y << z;
-}
-
-void API_ENTRY(glTranslatex)(GLfixed x, GLfixed y, GLfixed z) {
-    CALL_GL_API(glTranslatex, x, y, z);
-    GLLog("glTranslatex") << GLLogFixed(x) << GLLogFixed(y) << GLLogFixed(z);
-}
-
-void API_ENTRY(glVertexPointer)(   GLint size, GLenum type,
-                        GLsizei stride, const GLvoid *pointer) {
-    CALL_GL_API(glVertexPointer, size, type, stride, pointer);
-    GLLog("glVertexPointer") << size << GLLogEnum(type) << stride << pointer;
-}
-
-void API_ENTRY(glViewport)(GLint x, GLint y, GLsizei width, GLsizei height) {
-    CALL_GL_API(glViewport, x, y, width, height);
-    GLLog("glViewport") << x << y << width << height;
-}
-
-// ES 1.1
-void API_ENTRY(glClipPlanef)(GLenum plane, const GLfloat *equation) {
-    CALL_GL_API(glClipPlanef, plane, equation);
-    GLLog("glClipPlanef") << GLLogEnum(plane) << GLLogBuffer<GLfloat>(equation, 4);
-}
-void API_ENTRY(glClipPlanex)(GLenum plane, const GLfixed *equation) {
-    CALL_GL_API(glClipPlanex, plane, equation);
-    GLLog("glClipPlanex") << GLLogEnum(plane) << GLLogBuffer<GLfixed>(equation, 4);
-}
-void API_ENTRY(glBindBuffer)(GLenum target, GLuint buffer) {
-    CALL_GL_API(glBindBuffer, target, buffer);
-    GLLog("glBindBuffer") << GLLogEnum(target) << buffer;
-}
-void API_ENTRY(glBufferData)(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) {
-    CALL_GL_API(glBufferData, target, size, data, usage);
-    GLLog("glBufferData") << GLLogEnum(target) << size
-        << GLLogBuffer<unsigned char>(static_cast<const unsigned char*>(data), size);
-}
-void API_ENTRY(glBufferSubData)(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) {
-    CALL_GL_API(glBufferSubData, target, offset, size, data);
-    GLLog("glBufferSubData") << GLLogEnum(target) << offset << size
-        << GLLogBuffer<unsigned char>(static_cast<const unsigned char*>(data), size);
-}
-void API_ENTRY(glDeleteBuffers)(GLsizei n, const GLuint* buffers) {
-    CALL_GL_API(glDeleteBuffers, n, buffers);
-    GLLog("glDeleteBuffers") << n << GLLogBuffer<GLuint>(buffers, n);
-}
-void API_ENTRY(glGenBuffers)(GLsizei n, GLuint* buffers) {
-    CALL_GL_API(glGenBuffers, n, buffers);
-    GLLog("glGenBuffers") << n << GLLogBuffer<GLuint>(buffers, n);
-}
-void API_ENTRY(glGetBooleanv)(GLenum pname, GLboolean *params) {
-    CALL_GL_API(glGetBooleanv, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glGetBooleanv") << GLLogEnum(pname) << GLLogBuffer<GLboolean>(params);
-}
-void API_ENTRY(glGetFixedv)(GLenum pname, GLfixed *params) {
-    CALL_GL_API(glGetFixedv, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glGetFixedv") << GLLogEnum(pname) << GLLogBuffer<GLfixed>(params);
-}
-void API_ENTRY(glGetFloatv)(GLenum pname, GLfloat *params) {
-    CALL_GL_API(glGetFloatv, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glGetFloatv") << GLLogEnum(pname) << GLLogBuffer<GLfloat>(params);
-}
-void API_ENTRY(glGetPointerv)(GLenum pname, void **params) {
-    CALL_GL_API(glGetPointerv, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glGetPointerv") << GLLogEnum(pname) << GLLogBuffer<void*>(params);
-}
-void API_ENTRY(glGetBufferParameteriv)(GLenum target, GLenum pname, GLint *params) {
-    // XXX: we need to compute the size of this buffer
-    CALL_GL_API(glGetBufferParameteriv, target, pname, params);
-    GLLog("glGetBufferParameteriv") << GLLogEnum(target) << GLLogEnum(pname) << GLLogBuffer<GLint>(params);
-}
-void API_ENTRY(glGetClipPlanef)(GLenum pname, GLfloat eqn[4]) {
-    CALL_GL_API(glGetClipPlanef, pname, eqn);
-    GLLog("glGetClipPlanef") << GLLogEnum(pname) << GLLogBuffer<GLfloat>(eqn, 4);
-}
-void API_ENTRY(glGetClipPlanex)(GLenum pname, GLfixed eqn[4]) {
-    CALL_GL_API(glGetClipPlanex, pname, eqn);
-    GLLog("glGetClipPlanex") << GLLogEnum(pname) << GLLogBuffer<GLfixed>(eqn, 4);
-}
-void API_ENTRY(glGetLightxv)(GLenum light, GLenum pname, GLfixed *params) {
-    CALL_GL_API(glGetLightxv, light, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glGetLightxv") << GLLogEnum(light) << GLLogEnum(pname) << GLLogBuffer<GLfixed>(params);
-}
-void API_ENTRY(glGetLightfv)(GLenum light, GLenum pname, GLfloat *params) {
-    CALL_GL_API(glGetLightfv, light, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glGetLightfv") << GLLogEnum(light) << GLLogEnum(pname) << GLLogBuffer<GLfloat>(params);
-}
-void API_ENTRY(glGetMaterialxv)(GLenum face, GLenum pname, GLfixed *params) {
-    CALL_GL_API(glGetMaterialxv, face, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glGetMaterialxv") << GLLogEnum(face) << GLLogEnum(pname) << GLLogBuffer<GLfixed>(params);
-}
-void API_ENTRY(glGetMaterialfv)(GLenum face, GLenum pname, GLfloat *params) {
-    CALL_GL_API(glGetMaterialfv, face, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glGetMaterialfv") << GLLogEnum(face) << GLLogEnum(pname) << GLLogBuffer<GLfloat>(params);
-}
-void API_ENTRY(glGetTexEnvfv)(GLenum env, GLenum pname, GLfloat *params) {
-    CALL_GL_API(glGetTexEnvfv, env, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glGetTexEnvfv") << GLLogEnum(env) << GLLogEnum(pname) << GLLogBuffer<GLfloat>(params);
-}
-void API_ENTRY(glGetTexEnviv)(GLenum env, GLenum pname, GLint *params) {
-    CALL_GL_API(glGetTexEnviv, env, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glGetTexEnviv") << GLLogEnum(env) << GLLogEnum(pname) << GLLogBuffer<GLint>(params);
-}
-void API_ENTRY(glGetTexEnvxv)(GLenum env, GLenum pname, GLfixed *params) {
-    CALL_GL_API(glGetTexEnvxv, env, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glGetTexEnvxv") << GLLogEnum(env) << GLLogEnum(pname) << GLLogBuffer<GLfixed>(params);
-}
-void API_ENTRY(glGetTexParameterfv)(GLenum target, GLenum pname, GLfloat *params) {
-    CALL_GL_API(glGetTexParameterfv, target, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glGetTexParameterfv") << GLLogEnum(target) << GLLogEnum(pname) << GLLogBuffer<GLfloat>(params);
-}
-void API_ENTRY(glGetTexParameteriv)(GLenum target, GLenum pname, GLint *params) {
-    CALL_GL_API(glGetTexParameteriv, target, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glGetTexParameteriv") << GLLogEnum(target) << GLLogEnum(pname) << GLLogBuffer<GLint>(params);
-}
-void API_ENTRY(glGetTexParameterxv)(GLenum target, GLenum pname, GLfixed *params) {
-    CALL_GL_API(glGetTexParameterxv, target, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glGetTexParameterxv") << GLLogEnum(target) << GLLogEnum(pname) << GLLogBuffer<GLfixed>(params);
-}
-GLboolean API_ENTRY(glIsBuffer)(GLuint buffer) {
-    GLLog("glIsBuffer") << buffer;
-    CALL_GL_API_RETURN(glIsBuffer, buffer);
-}
-GLboolean API_ENTRY(glIsEnabled)(GLenum cap) {
-    GLLog("glIsEnabled") << GLLogEnum(cap);
-    CALL_GL_API_RETURN(glIsEnabled, cap);
-}
-GLboolean API_ENTRY(glIsTexture)(GLuint texture) {
-    GLLog("glIsTexture") << texture;
-    CALL_GL_API_RETURN(glIsTexture, texture);
-}
-void API_ENTRY(glPointParameterf)(GLenum pname, GLfloat param) {
-    CALL_GL_API(glPointParameterf, pname, param);
-    GLLog("glPointParameterf") << GLLogEnum(pname) << param;
-}
-void API_ENTRY(glPointParameterfv)(GLenum pname, const GLfloat *params) {
-    CALL_GL_API(glPointParameterfv, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glPointParameterfv") << GLLogEnum(pname) << GLLogBuffer<GLfloat>(params);
-}
-void API_ENTRY(glPointParameterx)(GLenum pname, GLfixed param) {
-    CALL_GL_API(glPointParameterx, pname, param);
-    GLLog("glPointParameterx") << GLLogEnum(pname) << GLLogFixed(param);
-}
-void API_ENTRY(glPointParameterxv)(GLenum pname, const GLfixed *params) {
-    CALL_GL_API(glPointParameterxv, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glPointParameterxv") << GLLogEnum(pname) << GLLogBuffer<GLfixed>(params);
-}
-void API_ENTRY(glColor4ub)(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha) {
-    CALL_GL_API(glColor4ub, red, green, blue, alpha);
-    GLLog("glColor4ub") << red << green << blue << alpha;
-}
-void API_ENTRY(glTexEnvi)(GLenum target, GLenum pname, GLint param) {
-    CALL_GL_API(glTexEnvi, target, pname, param);
-    GLLog("glTexEnvi") << GLLogEnum(target) << GLLogEnum(pname) << param;
-}
-void API_ENTRY(glTexEnviv)(GLenum target, GLenum pname, const GLint *params) {
-    CALL_GL_API(glTexEnviv, target, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glTexEnviv") << GLLogEnum(target) << GLLogEnum(pname) << GLLogBuffer<GLint>(params);
-}
-
-void API_ENTRY(glTexParameterfv)(GLenum target, GLenum pname, const GLfloat *params) {
-    CALL_GL_API(glTexParameterfv, target, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glTexParameterfv") << GLLogEnum(target) << GLLogEnum(pname) << GLLogBuffer<GLfloat>(params);
-}
-
-void API_ENTRY(glTexParameteriv)(GLenum target, GLenum pname, const GLint *params) {
-    CALL_GL_API(glTexParameteriv, target, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glTexParameteriv") << GLLogEnum(target) << GLLogEnum(pname) << GLLogBuffer<GLint>(params);
-}
-
-void API_ENTRY(glTexParameteri)(GLenum target, GLenum pname, GLint param) {
-    CALL_GL_API(glTexParameteri, target, pname, param);
-    GLLog("glTexParameteri") << GLLogEnum(target) << GLLogEnum(pname) << param;
-}
-void API_ENTRY(glTexParameterxv)(GLenum target, GLenum pname, const GLfixed *params) {
-    CALL_GL_API(glTexParameterxv, target, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glTexParameterxv") << GLLogEnum(target) << GLLogEnum(pname) << GLLogBuffer<GLfixed>(params);
-}
-void API_ENTRY(glPointSizePointerOES)(GLenum type, GLsizei stride, const GLvoid *pointer) {
-    CALL_GL_API(glPointSizePointerOES, type, stride, pointer);
-    GLLog("glPointSizePointerOES") << GLLogEnum(type) << stride << pointer;
-}
-
-// Extensions
-void API_ENTRY(glDrawTexsOES)(GLshort x , GLshort y, GLshort z, GLshort w, GLshort h) {
-    CALL_GL_API(glDrawTexsOES, x, y, z, w, h);
-    GLLog("glDrawTexsOES") << x << y << z << w << h;
-}
-void API_ENTRY(glDrawTexiOES)(GLint x, GLint y, GLint z, GLint w, GLint h) {
-    CALL_GL_API(glDrawTexiOES, x, y, z, w, h);
-    GLLog("glDrawTexiOES") << x << y << z << w << h;
-}
-void API_ENTRY(glDrawTexfOES)(GLfloat x, GLfloat y, GLfloat z, GLfloat w, GLfloat h) {
-    CALL_GL_API(glDrawTexfOES, x, y, z, w, h);
-    GLLog("glDrawTexfOES") << x << y << z << w << h;
-}
-void API_ENTRY(glDrawTexxOES)(GLfixed x, GLfixed y, GLfixed z, GLfixed w, GLfixed h) {
-    CALL_GL_API(glDrawTexxOES, x, y, z, w, h);
-    GLLog("glDrawTexfOES") << GLLogFixed(x) << GLLogFixed(y) << GLLogFixed(z) << GLLogFixed(w) << GLLogFixed(h);
-}
-void API_ENTRY(glDrawTexsvOES)(const GLshort* coords) {
-    CALL_GL_API(glDrawTexsvOES, coords);
-    GLLog("glDrawTexsvOES") << GLLogBuffer<GLshort>(coords, 5);
-}
-void API_ENTRY(glDrawTexivOES)(const GLint* coords) {
-    CALL_GL_API(glDrawTexivOES, coords);
-    GLLog("glDrawTexivOES") << GLLogBuffer<GLint>(coords, 5);
-}
-void API_ENTRY(glDrawTexfvOES)(const GLfloat* coords) {
-    CALL_GL_API(glDrawTexfvOES, coords);
-    GLLog("glDrawTexfvOES") << GLLogBuffer<GLfloat>(coords, 5);
-}
-void API_ENTRY(glDrawTexxvOES)(const GLfixed* coords) {
-    CALL_GL_API(glDrawTexxvOES, coords);
-    GLLog("glDrawTexxvOES") << GLLogBuffer<GLfixed>(coords, 5);
-}
-GLbitfield API_ENTRY(glQueryMatrixxOES)(GLfixed* mantissa, GLint* exponent) {
-    GLLog("glQueryMatrixxOES") << GLLogBuffer<GLfixed>(mantissa, 16) << GLLogBuffer<GLfixed>(exponent, 16);
-    CALL_GL_API_RETURN(glQueryMatrixxOES, mantissa, exponent);
-}
-
-// ----------------------------------------------------------------------------
-}; // namespace android
-// ----------------------------------------------------------------------------
diff --git a/opengl/libs/GLES_CM/glext_api.in b/opengl/libs/GLES_CM/glext_api.in
new file mode 100644
index 0000000..2c8648e
--- /dev/null
+++ b/opengl/libs/GLES_CM/glext_api.in
@@ -0,0 +1,270 @@
+void API_ENTRY(glBlendEquationSeparateOES)(GLenum modeRGB, GLenum modeAlpha) {
+    CALL_GL_API(glBlendEquationSeparateOES, modeRGB, modeAlpha);
+}
+void API_ENTRY(glBlendFuncSeparateOES)(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) {
+    CALL_GL_API(glBlendFuncSeparateOES, srcRGB, dstRGB, srcAlpha, dstAlpha);
+}
+void API_ENTRY(glBlendEquationOES)(GLenum mode) {
+    CALL_GL_API(glBlendEquationOES, mode);
+}
+void API_ENTRY(glDrawTexsOES)(GLshort x, GLshort y, GLshort z, GLshort width, GLshort height) {
+    CALL_GL_API(glDrawTexsOES, x, y, z, width, height);
+}
+void API_ENTRY(glDrawTexiOES)(GLint x, GLint y, GLint z, GLint width, GLint height) {
+    CALL_GL_API(glDrawTexiOES, x, y, z, width, height);
+}
+void API_ENTRY(glDrawTexxOES)(GLfixed x, GLfixed y, GLfixed z, GLfixed width, GLfixed height) {
+    CALL_GL_API(glDrawTexxOES, x, y, z, width, height);
+}
+void API_ENTRY(glDrawTexsvOES)(const GLshort *coords) {
+    CALL_GL_API(glDrawTexsvOES, coords);
+}
+void API_ENTRY(glDrawTexivOES)(const GLint *coords) {
+    CALL_GL_API(glDrawTexivOES, coords);
+}
+void API_ENTRY(glDrawTexxvOES)(const GLfixed *coords) {
+    CALL_GL_API(glDrawTexxvOES, coords);
+}
+void API_ENTRY(glDrawTexfOES)(GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height) {
+    CALL_GL_API(glDrawTexfOES, x, y, z, width, height);
+}
+void API_ENTRY(glDrawTexfvOES)(const GLfloat *coords) {
+    CALL_GL_API(glDrawTexfvOES, coords);
+}
+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(glAlphaFuncxOES)(GLenum func, GLclampx ref) {
+    CALL_GL_API(glAlphaFuncxOES, func, ref);
+}
+void API_ENTRY(glClearColorxOES)(GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha) {
+    CALL_GL_API(glClearColorxOES, red, green, blue, alpha);
+}
+void API_ENTRY(glClearDepthxOES)(GLclampx depth) {
+    CALL_GL_API(glClearDepthxOES, depth);
+}
+void API_ENTRY(glClipPlanexOES)(GLenum plane, const GLfixed *equation) {
+    CALL_GL_API(glClipPlanexOES, plane, equation);
+}
+void API_ENTRY(glColor4xOES)(GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha) {
+    CALL_GL_API(glColor4xOES, red, green, blue, alpha);
+}
+void API_ENTRY(glDepthRangexOES)(GLclampx zNear, GLclampx zFar) {
+    CALL_GL_API(glDepthRangexOES, zNear, zFar);
+}
+void API_ENTRY(glFogxOES)(GLenum pname, GLfixed param) {
+    CALL_GL_API(glFogxOES, pname, param);
+}
+void API_ENTRY(glFogxvOES)(GLenum pname, const GLfixed *params) {
+    CALL_GL_API(glFogxvOES, pname, params);
+}
+void API_ENTRY(glFrustumxOES)(GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar) {
+    CALL_GL_API(glFrustumxOES, left, right, bottom, top, zNear, zFar);
+}
+void API_ENTRY(glGetClipPlanexOES)(GLenum pname, GLfixed eqn[4]) {
+    CALL_GL_API(glGetClipPlanexOES, pname, eqn);
+}
+void API_ENTRY(glGetFixedvOES)(GLenum pname, GLfixed *params) {
+    CALL_GL_API(glGetFixedvOES, pname, params);
+}
+void API_ENTRY(glGetLightxvOES)(GLenum light, GLenum pname, GLfixed *params) {
+    CALL_GL_API(glGetLightxvOES, light, pname, params);
+}
+void API_ENTRY(glGetMaterialxvOES)(GLenum face, GLenum pname, GLfixed *params) {
+    CALL_GL_API(glGetMaterialxvOES, face, pname, params);
+}
+void API_ENTRY(glGetTexEnvxvOES)(GLenum env, GLenum pname, GLfixed *params) {
+    CALL_GL_API(glGetTexEnvxvOES, env, pname, params);
+}
+void API_ENTRY(glGetTexParameterxvOES)(GLenum target, GLenum pname, GLfixed *params) {
+    CALL_GL_API(glGetTexParameterxvOES, target, pname, params);
+}
+void API_ENTRY(glLightModelxOES)(GLenum pname, GLfixed param) {
+    CALL_GL_API(glLightModelxOES, pname, param);
+}
+void API_ENTRY(glLightModelxvOES)(GLenum pname, const GLfixed *params) {
+    CALL_GL_API(glLightModelxvOES, pname, params);
+}
+void API_ENTRY(glLightxOES)(GLenum light, GLenum pname, GLfixed param) {
+    CALL_GL_API(glLightxOES, light, pname, param);
+}
+void API_ENTRY(glLightxvOES)(GLenum light, GLenum pname, const GLfixed *params) {
+    CALL_GL_API(glLightxvOES, light, pname, params);
+}
+void API_ENTRY(glLineWidthxOES)(GLfixed width) {
+    CALL_GL_API(glLineWidthxOES, width);
+}
+void API_ENTRY(glLoadMatrixxOES)(const GLfixed *m) {
+    CALL_GL_API(glLoadMatrixxOES, m);
+}
+void API_ENTRY(glMaterialxOES)(GLenum face, GLenum pname, GLfixed param) {
+    CALL_GL_API(glMaterialxOES, face, pname, param);
+}
+void API_ENTRY(glMaterialxvOES)(GLenum face, GLenum pname, const GLfixed *params) {
+    CALL_GL_API(glMaterialxvOES, face, pname, params);
+}
+void API_ENTRY(glMultMatrixxOES)(const GLfixed *m) {
+    CALL_GL_API(glMultMatrixxOES, m);
+}
+void API_ENTRY(glMultiTexCoord4xOES)(GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q) {
+    CALL_GL_API(glMultiTexCoord4xOES, target, s, t, r, q);
+}
+void API_ENTRY(glNormal3xOES)(GLfixed nx, GLfixed ny, GLfixed nz) {
+    CALL_GL_API(glNormal3xOES, nx, ny, nz);
+}
+void API_ENTRY(glOrthoxOES)(GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar) {
+    CALL_GL_API(glOrthoxOES, left, right, bottom, top, zNear, zFar);
+}
+void API_ENTRY(glPointParameterxOES)(GLenum pname, GLfixed param) {
+    CALL_GL_API(glPointParameterxOES, pname, param);
+}
+void API_ENTRY(glPointParameterxvOES)(GLenum pname, const GLfixed *params) {
+    CALL_GL_API(glPointParameterxvOES, pname, params);
+}
+void API_ENTRY(glPointSizexOES)(GLfixed size) {
+    CALL_GL_API(glPointSizexOES, size);
+}
+void API_ENTRY(glPolygonOffsetxOES)(GLfixed factor, GLfixed units) {
+    CALL_GL_API(glPolygonOffsetxOES, factor, units);
+}
+void API_ENTRY(glRotatexOES)(GLfixed angle, GLfixed x, GLfixed y, GLfixed z) {
+    CALL_GL_API(glRotatexOES, angle, x, y, z);
+}
+void API_ENTRY(glSampleCoveragexOES)(GLclampx value, GLboolean invert) {
+    CALL_GL_API(glSampleCoveragexOES, value, invert);
+}
+void API_ENTRY(glScalexOES)(GLfixed x, GLfixed y, GLfixed z) {
+    CALL_GL_API(glScalexOES, x, y, z);
+}
+void API_ENTRY(glTexEnvxOES)(GLenum target, GLenum pname, GLfixed param) {
+    CALL_GL_API(glTexEnvxOES, target, pname, param);
+}
+void API_ENTRY(glTexEnvxvOES)(GLenum target, GLenum pname, const GLfixed *params) {
+    CALL_GL_API(glTexEnvxvOES, target, pname, params);
+}
+void API_ENTRY(glTexParameterxOES)(GLenum target, GLenum pname, GLfixed param) {
+    CALL_GL_API(glTexParameterxOES, target, pname, param);
+}
+void API_ENTRY(glTexParameterxvOES)(GLenum target, GLenum pname, const GLfixed *params) {
+    CALL_GL_API(glTexParameterxvOES, target, pname, params);
+}
+void API_ENTRY(glTranslatexOES)(GLfixed x, GLfixed y, GLfixed z) {
+    CALL_GL_API(glTranslatexOES, x, y, z);
+}
+GLboolean API_ENTRY(glIsRenderbufferOES)(GLuint renderbuffer) {
+    CALL_GL_API_RETURN(glIsRenderbufferOES, renderbuffer);
+}
+void API_ENTRY(glBindRenderbufferOES)(GLenum target, GLuint renderbuffer) {
+    CALL_GL_API(glBindRenderbufferOES, target, renderbuffer);
+}
+void API_ENTRY(glDeleteRenderbuffersOES)(GLsizei n, const GLuint* renderbuffers) {
+    CALL_GL_API(glDeleteRenderbuffersOES, n, renderbuffers);
+}
+void API_ENTRY(glGenRenderbuffersOES)(GLsizei n, GLuint* renderbuffers) {
+    CALL_GL_API(glGenRenderbuffersOES, n, renderbuffers);
+}
+void API_ENTRY(glRenderbufferStorageOES)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
+    CALL_GL_API(glRenderbufferStorageOES, target, internalformat, width, height);
+}
+void API_ENTRY(glGetRenderbufferParameterivOES)(GLenum target, GLenum pname, GLint* params) {
+    CALL_GL_API(glGetRenderbufferParameterivOES, target, pname, params);
+}
+GLboolean API_ENTRY(glIsFramebufferOES)(GLuint framebuffer) {
+    CALL_GL_API_RETURN(glIsFramebufferOES, framebuffer);
+}
+void API_ENTRY(glBindFramebufferOES)(GLenum target, GLuint framebuffer) {
+    CALL_GL_API(glBindFramebufferOES, target, framebuffer);
+}
+void API_ENTRY(glDeleteFramebuffersOES)(GLsizei n, const GLuint* framebuffers) {
+    CALL_GL_API(glDeleteFramebuffersOES, n, framebuffers);
+}
+void API_ENTRY(glGenFramebuffersOES)(GLsizei n, GLuint* framebuffers) {
+    CALL_GL_API(glGenFramebuffersOES, n, framebuffers);
+}
+GLenum API_ENTRY(glCheckFramebufferStatusOES)(GLenum target) {
+    CALL_GL_API_RETURN(glCheckFramebufferStatusOES, target);
+}
+void API_ENTRY(glFramebufferRenderbufferOES)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) {
+    CALL_GL_API(glFramebufferRenderbufferOES, target, attachment, renderbuffertarget, renderbuffer);
+}
+void API_ENTRY(glFramebufferTexture2DOES)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) {
+    CALL_GL_API(glFramebufferTexture2DOES, target, attachment, textarget, texture, level);
+}
+void API_ENTRY(glGetFramebufferAttachmentParameterivOES)(GLenum target, GLenum attachment, GLenum pname, GLint* params) {
+    CALL_GL_API(glGetFramebufferAttachmentParameterivOES, target, attachment, pname, params);
+}
+void API_ENTRY(glGenerateMipmapOES)(GLenum target) {
+    CALL_GL_API(glGenerateMipmapOES, target);
+}
+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(glCurrentPaletteMatrixOES)(GLuint matrixpaletteindex) {
+    CALL_GL_API(glCurrentPaletteMatrixOES, matrixpaletteindex);
+}
+void API_ENTRY(glLoadPaletteFromModelViewMatrixOES)(void) {
+    CALL_GL_API(glLoadPaletteFromModelViewMatrixOES);
+}
+void API_ENTRY(glMatrixIndexPointerOES)(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) {
+    CALL_GL_API(glMatrixIndexPointerOES, size, type, stride, pointer);
+}
+void API_ENTRY(glWeightPointerOES)(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) {
+    CALL_GL_API(glWeightPointerOES, size, type, stride, pointer);
+}
+GLbitfield API_ENTRY(glQueryMatrixxOES)(GLfixed mantissa[16], GLint exponent[16]) {
+    CALL_GL_API_RETURN(glQueryMatrixxOES, mantissa, exponent);
+}
+void API_ENTRY(glDepthRangefOES)(GLclampf zNear, GLclampf zFar) {
+    CALL_GL_API(glDepthRangefOES, zNear, zFar);
+}
+void API_ENTRY(glFrustumfOES)(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar) {
+    CALL_GL_API(glFrustumfOES, left, right, bottom, top, zNear, zFar);
+}
+void API_ENTRY(glOrthofOES)(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar) {
+    CALL_GL_API(glOrthofOES, left, right, bottom, top, zNear, zFar);
+}
+void API_ENTRY(glClipPlanefOES)(GLenum plane, const GLfloat *equation) {
+    CALL_GL_API(glClipPlanefOES, plane, equation);
+}
+void API_ENTRY(glGetClipPlanefOES)(GLenum pname, GLfloat eqn[4]) {
+    CALL_GL_API(glGetClipPlanefOES, pname, eqn);
+}
+void API_ENTRY(glClearDepthfOES)(GLclampf depth) {
+    CALL_GL_API(glClearDepthfOES, depth);
+}
+void API_ENTRY(glTexGenfOES)(GLenum coord, GLenum pname, GLfloat param) {
+    CALL_GL_API(glTexGenfOES, coord, pname, param);
+}
+void API_ENTRY(glTexGenfvOES)(GLenum coord, GLenum pname, const GLfloat *params) {
+    CALL_GL_API(glTexGenfvOES, coord, pname, params);
+}
+void API_ENTRY(glTexGeniOES)(GLenum coord, GLenum pname, GLint param) {
+    CALL_GL_API(glTexGeniOES, coord, pname, param);
+}
+void API_ENTRY(glTexGenivOES)(GLenum coord, GLenum pname, const GLint *params) {
+    CALL_GL_API(glTexGenivOES, coord, pname, params);
+}
+void API_ENTRY(glTexGenxOES)(GLenum coord, GLenum pname, GLfixed param) {
+    CALL_GL_API(glTexGenxOES, coord, pname, param);
+}
+void API_ENTRY(glTexGenxvOES)(GLenum coord, GLenum pname, const GLfixed *params) {
+    CALL_GL_API(glTexGenxvOES, coord, pname, params);
+}
+void API_ENTRY(glGetTexGenfvOES)(GLenum coord, GLenum pname, GLfloat *params) {
+    CALL_GL_API(glGetTexGenfvOES, coord, pname, params);
+}
+void API_ENTRY(glGetTexGenivOES)(GLenum coord, GLenum pname, GLint *params) {
+    CALL_GL_API(glGetTexGenivOES, coord, pname, params);
+}
+void API_ENTRY(glGetTexGenxvOES)(GLenum coord, GLenum pname, GLfixed *params) {
+    CALL_GL_API(glGetTexGenxvOES, coord, pname, params);
+}
diff --git a/opengl/libs/egl_entries.in b/opengl/libs/egl_entries.in
index 33b4c65..3b4551b 100644
--- a/opengl/libs/egl_entries.in
+++ b/opengl/libs/egl_entries.in
@@ -43,3 +43,10 @@
 /* EGL 1.3 */
 
 /* EGL 1.4 */
+
+/* EGL_EGLEXT_VERSION 3 */
+
+EGL_ENTRY(EGLBoolean,  eglLockSurfaceKHR,   EGLDisplay, EGLSurface, const EGLint *)
+EGL_ENTRY(EGLBoolean,  eglUnlockSurfaceKHR, EGLDisplay, EGLSurface)
+EGL_ENTRY(EGLImageKHR, eglCreateImageKHR,   EGLDisplay, EGLContext, EGLenum, EGLClientBuffer, const EGLint *)
+EGL_ENTRY(EGLBoolean,  eglDestroyImageKHR,  EGLDisplay, EGLImageKHR)
diff --git a/opengl/libs/egl_impl.h b/opengl/libs/egl_impl.h
index 62ce3fc..312b176 100644
--- a/opengl/libs/egl_impl.h
+++ b/opengl/libs/egl_impl.h
@@ -20,6 +20,8 @@
 #include <ctype.h>
 
 #include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <EGL/eglplatform.h>
 
 // ----------------------------------------------------------------------------
 namespace android {
diff --git a/opengl/libs/gl_entries.in b/opengl/libs/gl_entries.in
index b97e8fe..d7cc5da 100644
--- a/opengl/libs/gl_entries.in
+++ b/opengl/libs/gl_entries.in
@@ -1,159 +1,145 @@
-GL_ENTRY(void, glColor4f, GLfloat, GLfloat, GLfloat, GLfloat)
-GL_ENTRY(void, glColor4x, GLfixed, GLfixed, GLfixed, GLfixed)
-GL_ENTRY(void, glNormal3f, GLfloat, GLfloat, GLfloat)
-GL_ENTRY(void, glNormal3x, GLfixed, GLfixed, GLfixed)
-GL_ENTRY(void, glCullFace, GLenum)
-GL_ENTRY(void, glFrontFace, GLenum)
-GL_ENTRY(void, glDisable, GLenum)
-GL_ENTRY(void, glEnable, GLenum)
-GL_ENTRY(void, glFinish, void)
-GL_ENTRY(void, glFlush, void)
-GL_ENTRY(GLenum, glGetError, void)
-GL_ENTRY(const GLubyte*, glGetString, GLenum)
-GL_ENTRY(void, glGetIntegerv, GLenum, GLint *)
-GL_ENTRY(void, glColorMask, GLboolean, GLboolean, GLboolean, GLboolean)
-GL_ENTRY(void, glDepthMask, GLboolean)
-GL_ENTRY(void, glStencilMask, GLuint)
-GL_ENTRY(void, glDepthFunc, GLenum)
-GL_ENTRY(void, glDepthRangef, GLclampf zNear, GLclampf zFar)
-GL_ENTRY(void, glDepthRangex, GLclampx zNear, GLclampx zFar)
-GL_ENTRY(void, glPolygonOffset, GLfloat factor, GLfloat units)
-GL_ENTRY(void, glPolygonOffsetx, GLfixed factor, GLfixed units)
-GL_ENTRY(void, glLogicOp, GLenum opcode)
-GL_ENTRY(void, glAlphaFuncx, GLenum func, GLclampx ref)
 GL_ENTRY(void, glAlphaFunc, GLenum func, GLclampf ref)
-GL_ENTRY(void, glBlendFunc, GLenum sfactor, GLenum dfactor)
-GL_ENTRY(void, glClear, GLbitfield mask)
-GL_ENTRY(void, glClearColor, GLclampf r, GLclampf g, GLclampf b, GLclampf a)
-GL_ENTRY(void, glClearColorx, GLclampx r, GLclampx g, GLclampx b, GLclampx a)
+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, glPointSize, GLfloat)
-GL_ENTRY(void, glPointSizex, GLfixed)
-GL_ENTRY(void, glSampleCoverage, GLclampf value, GLboolean invert)
-GL_ENTRY(void, glSampleCoveragex, GLclampx value, GLboolean invert)
-GL_ENTRY(void, glStencilFunc, GLenum func, GLint ref, GLuint mask)
-GL_ENTRY(void, glStencilOp, GLenum fail, GLenum zfail, GLenum zpass)
-GL_ENTRY(void, glScissor, GLint x, GLint y, GLsizei width, GLsizei height)
-GL_ENTRY(void, glHint, GLenum, GLenum mode)
-GL_ENTRY(void, glLineWidth, GLfloat width)
+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, glShadeModel, GLenum)
-GL_ENTRY(void, glLightModelf, GLenum, GLfloat)
-GL_ENTRY(void, glLightModelfv, GLenum, const GLfloat *)
-GL_ENTRY(void, glLightModelx, GLenum, GLfixed)
-GL_ENTRY(void, glLightModelxv, GLenum, const GLfixed *)
-GL_ENTRY(void, glLightf, GLenum, GLenum, GLfloat)
-GL_ENTRY(void, glLightfv, GLenum, GLenum, const GLfloat *)
-GL_ENTRY(void, glLightx, GLenum, GLenum, GLfixed)
-GL_ENTRY(void, glLightxv, GLenum, GLenum, const GLfixed *)
-GL_ENTRY(void, glMaterialf, GLenum, GLenum, GLfloat)
-GL_ENTRY(void, glMaterialfv, GLenum, GLenum, const GLfloat *)
-GL_ENTRY(void, glMaterialx, GLenum, GLenum, GLfixed)
-GL_ENTRY(void, glMaterialxv, GLenum, GLenum, const GLfixed *)
-GL_ENTRY(void, glFogf, GLenum, GLfloat)
-GL_ENTRY(void, glFogfv, GLenum, const GLfloat *)
-GL_ENTRY(void, glFogx, GLenum, GLfixed)
-GL_ENTRY(void, glFogxv, GLenum, const GLfixed *)
-GL_ENTRY(void, glVertexPointer, GLint, GLenum, GLsizei, const GLvoid *)
-GL_ENTRY(void, glColorPointer, GLint, GLenum, GLsizei, const GLvoid *)
-GL_ENTRY(void, glNormalPointer, GLenum, GLsizei, const GLvoid *)
-GL_ENTRY(void, glTexCoordPointer, GLint, GLenum, GLsizei, const GLvoid *)
-GL_ENTRY(void, glEnableClientState, GLenum)
-GL_ENTRY(void, glDisableClientState, GLenum)
-GL_ENTRY(void, glClientActiveTexture, GLenum)
-GL_ENTRY(void, glDrawArrays, GLenum, GLint first, GLsizei)
-GL_ENTRY(void, glDrawElements, GLenum, GLsizei, GLenum, const GLvoid *)
 GL_ENTRY(void, glLoadIdentity, void)
-GL_ENTRY(void, glLoadMatrixf, const GLfloat*)
-GL_ENTRY(void, glLoadMatrixx, const GLfixed*)
+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, glMultMatrixf, const GLfloat*)
-GL_ENTRY(void, glMultMatrixx, const GLfixed*)
+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, glFrustumf, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat)
-GL_ENTRY(void, glFrustumx, GLfixed, GLfixed, GLfixed, GLfixed, GLfixed, GLfixed)
-GL_ENTRY(void, glOrthof, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat)
-GL_ENTRY(void, glOrthox, GLfixed, GLfixed, GLfixed, GLfixed, GLfixed, GLfixed)
-GL_ENTRY(void, glRotatef, GLfloat, GLfloat, GLfloat, GLfloat)
-GL_ENTRY(void, glRotatex, GLfixed, GLfixed, GLfixed, GLfixed)
-GL_ENTRY(void, glScalef, GLfloat, GLfloat, GLfloat)
-GL_ENTRY(void, glScalex, GLfixed, GLfixed, GLfixed)
-GL_ENTRY(void, glTranslatef, GLfloat, GLfloat, GLfloat)
-GL_ENTRY(void, glTranslatex, GLfixed, GLfixed, GLfixed)
-GL_ENTRY(void, glViewport, GLint, GLint, GLsizei, GLsizei)
-GL_ENTRY(void, glActiveTexture, GLenum)
-GL_ENTRY(void, glBindTexture, GLenum, GLuint)
-GL_ENTRY(void, glGenTextures, GLsizei, GLuint*)
-GL_ENTRY(void, glDeleteTextures, GLsizei n, const GLuint *)
-GL_ENTRY(void, glMultiTexCoord4f, GLenum, GLfloat, GLfloat, GLfloat, GLfloat)
-GL_ENTRY(void, glMultiTexCoord4x, GLenum, GLfixed, GLfixed, GLfixed, GLfixed)
-GL_ENTRY(void, glPixelStorei, GLenum, GLint)
-GL_ENTRY(void, glTexEnvf, GLenum, GLenum, GLfloat)
-GL_ENTRY(void, glTexEnvfv, GLenum, GLenum, const GLfloat*)
-GL_ENTRY(void, glTexEnvx, GLenum, GLenum, GLfixed)
-GL_ENTRY(void, glTexEnvxv, GLenum, GLenum, const GLfixed*)
-GL_ENTRY(void, glTexParameterf, GLenum, GLenum, GLfloat)
-GL_ENTRY(void, glTexParameterx, GLenum, GLenum, GLfixed)
-GL_ENTRY(void, glCompressedTexImage2D,    GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLsizei, const GLvoid*)
-GL_ENTRY(void, glCompressedTexSubImage2D, GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid*)
-GL_ENTRY(void, glCopyTexImage2D, GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLsizei, GLint)
-GL_ENTRY(void, glCopyTexSubImage2D, GLenum, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei)
-GL_ENTRY(void, glTexImage2D, GLenum, GLint, GLint, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid*)
-GL_ENTRY(void, glTexSubImage2D, GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const GLvoid*)
-GL_ENTRY(void, glReadPixels, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, GLvoid *)
-
-// 1.1 additions
-GL_ENTRY(void, glClipPlanef, GLenum plane, const GLfloat*)
-GL_ENTRY(void, glClipPlanex, GLenum plane, const GLfixed*)
-GL_ENTRY(void, glBindBuffer, GLenum, GLuint)
-GL_ENTRY(void, glBufferData, GLenum, GLsizeiptr, const GLvoid*, GLenum)
-GL_ENTRY(void, glBufferSubData, GLenum, GLintptr, GLsizeiptr, const GLvoid*)
-GL_ENTRY(void, glDeleteBuffers, GLsizei, const GLuint*)
-GL_ENTRY(void, glGenBuffers, GLsizei, GLuint*)
-GL_ENTRY(void, glGetBooleanv, GLenum, GLboolean *)
-GL_ENTRY(void, glGetFixedv, GLenum, GLfixed *)
-GL_ENTRY(void, glGetFloatv, GLenum, GLfloat *)
-GL_ENTRY(void, glGetPointerv, GLenum, void **)
-GL_ENTRY(void, glGetBufferParameteriv, GLenum, GLenum, GLint *)
-GL_ENTRY(void, glGetClipPlanef, GLenum, GLfloat[4])
-GL_ENTRY(void, glGetClipPlanex, GLenum, GLfixed[4])
-GL_ENTRY(void, glGetLightxv, GLenum, GLenum, GLfixed *)
-GL_ENTRY(void, glGetLightfv, GLenum, GLenum, GLfloat *)
-GL_ENTRY(void, glGetMaterialxv, GLenum, GLenum, GLfixed *)
-GL_ENTRY(void, glGetMaterialfv, GLenum, GLenum, GLfloat *)
-GL_ENTRY(void, glGetTexEnvfv, GLenum, GLenum, GLfloat *)
-GL_ENTRY(void, glGetTexEnviv, GLenum, GLenum, GLint *)
-GL_ENTRY(void, glGetTexEnvxv, GLenum, GLenum, GLfixed *)
-GL_ENTRY(void, glGetTexParameterfv, GLenum, GLenum, GLfloat *)
-GL_ENTRY(void, glGetTexParameteriv, GLenum, GLenum, GLint *)
-GL_ENTRY(void, glGetTexParameterxv, GLenum, GLenum, GLfixed *)
-GL_ENTRY(GLboolean, glIsBuffer, GLuint)
-GL_ENTRY(GLboolean, glIsEnabled, GLenum)
-GL_ENTRY(GLboolean, glIsTexture, GLuint)
-GL_ENTRY(void, glPointParameterf, GLenum, GLfloat)
-GL_ENTRY(void, glPointParameterfv, GLenum, const GLfloat *)
-GL_ENTRY(void, glPointParameterx, GLenum, GLfixed)
-GL_ENTRY(void, glPointParameterxv, GLenum, const GLfixed *)
-GL_ENTRY(void, glColor4ub, GLubyte, GLubyte, GLubyte, GLubyte)
-GL_ENTRY(void, glTexEnvi, GLenum, GLenum, GLint)
-GL_ENTRY(void, glTexEnviv, GLenum, GLenum, const GLint *)
-GL_ENTRY(void, glTexParameterfv, GLenum, GLenum, const GLfloat *)
-GL_ENTRY(void, glTexParameteriv, GLenum, GLenum, const GLint *)
-GL_ENTRY(void, glTexParameteri, GLenum, GLenum, GLint)
-GL_ENTRY(void, glTexParameterxv, GLenum, GLenum, const GLfixed *)
-GL_ENTRY(void, glPointSizePointerOES, GLenum type, GLsizei stride, const GLvoid*)
-
-// Extensions
-GL_ENTRY(void, glDrawTexsOES, GLshort, GLshort, GLshort, GLshort, GLshort)
-GL_ENTRY(void, glDrawTexiOES, GLint, GLint, GLint, GLint, GLint)
-GL_ENTRY(void, glDrawTexfOES, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat)
-GL_ENTRY(void, glDrawTexxOES, GLfixed, GLfixed, GLfixed, GLfixed, GLfixed)
-GL_ENTRY(void, glDrawTexsvOES, const GLshort*)
-GL_ENTRY(void, glDrawTexivOES, const GLint*)
-GL_ENTRY(void, glDrawTexfvOES, const GLfloat*)
-GL_ENTRY(void, glDrawTexxvOES, const GLfixed*)
-GL_ENTRY(GLbitfield, glQueryMatrixxOES, GLfixed* mantissa, GLint* exponent)
-
+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_logger.h b/opengl/libs/gl_logger.h
deleted file mode 100644
index ce85dd1..0000000
--- a/opengl/libs/gl_logger.h
+++ /dev/null
@@ -1,26 +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.
- */
-
-#ifndef ANDROID_GL_LOGGER_H
-#define ANDROID_GL_LOGGER_H
-
-namespace android {
-#define GL_ENTRY(r, api, ...) r log_##api(__VA_ARGS__);
-#include "gl_entries.in"
-#undef GL_ENTRY
-}; // namespace android
-
-#endif /* ANDROID_GL_LOGGER_H */
diff --git a/opengl/libs/glext_entries.in b/opengl/libs/glext_entries.in
new file mode 100644
index 0000000..dd09c71
--- /dev/null
+++ b/opengl/libs/glext_entries.in
@@ -0,0 +1,90 @@
+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 63fb017..fd97254 100644
--- a/opengl/libs/hooks.h
+++ b/opengl/libs/hooks.h
@@ -22,9 +22,10 @@
 #include <errno.h>
 
 #include <EGL/egl.h>
+#include <EGL/eglext.h>
 #include <GLES/gl.h>
+#include <GLES/glext.h>
 
-#define GL_LOGGER                   0
 #if !defined(__arm__)
 #define USE_SLOW_BINDING            1
 #else
@@ -35,7 +36,7 @@
 #define MAX_NUMBER_OF_GL_EXTENSIONS 32
 
 
-#if defined(HAVE_ANDROID_OS) && !USE_SLOW_BINDING && !GL_LOGGER && __OPTIMIZE__
+#if defined(HAVE_ANDROID_OS) && !USE_SLOW_BINDING && __OPTIMIZE__
 #define USE_FAST_TLS_KEY            1
 #else
 #define USE_FAST_TLS_KEY            0
@@ -55,7 +56,10 @@
 enum {
     IMPL_HARDWARE = 0,
     IMPL_SOFTWARE,
-    IMPL_CONTEXT_LOST,
+    
+    IMPL_NUM_DRIVERS_IMPLEMENTATIONS,
+
+    IMPL_CONTEXT_LOST = IMPL_NUM_DRIVERS_IMPLEMENTATIONS,
     IMPL_NO_CONTEXT,
     
     IMPL_NUM_IMPLEMENTATIONS
@@ -73,6 +77,7 @@
 struct gl_hooks_t {
     struct gl_t {
         #include "gl_entries.in"
+        #include "glext_entries.in"
     } gl;
     struct egl_t {
         #include "egl_entries.in"
diff --git a/opengl/libs/tools/genfiles b/opengl/libs/tools/genfiles
new file mode 100755
index 0000000..107768b
--- /dev/null
+++ b/opengl/libs/tools/genfiles
@@ -0,0 +1,20 @@
+#! /bin/sh
+#
+# Copyright (C) 2008 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+./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 
diff --git a/opengl/libs/tools/glapigen b/opengl/libs/tools/glapigen
new file mode 100755
index 0000000..a2c3a7b
--- /dev/null
+++ b/opengl/libs/tools/glapigen
@@ -0,0 +1,72 @@
+#! /usr/bin/perl
+#
+# Copyright (C) 2008 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+use strict;
+
+while (my $line = <>) {
+  next if $line =~ /^\//;
+  next if $line =~ /^#/;
+  next if $line =~ /^\s*$/;
+  if ($line !~ /^GL_API\s+(.+)\s+GL_APIENTRY\s+([\w]+)\s*\(([^\)]+)\);/) {
+    next;
+  }
+  my $type = $1;
+  my $name = $2;
+  my $args = $3;
+
+  #printf("%s", $line);
+  
+  my $prefix = "";
+  if ($name eq "glEGLImageTargetTexture2DOES") {
+    $prefix = "__";
+  }
+  if ($name eq "glEGLImageTargetRenderbufferStorageOES") {
+    $prefix = "__";
+  }
+  
+  printf("%s API_ENTRY(%s%s)(%s)", $type, $prefix, $name, $args);
+  
+  printf(" {\n");
+  if ($type eq "void") {
+    printf("    CALL_GL_API(%s", $name);
+  } else {
+    printf("    CALL_GL_API_RETURN(%s", $name);
+  }
+  my @args = split ',', $args;
+  my $len = scalar(@args);
+  for (my $num = 0; $num < $len; $num++) {
+    if ($args[$num] ne "void") {
+      print ", ";
+      #
+      # extract the name from the parameter
+      # type name
+      # const type *name
+      # type *name
+      # type name[4]
+      #
+      if ($args[$num] =~ /(\S+\s)+\**\s*([\w]+)/) {
+        printf("%s", $2);
+      }
+    }
+  }
+  printf(");\n");
+  printf("}\n");
+}
+
+
+
+
+
diff --git a/opengl/libs/tools/glentrygen b/opengl/libs/tools/glentrygen
new file mode 100755
index 0000000..5e0f7b6
--- /dev/null
+++ b/opengl/libs/tools/glentrygen
@@ -0,0 +1,31 @@
+#! /usr/bin/perl
+#
+# Copyright (C) 2008 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+use strict;
+
+while (my $line = <>) {
+  next if $line =~ /^\//;
+  next if $line =~ /^#/;
+  next if $line =~ /^\s*$/;
+  if ($line !~ /^GL_API\s+(.+)\s+GL_APIENTRY\s+([\w]+)\s*\(([^\)]+)\);/) {
+    next;
+  }
+  my $type = $1;
+  my $name = $2;
+  my $args = $3;
+
+  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 46958d3..e193483 100644
--- a/opengl/tests/angeles/Android.mk
+++ b/opengl/tests/angeles/Android.mk
@@ -5,7 +5,7 @@
 LOCAL_SRC_FILES:= app-linux.c demo.c.arm
 LOCAL_SHARED_LIBRARIES := libEGL libGLESv1_CM libui
 LOCAL_MODULE:= angeles
-LOCAL_MODULE_TAGS := tests
+LOCAL_MODULE_TAGS := optional
 include $(BUILD_EXECUTABLE)
 
 
@@ -13,5 +13,5 @@
 LOCAL_SRC_FILES:= gpustate.c
 LOCAL_SHARED_LIBRARIES := libEGL libGLESv1_CM
 LOCAL_MODULE:= gpustate
-LOCAL_MODULE_TAGS := tests
+LOCAL_MODULE_TAGS := optional
 include $(BUILD_EXECUTABLE)
diff --git a/opengl/tests/filter/Android.mk b/opengl/tests/filter/Android.mk
index a448f0d..31b7d9a 100644
--- a/opengl/tests/filter/Android.mk
+++ b/opengl/tests/filter/Android.mk
@@ -12,6 +12,6 @@
 
 LOCAL_MODULE:= test-opengl-filter
 
-LOCAL_MODULE_TAGS := tests
+LOCAL_MODULE_TAGS := optional
 
 include $(BUILD_EXECUTABLE)
diff --git a/opengl/tests/finish/Android.mk b/opengl/tests/finish/Android.mk
index 26836c1..8b46cd7 100644
--- a/opengl/tests/finish/Android.mk
+++ b/opengl/tests/finish/Android.mk
@@ -12,6 +12,6 @@
 
 LOCAL_MODULE:= test-opengl-finish
 
-LOCAL_MODULE_TAGS := tests
+LOCAL_MODULE_TAGS := optional
 
 include $(BUILD_EXECUTABLE)
diff --git a/opengl/tests/lighting1709/Android.mk b/opengl/tests/lighting1709/Android.mk
new file mode 100644
index 0000000..9563e61
--- /dev/null
+++ b/opengl/tests/lighting1709/Android.mk
@@ -0,0 +1,11 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := LightingTest
+LOCAL_CERTIFICATE := platform
+
+include $(BUILD_PACKAGE)
diff --git a/opengl/tests/lighting1709/AndroidManifest.xml b/opengl/tests/lighting1709/AndroidManifest.xml
new file mode 100644
index 0000000..6c23d42
--- /dev/null
+++ b/opengl/tests/lighting1709/AndroidManifest.xml
@@ -0,0 +1,13 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.lightingtest">
+
+    <application>
+        <activity android:name="ClearActivity" android:label="LightingTest">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/opengl/tests/lighting1709/src/com/android/lightingtest/ClearActivity.java b/opengl/tests/lighting1709/src/com/android/lightingtest/ClearActivity.java
new file mode 100644
index 0000000..3ae8c5c
--- /dev/null
+++ b/opengl/tests/lighting1709/src/com/android/lightingtest/ClearActivity.java
@@ -0,0 +1,174 @@
+/*
+ * 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.lightingtest;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+
+import javax.microedition.khronos.egl.EGL10;
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+import android.app.Activity;
+import android.content.Context;
+import android.opengl.GLSurfaceView;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.MotionEvent;
+
+public class ClearActivity extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mGLView = new ClearGLSurfaceView(this);
+        setContentView(mGLView);
+    }
+
+    @Override
+    protected void onPause() {
+        super.onPause();
+        mGLView.onPause();
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        mGLView.onResume();
+    }
+    private GLSurfaceView mGLView;
+}
+
+class ClearGLSurfaceView extends GLSurfaceView {
+    public ClearGLSurfaceView(Context context) {
+        super(context);
+        mRenderer = new ClearRenderer();
+        setRenderer(mRenderer);
+    }
+
+    ClearRenderer mRenderer;
+}
+
+class ClearRenderer implements GLSurfaceView.Renderer {
+    public ClearRenderer() {
+    }
+
+    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
+        // Do nothing special.
+    }
+
+    public void onSurfaceChanged(GL10 gl, int w, int h) {
+        // Compute the projection matrix
+        gl.glMatrixMode(GL10.GL_PROJECTION);
+        gl.glLoadIdentity();
+
+        // Compute the boundaries of the frustum
+        float fl = (float) (-(w / 2)) / 288;
+        float fr = (float) (w / 2) / 288;
+        float ft = (float) (h / 2) / 288;
+        float fb = (float) (-(h / 2)) / 288;
+
+        // Set the view frustum
+        gl.glFrustumf(fl, fr, fb, ft, 1.0f, 2000.0f);
+
+        // Set the viewport dimensions
+        gl.glMatrixMode(GL10.GL_MODELVIEW);
+        gl.glLoadIdentity();
+        gl.glViewport(0, 0, w, h);
+    }
+
+    public void onDrawFrame(GL10 gl) {
+        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
+
+        final float lightOff[]        = {0.0f, 0.0f,  0.0f, 1.0f};
+        final float lightAmbient[]    = {5.0f, 0.0f,  0.0f, 1.0f};
+        final float lightDiffuse[]    = {0.0f, 2.0f,  0.0f, 0.0f};
+        final float lightPosSpot[]    = {0.0f, 0.0f, -8.0f, 1.0f};
+
+        final float pos[] = {
+                    -5.0f, -1.5f, 0.0f,
+                     0.0f, -1.5f, 0.0f,
+                     5.0f, -1.5f, 0.0f,
+                };
+        
+        final float v[] = new float[9];
+        ByteBuffer vbb = ByteBuffer.allocateDirect(v.length*4);
+        vbb.order(ByteOrder.nativeOrder());
+        FloatBuffer vb = vbb.asFloatBuffer();
+
+        gl.glDisable(GL10.GL_DITHER);
+
+        gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_AMBIENT, lightAmbient, 0);
+        gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_DIFFUSE, lightDiffuse, 0);
+        gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_SPECULAR, lightOff, 0);
+        gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, lightPosSpot, 0);
+        gl.glEnable(GL10.GL_LIGHT0);
+        
+        gl.glEnable(GL10.GL_LIGHTING);
+
+
+        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
+        gl.glNormal3f(0, 0, 1);
+        
+
+        // draw first 3 triangles, without using transforms
+        for (int i=0 ; i<3 ; i++) {
+            v[0] = -1; v[1] =-1; v[2] = -10;
+            v[3] =  0; v[4] = 1; v[5] = -10;
+            v[6] =  1; v[7] =-1; v[8] = -10;
+            for (int j=0 ; j<3 ; j++) {
+                v[j*3+0] -= pos[i*3+0];
+                v[j*3+1] -= pos[i*3+1];
+                v[j*3+2] -= pos[i*3+2];
+            }
+            vb.put(v).position(0);
+            gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vb);
+            gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 3);
+        }
+        
+        // draw the 2nd batch this time with transforms
+        v[0] = -1; v[1] =-1; v[2] = -10;
+        v[3] =  0; v[4] = 1; v[5] = -10;
+        v[6] =  1; v[7] =-1; v[8] = -10;
+        vb.put(v).position(0);
+        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vb);
+
+        // draw lower left triangle
+        gl.glPushMatrix();
+        gl.glTranslatef(pos[0], pos[1], pos[2]);
+        gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 3);
+        gl.glPopMatrix();
+
+        // draw lower middle triangle
+        gl.glPushMatrix();
+        gl.glTranslatef(pos[3], pos[4], pos[5]);
+        gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 3);
+        gl.glPopMatrix();
+
+        // draw lower right triangle
+        gl.glPushMatrix();
+        gl.glTranslatef(pos[6], pos[7], pos[8]);
+        gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 3);
+        gl.glPopMatrix();      
+    }
+
+    public int[] getConfigSpec() {
+        int[] configSpec = { EGL10.EGL_DEPTH_SIZE, 16, EGL10.EGL_NONE };
+        return configSpec;      
+    }
+}
+
diff --git a/opengl/tests/textures/Android.mk b/opengl/tests/textures/Android.mk
index a8c6220..8d5f56d 100644
--- a/opengl/tests/textures/Android.mk
+++ b/opengl/tests/textures/Android.mk
@@ -12,6 +12,6 @@
 
 LOCAL_MODULE:= test-opengl-textures
 
-LOCAL_MODULE_TAGS := tests
+LOCAL_MODULE_TAGS := optional
 
 include $(BUILD_EXECUTABLE)
diff --git a/opengl/tests/tritex/Android.mk b/opengl/tests/tritex/Android.mk
index 5cd1f04..76fd8dd 100644
--- a/opengl/tests/tritex/Android.mk
+++ b/opengl/tests/tritex/Android.mk
@@ -12,6 +12,6 @@
 
 LOCAL_MODULE:= test-opengl-tritex
 
-LOCAL_MODULE_TAGS := tests
+LOCAL_MODULE_TAGS := optional
 
 include $(BUILD_EXECUTABLE)
diff --git a/opengl/tools/glgen/.gitignore b/opengl/tools/glgen/.gitignore
new file mode 100644
index 0000000..007ec65
--- /dev/null
+++ b/opengl/tools/glgen/.gitignore
@@ -0,0 +1,2 @@
+generated
+out
diff --git a/opengl/tools/glgen/gen b/opengl/tools/glgen/gen
index 1c49861..9bff0b2 100755
--- a/opengl/tools/glgen/gen
+++ b/opengl/tools/glgen/gen
@@ -1,28 +1,75 @@
-#!/bin/sh
+#!/bin/bash
+set -u
+set -e
 rm -rf out generated
 
 mkdir out
+
+# Create dummy Java files for Android APIs that are used by the code we generate.
+# This allows us to test the generated code without building the rest of Android.
+
 mkdir -p out/javax/microedition/khronos/opengles
 mkdir -p out/com/google/android/gles_jni
+mkdir -p out/android/app
 mkdir -p out/android/graphics
+mkdir -p out/android/opengl
+mkdir -p out/android/content
+mkdir -p out/android/content/pm
+mkdir -p out/android/os
+mkdir -p out/android/util
 
 echo "package android.graphics;" > out/android/graphics/Canvas.java
 echo "public interface Canvas {}" >> out/android/graphics/Canvas.java
 
-GLFILE=out/javax/microedition/khronos/opengles/GL.java
-cp stubs/GLHeader.java-if $GLFILE
+echo "package android.app; import android.content.pm.IPackageManager; public class ActivityThread { public static final ActivityThread currentActivityThread() { return null; } public static final String currentPackageName(){ return null; } public static IPackageManager getPackageManager() { return null;} }" > out/android/app/ActivityThread.java
+# echo "package android.content; import android.content.pm.PackageManager; public interface Context { public PackageManager getPackageManager(); }" > out/android/content/Context.java
+echo "package android.content.pm; public class ApplicationInfo {public int targetSdkVersion;}" > out/android/content/pm/ApplicationInfo.java
+echo "package android.content.pm; public interface IPackageManager {ApplicationInfo getApplicationInfo(java.lang.String packageName, int flags) throws android.os.RemoteException;}" > out/android/content/pm/IPackageManager.java
+echo "package android.os; public class Build {public static class VERSION_CODES { public static final int CUPCAKE = 3;};	}" > out/android/os/Build.java
+echo "package android.os; public class RemoteException extends Exception {}" > out/android/os/RemoteException.java
+echo "package android.util; public class Log {public static void w(String a, String b) {} public static void e(String a, String b) {}}" > out/android/util/Log.java
 
-GLGEN_FILES="CFunc.java CType.java CodeEmitter.java GenerateGL.java JFunc.java JType.java JniCodeEmitter.java ParameterChecker.java"
+GLFILE=out/javax/microedition/khronos/opengles/GL.java
+cp stubs/jsr239/GLHeader.java-if $GLFILE
+
+GLGEN_FILES="CFunc.java CType.java CodeEmitter.java GenerateGL.java GenerateGLES.java GLESCodeEmitter.java JFunc.java JniCodeEmitter.java JType.java Jsr239CodeEmitter.java ParameterChecker.java"
 
 pushd src > /dev/null
 javac ${GLGEN_FILES}
+JAVAC_RESULT=$?
+if [ $JAVAC_RESULT -ne 0 ]; then
+    echo "Could not compile glgen."
+    exit $JAVAC_RESULT
+fi
 popd > /dev/null
-java -classpath src GenerateGL -c glspec-1.0 glspec-1.0ext glspec-1.1 glspec-1.1ext glspec-1.1extpack glspec-checks
+
+echo "Generating JSR239-like APIs"
+java -classpath src GenerateGL -c specs/jsr239/glspec-1.0 specs/jsr239/glspec-1.0ext specs/jsr239/glspec-1.1 specs/jsr239/glspec-1.1ext specs/jsr239/glspec-1.1extpack specs/jsr239/glspec-checks
+JAVA_RESULT=$?
+if [ $JAVA_RESULT -ne 0 ]; then
+    echo "Could not run GenerateGL."
+    exit $JAVA_RESULT
+fi
+
+echo "Generating static OpenGLES 1.1 bindings"
+java -classpath src GenerateGLES
+JAVA_RESULT=$?
+if [ $JAVA_RESULT -ne 0 ]; then
+    echo "Could not run GenerateGLES."
+    exit $JAVA_RESULT
+fi
+
+rm src/*.class
 
 pushd out > /dev/null
 mkdir classes
-javac -d classes com/google/android/gles_jni/GLImpl.java javax/microedition/khronos/opengles/GL10.java javax/microedition/khronos/opengles/GL10Ext.java javax/microedition/khronos/opengles/GL11.java javax/microedition/khronos/opengles/GL11Ext.java javax/microedition/khronos/opengles/GL11ExtensionPack.java
+javac -d classes com/google/android/gles_jni/GLImpl.java javax/microedition/khronos/opengles/GL10.java javax/microedition/khronos/opengles/GL10Ext.java javax/microedition/khronos/opengles/GL11.java javax/microedition/khronos/opengles/GL11Ext.java javax/microedition/khronos/opengles/GL11ExtensionPack.java android/opengl/GLES10.java android/opengl/GLES10Ext.java android/opengl/GLES11.java android/opengl/GLES11Ext.java
 popd > /dev/null
+JAVA_RESULT=$?
+if [ $JAVA_RESULT -ne 0 ]; then
+    echo "Could not compile generated classes."
+    exit $JAVA_RESULT
+fi
 
 rm -rf generated
 mkdir -p generated/C
@@ -30,70 +77,44 @@
 cp -r out/com generated
 cp -r out/javax generated
 
+cp out/android_opengl_*.cpp generated/C
+mkdir -p generated/android/opengl
+cp -r out/android/opengl generated/android
+
 rm -rf out
+KEEP_GENERATED=0
+SAID_PLEASE=0
 
-# com_google_android_gles_jni_GLImpl.cpp
-if cmp ../../../frameworks/base/core/jni/com_google_android_gles_jni_GLImpl.cpp generated/C/com_google_android_gles_jni_GLImpl.cpp ; then
-echo com_google_android_gles_jni_GLImpl.cpp unchanged
-else
-echo Please edit ../../../frameworks/base/core/jni/com_google_android_gles_jni_GLImpl.cpp
-echo Please cp generated/C/com_google_android_gles_jni_GLImpl.cpp ../../../frameworks/base/core/jni
+# compareGenerated destDir generatedDir file
+compareGenerated() {
+    if cmp -s $1/$3 $2/$3 ; then
+        echo "#    " $3 unchanged
+    else
+        if [ $SAID_PLEASE == "0" ] ; then
+            echo Please evaluate the following commands:
+            echo
+            SAID_PLEASE=1
+        fi
+        echo "    " cp $2/$3 $1
+        echo "    " git add $1/$3
+        KEEP_GENERATED=1
+    fi
+}
+
+compareGenerated ../../../core/jni generated/C com_google_android_gles_jni_GLImpl.cpp
+compareGenerated ../../java/com/google/android/gles_jni generated/com/google/android/gles_jni GLImpl.java
+
+for x in GL.java GL10.java GL10Ext.java GL11.java GL11Ext.java GL11ExtensionPack.java
+do
+    compareGenerated ../../java/javax/microedition/khronos/opengles generated/javax/microedition/khronos/opengles $x
+done
+
+for x in GLES10 GLES10Ext GLES11 GLES11Ext
+do
+    compareGenerated ../../java/android/opengl generated/android/opengl ${x}.java
+    compareGenerated ../../../core/jni generated/C android_opengl_${x}.cpp
+done
+
+if [ $KEEP_GENERATED == "0" ] ; then
+    rm -rf generated
 fi
-
-# GLImpl.java
-if cmp ../../java/com/google/android/gles_jni/GLImpl.java generated/com/google/android/gles_jni/GLImpl.java ; then
-echo GLImpl.java unchanged
-else
-echo Please edit ../../java/com/google/android/gles_jni/GLImpl.java
-echo Please cp generated/com/google/android/gles_jni/GLImpl.java ../../java/com/google/android/gles_jni
-fi
-
-# GL.java
-if cmp ../../java/javax/microedition/khronos/opengles/GL.java generated/javax/microedition/khronos/opengles/GL.java ; then
-echo GL.java unchanged
-else
-echo Please edit ../../java/javax/microedition/khronos/opengles/GL.java
-echo Please cp generated/javax/microedition/khronos/opengles/GL.java ../../java/javax/microedition/khronos/opengles/GL.java
-fi
-
-# GL10.java
-if cmp ../../java/javax/microedition/khronos/opengles/GL10.java generated/javax/microedition/khronos/opengles/GL10.java ; then
-echo GL10.java unchanged
-else
-echo Please edit ../../java/javax/microedition/khronos/opengles/GL10.java
-echo Please cp generated/javax/microedition/khronos/opengles/GL10.java ../../java/javax/microedition/khronos/opengles/GL10.java
-fi
-
-# GL10Ext.java
-if cmp ../../java/javax/microedition/khronos/opengles/GL10Ext.java generated/javax/microedition/khronos/opengles/GL10Ext.java ; then
-echo GL10Ext.java unchanged
-else
-echo Please edit ../../java/javax/microedition/khronos/opengles/GL10Ext.java
-echo Please cp generated/javax/microedition/khronos/opengles/GL10Ext.java ../../java/javax/microedition/khronos/opengles/GL10Ext.java
-fi
-
-# GL11.java
-if cmp ../../java/javax/microedition/khronos/opengles/GL11.java generated/javax/microedition/khronos/opengles/GL11.java ; then
-echo GL11.java unchanged
-else
-echo Please edit ../../java/javax/microedition/khronos/opengles/GL11.java
-echo Please cp generated/javax/microedition/khronos/opengles/GL11.java ../../java/javax/microedition/khronos/opengles/GL11.java
-fi
-
-# GL11Ext.java
-if cmp ../../java/javax/microedition/khronos/opengles/GL11Ext.java generated/javax/microedition/khronos/opengles/GL11Ext.java ; then
-echo GL11Ext.java unchanged
-else
-echo Please edit ../../java/javax/microedition/khronos/opengles/GL11Ext.java
-echo Please cp generated/javax/microedition/khronos/opengles/GL11Ext.java ../../java/javax/microedition/khronos/opengles/GL11Ext.java
-fi
-
-# GL11ExtensionPack.java
-if cmp ../../java/javax/microedition/khronos/opengles/GL11ExtensionPack.java generated/javax/microedition/khronos/opengles/GL11ExtensionPack.java ; then
-echo GL11ExtensionPack.java unchanged
-else
-echo Please edit ../../java/javax/microedition/khronos/opengles/GL11ExtensionPack.java
-echo Please cp generated/javax/microedition/khronos/opengles/GL11ExtensionPack.java ../../java/javax/microedition/khronos/opengles/GL11ExtensionPack.java
-fi
-
-rm -rf generated
diff --git a/opengl/tools/glgen/specs/gles11/GLES10.spec b/opengl/tools/glgen/specs/gles11/GLES10.spec
new file mode 100644
index 0000000..8e1152d
--- /dev/null
+++ b/opengl/tools/glgen/specs/gles11/GLES10.spec
@@ -0,0 +1,106 @@
+void glActiveTexture ( GLenum texture )
+void glAlphaFunc ( GLenum func, GLclampf ref )
+void glAlphaFuncx ( GLenum func, GLclampx ref )
+void glBindTexture ( GLenum target, GLuint texture )
+void glBlendFunc ( GLenum sfactor, GLenum dfactor )
+void glClear ( GLbitfield mask )
+void glClearColor ( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha )
+void glClearColorx ( GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha )
+void glClearDepthf ( GLclampf depth )
+void glClearDepthx ( GLclampx depth )
+void glClearStencil ( GLint s )
+void glClientActiveTexture ( GLenum texture )
+void glColor4f ( GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha )
+void glColor4x ( GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha )
+void glColorMask ( GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha )
+void glColorPointer ( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer )
+void glCompressedTexImage2D ( GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data )
+void glCompressedTexSubImage2D ( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data )
+void glCopyTexImage2D ( GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border )
+void glCopyTexSubImage2D ( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height )
+void glCullFace ( GLenum mode )
+void glDeleteTextures ( GLsizei n, const GLuint *textures )
+void glDepthFunc ( GLenum func )
+void glDepthMask ( GLboolean flag )
+void glDepthRangef ( GLclampf zNear, GLclampf zFar )
+void glDepthRangex ( GLclampx zNear, GLclampx zFar )
+void glDisable ( GLenum cap )
+void glDisableClientState ( GLenum array )
+void glDrawArrays ( GLenum mode, GLint first, GLsizei count )
+void glDrawElements ( GLenum mode, GLsizei count, GLenum type, const GLvoid *indices )
+void glEnable ( GLenum cap )
+void glEnableClientState ( GLenum array )
+void glFinish ( void )
+void glFlush ( void )
+void glFogf ( GLenum pname, GLfloat param )
+void glFogfv ( GLenum pname, const GLfloat *params )
+void glFogx ( GLenum pname, GLfixed param )
+void glFogxv ( GLenum pname, const GLfixed *params )
+void glFrontFace ( GLenum mode )
+void glFrustumf ( GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar )
+void glFrustumx ( GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar )
+void glGenTextures ( GLsizei n, GLuint *textures )
+GLenum glGetError ( void )
+void glGetIntegerv ( GLenum pname, GLint *params )
+const GLubyte * glGetString ( GLenum name )
+void glHint ( GLenum target, GLenum mode )
+void glLightModelf ( GLenum pname, GLfloat param )
+void glLightModelfv ( GLenum pname, const GLfloat *params )
+void glLightModelx ( GLenum pname, GLfixed param )
+void glLightModelxv ( GLenum pname, const GLfixed *params )
+void glLightf ( GLenum light, GLenum pname, GLfloat param )
+void glLightfv ( GLenum light, GLenum pname, const GLfloat *params )
+void glLightx ( GLenum light, GLenum pname, GLfixed param )
+void glLightxv ( GLenum light, GLenum pname, const GLfixed *params )
+void glLineWidth ( GLfloat width )
+void glLineWidthx ( GLfixed width )
+void glLoadIdentity ( void )
+void glLoadMatrixf ( const GLfloat *m )
+void glLoadMatrixx ( const GLfixed *m )
+void glLogicOp ( GLenum opcode )
+void glMaterialf ( GLenum face, GLenum pname, GLfloat param )
+void glMaterialfv ( GLenum face, GLenum pname, const GLfloat *params )
+void glMaterialx ( GLenum face, GLenum pname, GLfixed param )
+void glMaterialxv ( GLenum face, GLenum pname, const GLfixed *params )
+void glMatrixMode ( GLenum mode )
+void glMultMatrixf ( const GLfloat *m )
+void glMultMatrixx ( const GLfixed *m )
+void glMultiTexCoord4f ( GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q )
+void glMultiTexCoord4x ( GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q )
+void glNormal3f ( GLfloat nx, GLfloat ny, GLfloat nz )
+void glNormal3x ( GLfixed nx, GLfixed ny, GLfixed nz )
+void glNormalPointer ( GLenum type, GLsizei stride, const GLvoid *pointer )
+void glOrthof ( GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar )
+void glOrthox ( GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar )
+void glPixelStorei ( GLenum pname, GLint param )
+void glPointSize ( GLfloat size )
+void glPointSizex ( GLfixed size )
+void glPolygonOffset ( GLfloat factor, GLfloat units )
+void glPolygonOffsetx ( GLfixed factor, GLfixed units )
+void glPopMatrix ( void )
+void glPushMatrix ( void )
+void glReadPixels ( GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels )
+void glRotatef ( GLfloat angle, GLfloat x, GLfloat y, GLfloat z )
+void glRotatex ( GLfixed angle, GLfixed x, GLfixed y, GLfixed z )
+void glSampleCoverage ( GLclampf value, GLboolean invert )
+void glSampleCoveragex ( GLclampx value, GLboolean invert )
+void glScalef ( GLfloat x, GLfloat y, GLfloat z )
+void glScalex ( GLfixed x, GLfixed y, GLfixed z )
+void glScissor ( GLint x, GLint y, GLsizei width, GLsizei height )
+void glShadeModel ( GLenum mode )
+void glStencilFunc ( GLenum func, GLint ref, GLuint mask )
+void glStencilMask ( GLuint mask )
+void glStencilOp ( GLenum fail, GLenum zfail, GLenum zpass )
+void glTexCoordPointer ( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer )
+void glTexEnvf ( GLenum target, GLenum pname, GLfloat param )
+void glTexEnvfv ( GLenum target, GLenum pname, const GLfloat *params )
+void glTexEnvx ( GLenum target, GLenum pname, GLfixed param )
+void glTexEnvxv ( GLenum target, GLenum pname, const GLfixed *params )
+void glTexImage2D ( GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels )
+void glTexParameterf ( GLenum target, GLenum pname, GLfloat param )
+void glTexParameterx ( GLenum target, GLenum pname, GLfixed param )
+void glTexSubImage2D ( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels )
+void glTranslatef ( GLfloat x, GLfloat y, GLfloat z )
+void glTranslatex ( GLfixed x, GLfixed y, GLfixed z )
+void glVertexPointer ( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer )
+void glViewport ( GLint x, GLint y, GLsizei width, GLsizei height )
diff --git a/opengl/tools/glgen/specs/gles11/GLES10Ext.spec b/opengl/tools/glgen/specs/gles11/GLES10Ext.spec
new file mode 100644
index 0000000..53f6c65
--- /dev/null
+++ b/opengl/tools/glgen/specs/gles11/GLES10Ext.spec
@@ -0,0 +1 @@
+GLbitfield glQueryMatrixxOES ( GLfixed *mantissa, GLint *exponent )
diff --git a/opengl/tools/glgen/specs/gles11/GLES11.spec b/opengl/tools/glgen/specs/gles11/GLES11.spec
new file mode 100644
index 0000000..5527c18
--- /dev/null
+++ b/opengl/tools/glgen/specs/gles11/GLES11.spec
@@ -0,0 +1,44 @@
+void glBindBuffer ( GLenum target, GLuint buffer )
+void glBufferData ( GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage )
+void glBufferSubData ( GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data )
+void glClipPlanef ( GLenum plane, const GLfloat *equation )
+void glClipPlanex ( GLenum plane, const GLfixed *equation )
+void glColor4ub ( GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha )
+void glColorPointer ( GLint size, GLenum type, GLsizei stride, GLint offset )
+void glDeleteBuffers ( GLsizei n, const GLuint *buffers )
+void glDrawElements ( GLenum mode, GLsizei count, GLenum type, GLint offset )
+void glGenBuffers ( GLsizei n, GLuint *buffers )
+void glGetBooleanv ( GLenum pname, GLboolean *params )
+void glGetBufferParameteriv ( GLenum target, GLenum pname, GLint *params )
+void glGetClipPlanef ( GLenum pname, GLfloat *eqn )
+void glGetClipPlanex ( GLenum pname, GLfixed *eqn )
+void glGetFixedv ( GLenum pname, GLfixed *params )
+void glGetFloatv ( GLenum pname, GLfloat *params )
+void glGetLightfv ( GLenum light, GLenum pname, GLfloat *params )
+void glGetLightxv ( GLenum light, GLenum pname, GLfixed *params )
+void glGetMaterialfv ( GLenum face, GLenum pname, GLfloat *params )
+void glGetMaterialxv ( GLenum face, GLenum pname, GLfixed *params )
+// void glGetPointerv ( GLenum pname, void **params )
+void glGetTexEnvfv ( GLenum env, GLenum pname, GLfloat *params )
+void glGetTexEnviv ( GLenum env, GLenum pname, GLint *params )
+void glGetTexEnvxv ( GLenum env, GLenum pname, GLfixed *params )
+void glGetTexParameterfv ( GLenum target, GLenum pname, GLfloat *params )
+void glGetTexParameteriv ( GLenum target, GLenum pname, GLint *params )
+void glGetTexParameterxv ( GLenum target, GLenum pname, GLfixed *params )
+GLboolean glIsBuffer ( GLuint buffer )
+GLboolean glIsEnabled ( GLenum cap )
+GLboolean glIsTexture ( GLuint texture )
+void glNormalPointer ( GLenum type, GLsizei stride, GLint offset )
+void glPointParameterf ( GLenum pname, GLfloat param )
+void glPointParameterfv ( GLenum pname, const GLfloat *params )
+void glPointParameterx ( GLenum pname, GLfixed param )
+void glPointParameterxv ( GLenum pname, const GLfixed *params )
+void glPointSizePointerOES ( GLenum type, GLsizei stride, const GLvoid *pointer )
+void glTexCoordPointer ( GLint size, GLenum type, GLsizei stride, GLint offset )
+void glTexEnvi ( GLenum target, GLenum pname, GLint param )
+void glTexEnviv ( GLenum target, GLenum pname, const GLint *params )
+void glTexParameterfv ( GLenum target, GLenum pname, const GLfloat *params )
+void glTexParameteri ( GLenum target, GLenum pname, GLint param )
+void glTexParameteriv ( GLenum target, GLenum pname, const GLint *params )
+void glTexParameterxv ( GLenum target, GLenum pname, const GLfixed *params )
+void glVertexPointer ( GLint size, GLenum type, GLsizei stride, GLint offset )
diff --git a/opengl/tools/glgen/specs/gles11/GLES11Ext.spec b/opengl/tools/glgen/specs/gles11/GLES11Ext.spec
new file mode 100644
index 0000000..cd7333a
--- /dev/null
+++ b/opengl/tools/glgen/specs/gles11/GLES11Ext.spec
@@ -0,0 +1,90 @@
+void glBlendEquationSeparateOES ( GLenum modeRGB, GLenum modeAlpha )
+void glBlendFuncSeparateOES ( GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha )
+void glBlendEquationOES ( GLenum mode )
+void glDrawTexsOES ( GLshort x, GLshort y, GLshort z, GLshort width, GLshort height )
+void glDrawTexiOES ( GLint x, GLint y, GLint z, GLint width, GLint height )
+void glDrawTexxOES ( GLfixed x, GLfixed y, GLfixed z, GLfixed width, GLfixed height )
+void glDrawTexsvOES ( const GLshort *coords )
+void glDrawTexivOES ( const GLint *coords )
+void glDrawTexxvOES ( const GLfixed *coords )
+void glDrawTexfOES ( GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height )
+void glDrawTexfvOES ( const GLfloat *coords )
+void glEGLImageTargetTexture2DOES ( GLenum target, GLeglImageOES image )
+void glEGLImageTargetRenderbufferStorageOES ( GLenum target, GLeglImageOES image )
+void glAlphaFuncxOES ( GLenum func, GLclampx ref )
+void glClearColorxOES ( GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha )
+void glClearDepthxOES ( GLclampx depth )
+void glClipPlanexOES ( GLenum plane, const GLfixed *equation )
+void glColor4xOES ( GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha )
+void glDepthRangexOES ( GLclampx zNear, GLclampx zFar )
+void glFogxOES ( GLenum pname, GLfixed param )
+void glFogxvOES ( GLenum pname, const GLfixed *params )
+void glFrustumxOES ( GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar )
+void glGetClipPlanexOES ( GLenum pname, GLfixed *eqn )
+void glGetFixedvOES ( GLenum pname, GLfixed *params )
+void glGetLightxvOES ( GLenum light, GLenum pname, GLfixed *params )
+void glGetMaterialxvOES ( GLenum face, GLenum pname, GLfixed *params )
+void glGetTexEnvxvOES ( GLenum env, GLenum pname, GLfixed *params )
+void glGetTexParameterxvOES ( GLenum target, GLenum pname, GLfixed *params )
+void glLightModelxOES ( GLenum pname, GLfixed param )
+void glLightModelxvOES ( GLenum pname, const GLfixed *params )
+void glLightxOES ( GLenum light, GLenum pname, GLfixed param )
+void glLightxvOES ( GLenum light, GLenum pname, const GLfixed *params )
+void glLineWidthxOES ( GLfixed width )
+void glLoadMatrixxOES ( const GLfixed *m )
+void glMaterialxOES ( GLenum face, GLenum pname, GLfixed param )
+void glMaterialxvOES ( GLenum face, GLenum pname, const GLfixed *params )
+void glMultMatrixxOES ( const GLfixed *m )
+void glMultiTexCoord4xOES ( GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q )
+void glNormal3xOES ( GLfixed nx, GLfixed ny, GLfixed nz )
+void glOrthoxOES ( GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar )
+void glPointParameterxOES ( GLenum pname, GLfixed param )
+void glPointParameterxvOES ( GLenum pname, const GLfixed *params )
+void glPointSizexOES ( GLfixed size )
+void glPolygonOffsetxOES ( GLfixed factor, GLfixed units )
+void glRotatexOES ( GLfixed angle, GLfixed x, GLfixed y, GLfixed z )
+void glSampleCoveragexOES ( GLclampx value, GLboolean invert )
+void glScalexOES ( GLfixed x, GLfixed y, GLfixed z )
+void glTexEnvxOES ( GLenum target, GLenum pname, GLfixed param )
+void glTexEnvxvOES ( GLenum target, GLenum pname, const GLfixed *params )
+void glTexParameterxOES ( GLenum target, GLenum pname, GLfixed param )
+void glTexParameterxvOES ( GLenum target, GLenum pname, const GLfixed *params )
+void glTranslatexOES ( GLfixed x, GLfixed y, GLfixed z )
+GLboolean glIsRenderbufferOES ( GLuint renderbuffer )
+void glBindRenderbufferOES ( GLenum target, GLuint renderbuffer )
+void glDeleteRenderbuffersOES ( GLsizei n, const GLuint *renderbuffers )
+void glGenRenderbuffersOES ( GLsizei n, GLuint *renderbuffers )
+void glRenderbufferStorageOES ( GLenum target, GLenum internalformat, GLsizei width, GLsizei height )
+void glGetRenderbufferParameterivOES ( GLenum target, GLenum pname, GLint *params )
+GLboolean glIsFramebufferOES ( GLuint framebuffer )
+void glBindFramebufferOES ( GLenum target, GLuint framebuffer )
+void glDeleteFramebuffersOES ( GLsizei n, const GLuint *framebuffers )
+void glGenFramebuffersOES ( GLsizei n, GLuint *framebuffers )
+GLenum glCheckFramebufferStatusOES ( GLenum target )
+void glFramebufferRenderbufferOES ( GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer )
+void glFramebufferTexture2DOES ( GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level )
+void glGetFramebufferAttachmentParameterivOES ( GLenum target, GLenum attachment, GLenum pname, GLint *params )
+void glGenerateMipmapOES ( GLenum target )
+// Hard to export to Java:
+// void *glMapBufferOES ( GLenum target, GLenum access )
+// GLboolean glUnmapBufferOES ( GLenum target )
+// void glGetBufferPointervOES ( GLenum target, GLenum pname, void **params )
+void glCurrentPaletteMatrixOES ( GLuint matrixpaletteindex )
+void glLoadPaletteFromModelViewMatrixOES ( void )
+void glMatrixIndexPointerOES ( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer )
+void glWeightPointerOES ( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer )
+void glDepthRangefOES ( GLclampf zNear, GLclampf zFar )
+void glFrustumfOES ( GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar )
+void glOrthofOES ( GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar )
+void glClipPlanefOES ( GLenum plane, const GLfloat *equation )
+void glGetClipPlanefOES ( GLenum pname, GLfloat *eqn )
+void glClearDepthfOES ( GLclampf depth )
+void glTexGenfOES ( GLenum coord, GLenum pname, GLfloat param )
+void glTexGenfvOES ( GLenum coord, GLenum pname, const GLfloat *params )
+void glTexGeniOES ( GLenum coord, GLenum pname, GLint param )
+void glTexGenivOES ( GLenum coord, GLenum pname, const GLint *params )
+void glTexGenxOES ( GLenum coord, GLenum pname, GLfixed param )
+void glTexGenxvOES ( GLenum coord, GLenum pname, const GLfixed *params )
+void glGetTexGenfvOES ( GLenum coord, GLenum pname, GLfloat *params )
+void glGetTexGenivOES ( GLenum coord, GLenum pname, GLint *params )
+void glGetTexGenxvOES ( GLenum coord, GLenum pname, GLfixed *params )
diff --git a/opengl/tools/glgen/specs/gles11/checks.spec b/opengl/tools/glgen/specs/gles11/checks.spec
new file mode 100644
index 0000000..e31a2ce
--- /dev/null
+++ b/opengl/tools/glgen/specs/gles11/checks.spec
@@ -0,0 +1,61 @@
+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

diff --git a/opengl/tools/glgen/glspec-1.0 b/opengl/tools/glgen/specs/jsr239/glspec-1.0
similarity index 100%
rename from opengl/tools/glgen/glspec-1.0
rename to opengl/tools/glgen/specs/jsr239/glspec-1.0
diff --git a/opengl/tools/glgen/glspec-1.0ext b/opengl/tools/glgen/specs/jsr239/glspec-1.0ext
similarity index 100%
rename from opengl/tools/glgen/glspec-1.0ext
rename to opengl/tools/glgen/specs/jsr239/glspec-1.0ext
diff --git a/opengl/tools/glgen/glspec-1.1 b/opengl/tools/glgen/specs/jsr239/glspec-1.1
similarity index 100%
rename from opengl/tools/glgen/glspec-1.1
rename to opengl/tools/glgen/specs/jsr239/glspec-1.1
diff --git a/opengl/tools/glgen/glspec-1.1ext b/opengl/tools/glgen/specs/jsr239/glspec-1.1ext
similarity index 100%
rename from opengl/tools/glgen/glspec-1.1ext
rename to opengl/tools/glgen/specs/jsr239/glspec-1.1ext
diff --git a/opengl/tools/glgen/glspec-1.1extpack b/opengl/tools/glgen/specs/jsr239/glspec-1.1extpack
similarity index 100%
rename from opengl/tools/glgen/glspec-1.1extpack
rename to opengl/tools/glgen/specs/jsr239/glspec-1.1extpack
diff --git a/opengl/tools/glgen/glspec-checks b/opengl/tools/glgen/specs/jsr239/glspec-checks
similarity index 61%
rename from opengl/tools/glgen/glspec-checks
rename to opengl/tools/glgen/specs/jsr239/glspec-checks
index a84ed65..55840fa 100644
--- a/opengl/tools/glgen/glspec-checks
+++ b/opengl/tools/glgen/specs/jsr239/glspec-checks
@@ -7,7 +7,7 @@
 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_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_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 _NUM_COMPRESSED_TEXTURE_FORMATS pname GL_COMPRESSED_TEXTURE_FORMATS,GL_FOG_COLOR,GL_LIGHT_MODEL_AMBIENT

+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

diff --git a/opengl/tools/glgen/src/.gitignore b/opengl/tools/glgen/src/.gitignore
new file mode 100644
index 0000000..6b468b6
--- /dev/null
+++ b/opengl/tools/glgen/src/.gitignore
@@ -0,0 +1 @@
+*.class
diff --git a/opengl/tools/glgen/src/CFunc.java b/opengl/tools/glgen/src/CFunc.java
index 0794f41..a89e1c5 100644
--- a/opengl/tools/glgen/src/CFunc.java
+++ b/opengl/tools/glgen/src/CFunc.java
@@ -1,155 +1,156 @@
-

-import java.util.*;

-

-public class CFunc {

-

-    String original;

-

-    CType ftype;

-    String fname;

-

-    List<String> argNames = new ArrayList<String>();

-    List<CType> argTypes = new ArrayList<CType>();

-

-    boolean hasPointerArg = false;

-    boolean hasTypedPointerArg = false;

-

-    public CFunc(String original) {

-        this.original = original;

-    }

-

-    public String getOriginal() {

-        return original;

-    }

-

-    public void setName(String fname) {

-        this.fname = fname;

-    }

-

-    public String getName() {

-        return fname;

-    }

-

-    public void setType(CType ftype) {

-        this.ftype = ftype;

-    }

-

-    public CType getType() {

-        return ftype;

-    }

-

-    public void addArgument(String argName, CType argType) {

-        argNames.add(argName);

-        argTypes.add(argType);

-

-        if (argType.isPointer()) {

-            hasPointerArg = true;

-        }

-        if (argType.isTypedPointer()) {

-            hasTypedPointerArg = true;

-        }

-    }

-

-    public int getNumArgs() {

-        return argNames.size();

-    }

-

-    public int getArgIndex(String name) {

-        int len = argNames.size();

-        for (int i = 0; i < len; i++) {

-            if (name.equals(argNames.get(i))) {

-                return i;

-            }

-        }

-        return -1;

-    }

-

-    public String getArgName(int index) {

-        return argNames.get(index);

-    }

-

-    public CType getArgType(int index) {

-        return argTypes.get(index);

-    }

-

-    public boolean hasPointerArg() {

-        return hasPointerArg;

-    }

-

-    public boolean hasTypedPointerArg() {

-        return hasTypedPointerArg;

-    }

-

-    public String toString() {

-        String s =  "Function " + fname + " returns " + ftype + ": ";

-        for (int i = 0; i < argNames.size(); i++) {

-            if (i > 0) {

-                s += ", ";

-            }

-            s += argTypes.get(i) + " " + argNames.get(i);

-        }

-        return s;

-    }

-

-    public static CFunc parseCFunc(String s) {

-        CFunc cfunc = new CFunc(s);

-        String[] tokens = s.split("\\s");

-

-        int i = 0;

-        CType ftype = new CType();

-        String ftypeName = tokens[i++];

-        if (ftypeName.equals("const")) {

-            ftype.setIsConst(true);

-            ftypeName = tokens[i++];

-        }

-        ftype.setBaseType(ftypeName);

-

-        String fname = tokens[i++];

-        if (fname.equals("*")) {

-            ftype.setIsPointer(true);

-            fname = tokens[i++];

-        }

-	

-        cfunc.setName(fname);

-        cfunc.setType(ftype);

-	

-        while (i < tokens.length) {

-            String tok = tokens[i++];

-	    

-            if (tok.equals("(")) {

-                continue;

-            }

-            if (tok.equals(")")) {

-                break;

-            }

-

-            CType argType = new CType();

-	    

-            String argTypeName = tok;

-            String argName = "";

-	    

-            if (argTypeName.equals("const")) {

-                argType.setIsConst(true);

-                argTypeName = tokens[i++];

-            }

-            argType.setBaseType(argTypeName);

-

-            if (argTypeName.equals("void")) {

-                break;

-            }

-	    

-            argName = tokens[i++];

-            if (argName.startsWith("*")) {

-                argType.setIsPointer(true);

-                argName = argName.substring(1, argName.length());

-            }

-            if (argName.endsWith(",")) {

-                argName = argName.substring(0, argName.length() - 1);

-            }

-	    

-            cfunc.addArgument(argName, argType);

-        }

-

-        return cfunc;

-    }

-}

+
+import java.util.*;
+
+public class CFunc {
+
+    String original;
+
+    CType ftype;
+    String fname;
+
+    List<String> argNames = new ArrayList<String>();
+    List<CType> argTypes = new ArrayList<CType>();
+
+    boolean hasPointerArg = false;
+    boolean hasTypedPointerArg = false;
+
+    public CFunc(String original) {
+        this.original = original;
+    }
+
+    public String getOriginal() {
+        return original;
+    }
+
+    public void setName(String fname) {
+        this.fname = fname;
+    }
+
+    public String getName() {
+        return fname;
+    }
+
+    public void setType(CType ftype) {
+        this.ftype = ftype;
+    }
+
+    public CType getType() {
+        return ftype;
+    }
+
+    public void addArgument(String argName, CType argType) {
+        argNames.add(argName);
+        argTypes.add(argType);
+
+        if (argType.isPointer()) {
+            hasPointerArg = true;
+        }
+        if (argType.isTypedPointer()) {
+            hasTypedPointerArg = true;
+        }
+    }
+
+    public int getNumArgs() {
+        return argNames.size();
+    }
+
+    public int getArgIndex(String name) {
+        int len = argNames.size();
+        for (int i = 0; i < len; i++) {
+            if (name.equals(argNames.get(i))) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    public String getArgName(int index) {
+        return argNames.get(index);
+    }
+
+    public CType getArgType(int index) {
+        return argTypes.get(index);
+    }
+
+    public boolean hasPointerArg() {
+        return hasPointerArg;
+    }
+
+    public boolean hasTypedPointerArg() {
+        return hasTypedPointerArg;
+    }
+
+    @Override
+    public String toString() {
+        String s =  "Function " + fname + " returns " + ftype + ": ";
+        for (int i = 0; i < argNames.size(); i++) {
+            if (i > 0) {
+                s += ", ";
+            }
+            s += argTypes.get(i) + " " + argNames.get(i);
+        }
+        return s;
+    }
+
+    public static CFunc parseCFunc(String s) {
+        CFunc cfunc = new CFunc(s);
+        String[] tokens = s.split("\\s");
+
+        int i = 0;
+        CType ftype = new CType();
+        String ftypeName = tokens[i++];
+        if (ftypeName.equals("const")) {
+            ftype.setIsConst(true);
+            ftypeName = tokens[i++];
+        }
+        ftype.setBaseType(ftypeName);
+
+        String fname = tokens[i++];
+        if (fname.equals("*")) {
+            ftype.setIsPointer(true);
+            fname = tokens[i++];
+        }
+
+        cfunc.setName(fname);
+        cfunc.setType(ftype);
+
+        while (i < tokens.length) {
+            String tok = tokens[i++];
+
+            if (tok.equals("(")) {
+                continue;
+            }
+            if (tok.equals(")")) {
+                break;
+            }
+
+            CType argType = new CType();
+
+            String argTypeName = tok;
+            String argName = "";
+
+            if (argTypeName.equals("const")) {
+                argType.setIsConst(true);
+                argTypeName = tokens[i++];
+            }
+            argType.setBaseType(argTypeName);
+
+            if (argTypeName.equals("void")) {
+                break;
+            }
+
+            argName = tokens[i++];
+            if (argName.startsWith("*")) {
+                argType.setIsPointer(true);
+                argName = argName.substring(1, argName.length());
+            }
+            if (argName.endsWith(",")) {
+                argName = argName.substring(0, argName.length() - 1);
+            }
+
+            cfunc.addArgument(argName, argType);
+        }
+
+        return cfunc;
+    }
+}
diff --git a/opengl/tools/glgen/src/CType.java b/opengl/tools/glgen/src/CType.java
index 331ec62..826c90d 100644
--- a/opengl/tools/glgen/src/CType.java
+++ b/opengl/tools/glgen/src/CType.java
@@ -1,85 +1,88 @@
-

-public class CType {

-

-    String baseType;

-    boolean isConst;

-    boolean isPointer;

-

-    public CType() {

-    }

-

-    public CType(String baseType) {

-	setBaseType(baseType);

-    }

-

-    public CType(String baseType, boolean isConst, boolean isPointer) {

-	setBaseType(baseType);

-	setIsConst(isConst);

-	setIsPointer(isPointer);

-    }

-

-    public String getDeclaration() {

-	return baseType + (isPointer ? " *" : "");

-    }

-    

-    public void setIsConst(boolean isConst) {

-	this.isConst = isConst;

-    }

-

-    public boolean isConst() {

-	return isConst;

-    }

-

-    public void setIsPointer(boolean isPointer) {

-	this.isPointer = isPointer;

-    }

-

-    public boolean isPointer() {

-	return isPointer;

-    }

-

-    boolean isVoid() {

-	String baseType = getBaseType();

-	return baseType.equals("GLvoid") ||

-	    baseType.equals("void");

-    }

-

-    public boolean isTypedPointer() {

-	return isPointer() && !isVoid();

-    }

-

-    public void setBaseType(String baseType) {

-	this.baseType = baseType;

-    }

-

-    public String getBaseType() {

-	return baseType;

-    }

-

-    public String toString() {

-	String s = "";

-	if (isConst()) {

-	    s += "const ";

-	}

-	s += baseType;

-	if (isPointer()) {

-	    s += "*";

-	}

-

-	return s;

-    }

-

-    public int hashCode() {

-	return baseType.hashCode() ^ (isPointer ? 2 : 0) ^ (isConst ? 1 : 0);

-    }

-

-    public boolean equals(Object o) {

-	if (o != null && o instanceof CType) {

-	    CType c = (CType)o;

-	    return baseType.equals(c.baseType) &&

-		isPointer() == c.isPointer() &&

-		isConst() == c.isConst();

-	}

-	return false;

-    }

-}

+
+public class CType {
+
+    String baseType;
+    boolean isConst;
+    boolean isPointer;
+
+    public CType() {
+    }
+
+    public CType(String baseType) {
+    setBaseType(baseType);
+    }
+
+    public CType(String baseType, boolean isConst, boolean isPointer) {
+    setBaseType(baseType);
+    setIsConst(isConst);
+    setIsPointer(isPointer);
+    }
+
+    public String getDeclaration() {
+    return baseType + (isPointer ? " *" : "");
+    }
+
+    public void setIsConst(boolean isConst) {
+    this.isConst = isConst;
+    }
+
+    public boolean isConst() {
+    return isConst;
+    }
+
+    public void setIsPointer(boolean isPointer) {
+    this.isPointer = isPointer;
+    }
+
+    public boolean isPointer() {
+    return isPointer;
+    }
+
+    boolean isVoid() {
+    String baseType = getBaseType();
+    return baseType.equals("GLvoid") ||
+        baseType.equals("void");
+    }
+
+    public boolean isTypedPointer() {
+    return isPointer() && !isVoid();
+    }
+
+    public void setBaseType(String baseType) {
+    this.baseType = baseType;
+    }
+
+    public String getBaseType() {
+    return baseType;
+    }
+
+    @Override
+    public String toString() {
+    String s = "";
+    if (isConst()) {
+        s += "const ";
+    }
+    s += baseType;
+    if (isPointer()) {
+        s += "*";
+    }
+
+    return s;
+    }
+
+    @Override
+    public int hashCode() {
+    return baseType.hashCode() ^ (isPointer ? 2 : 0) ^ (isConst ? 1 : 0);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+    if (o != null && o instanceof CType) {
+        CType c = (CType)o;
+        return baseType.equals(c.baseType) &&
+        isPointer() == c.isPointer() &&
+        isConst() == c.isConst();
+    }
+    return false;
+    }
+}
diff --git a/opengl/tools/glgen/src/CodeEmitter.java b/opengl/tools/glgen/src/CodeEmitter.java
index 3e9b90a..ebb9727 100644
--- a/opengl/tools/glgen/src/CodeEmitter.java
+++ b/opengl/tools/glgen/src/CodeEmitter.java
@@ -1,8 +1,8 @@
-

-public interface CodeEmitter {

-

-    void setVersion(int version, boolean ext, boolean pack);

-    void emitCode(CFunc cfunc, String original);

-    void addNativeRegistration(String fname);

-    void emitNativeRegistration();

-}

+
+public interface CodeEmitter {
+
+    void setVersion(int version, boolean ext, boolean pack);
+    void emitCode(CFunc cfunc, String original);
+    void addNativeRegistration(String fname);
+    void emitNativeRegistration();
+}
diff --git a/opengl/tools/glgen/src/GLESCodeEmitter.java b/opengl/tools/glgen/src/GLESCodeEmitter.java
new file mode 100644
index 0000000..b303503
--- /dev/null
+++ b/opengl/tools/glgen/src/GLESCodeEmitter.java
@@ -0,0 +1,40 @@
+import java.io.PrintStream;
+
+/**
+ * Emits a Java interface and Java & C implementation for a C function.
+ *
+ * <p> The Java interface will have Buffer and array variants for functions that
+ * have a typed pointer argument.  The array variant will convert a single "<type> *data"
+ * argument to a pair of arguments "<type>[] data, int offset".
+ */
+public class GLESCodeEmitter extends JniCodeEmitter {
+
+    PrintStream mJavaImplStream;
+    PrintStream mCStream;
+
+    PrintStream mJavaInterfaceStream;
+
+    /**
+      */
+    public GLESCodeEmitter(String classPathName,
+                          ParameterChecker checker,
+                          PrintStream javaImplStream,
+                          PrintStream cStream) {
+        mClassPathName = classPathName;
+        mChecker = checker;
+
+        mJavaImplStream = javaImplStream;
+        mCStream = cStream;
+        mUseContextPointer = false;
+        mUseStaticMethods = true;
+    }
+
+    public void emitCode(CFunc cfunc, String original) {
+        emitCode(cfunc, original, null, mJavaImplStream,
+                mCStream);
+    }
+
+    public void emitNativeRegistration(String nativeRegistrationName) {
+        emitNativeRegistration(nativeRegistrationName, mCStream);
+    }
+}
diff --git a/opengl/tools/glgen/src/GenerateGL.java b/opengl/tools/glgen/src/GenerateGL.java
index 657ee6e..3715a96 100644
--- a/opengl/tools/glgen/src/GenerateGL.java
+++ b/opengl/tools/glgen/src/GenerateGL.java
@@ -1,164 +1,167 @@
-

-import java.io.*;

-import java.util.*;

-

-public class GenerateGL {

-

-    static void copy(String filename, PrintStream out) throws IOException {

-        BufferedReader br = new BufferedReader(new FileReader(filename));

-        String s;

-        while ((s = br.readLine()) != null) {

-            out.println(s);

-        }

-    }

-

-    private static void emit(int version, boolean ext, boolean pack,

-                             CodeEmitter emitter,

-                             BufferedReader specReader,

-                             PrintStream glStream,

-                             PrintStream glImplStream,

-                             PrintStream cStream) throws Exception {

-        String s = null;

-        int counter = 0;

-        while ((s = specReader.readLine()) != null) {

-            if (s.trim().startsWith("//")) {

-                continue;

-            }

-

-            CFunc cfunc = CFunc.parseCFunc(s);

-

-            String fname = cfunc.getName();

-            File f = new File("stubs/" + fname +

-                              ".java-1" + version + "-if");

-            if (f.exists()) {

-                System.out.println("Special-casing function " + fname);

-                copy("stubs/" + fname +

-                     ".java-1" + version + "-if", glStream);

-                copy("stubs/" + fname + ".java-impl", glImplStream);

-                copy("stubs/" + fname + ".cpp", cStream);

-

-                // Register native function names

-                // This should be improved to require fewer discrete files

-                String filename = "stubs/" + fname + ".nativeReg";

-                BufferedReader br =

-                    new BufferedReader(new FileReader(filename));

-                String nfunc;

-                while ((nfunc = br.readLine()) != null) {

-                    emitter.addNativeRegistration(nfunc);

-                }

-            } else {

-                emitter.setVersion(version, ext, pack);

-                emitter.emitCode(cfunc, s);

-            }

-        }

-    }

-

-    public static void main(String[] args) throws Exception {

-        String classPathName = "com/google/android/gles_jni/GLImpl";

-        boolean useContextPointer = true;

-

-        int aidx = 0;

-        while (args[aidx].charAt(0) == '-') {

-            switch (args[aidx].charAt(1)) {

-            case 'c':

-                useContextPointer = false;

-                break;

-

-            default:

-                System.err.println("Unknown flag: " + args[aidx]);

-                System.exit(1);

-            }

-

-            aidx++;

-        }

-

-        System.out.println("useContextPointer = " + useContextPointer);

-

-        BufferedReader spec10Reader =

-            new BufferedReader(new FileReader(args[aidx++]));

-        BufferedReader spec10ExtReader =

-            new BufferedReader(new FileReader(args[aidx++]));

-        BufferedReader spec11Reader =

-            new BufferedReader(new FileReader(args[aidx++]));

-        BufferedReader spec11ExtReader =

-            new BufferedReader(new FileReader(args[aidx++]));

-        BufferedReader spec11ExtPackReader =

-            new BufferedReader(new FileReader(args[aidx++]));

-        BufferedReader checksReader =

-            new BufferedReader(new FileReader(args[aidx++]));

-

-        String gl10Filename = "javax/microedition/khronos/opengles/GL10.java";

-        String gl10ExtFilename =

-            "javax/microedition/khronos/opengles/GL10Ext.java";

-        String gl11Filename = "javax/microedition/khronos/opengles/GL11.java";

-        String gl11ExtFilename =

-            "javax/microedition/khronos/opengles/GL11Ext.java";

-        String gl11ExtPackFilename =

-            "javax/microedition/khronos/opengles/GL11ExtensionPack.java";

-        String glImplFilename = "com/google/android/gles_jni/GLImpl.java";

-        String cFilename = "com_google_android_gles_jni_GLImpl.cpp";

-

-        PrintStream gl10Stream =

-            new PrintStream(new FileOutputStream("out/" + gl10Filename));

-        PrintStream gl10ExtStream =

-            new PrintStream(new FileOutputStream("out/" + gl10ExtFilename));

-        PrintStream gl11Stream =

-            new PrintStream(new FileOutputStream("out/" + gl11Filename));

-        PrintStream gl11ExtStream =

-            new PrintStream(new FileOutputStream("out/" + gl11ExtFilename));

-        PrintStream gl11ExtPackStream =

-            new PrintStream(new FileOutputStream("out/" + gl11ExtPackFilename));

-        PrintStream glImplStream =

-            new PrintStream(new FileOutputStream("out/" + glImplFilename));

-        PrintStream cStream =

-            new PrintStream(new FileOutputStream("out/" + cFilename));

-

-        ParameterChecker checker = new ParameterChecker(checksReader);

-

-        CodeEmitter emitter =

-            new JniCodeEmitter(classPathName,

-                               checker,

-                               gl10Stream, gl10ExtStream,

-                               gl11Stream, gl11ExtStream, gl11ExtPackStream,

-                               glImplStream, cStream,

-                               useContextPointer);

-

-        gl10Stream.println("/* //device/java/android/" + gl10Filename);

-        gl10ExtStream.println("/* //device/java/android/" + gl10ExtFilename);

-        gl11Stream.println("/* //device/java/android/" + gl11Filename);

-        gl11ExtStream.println("/* //device/java/android/" + gl11ExtFilename);

-        gl11ExtPackStream.println("/* //device/java/android/" +

-            gl11ExtPackFilename);

-        glImplStream.println("/* //device/java/android/" + glImplFilename);

-        cStream.println("/* //device/libs/android_runtime/" + cFilename);

-

-        copy("stubs/GL10Header.java-if", gl10Stream);

-        copy("stubs/GL10ExtHeader.java-if", gl10ExtStream);

-        copy("stubs/GL11Header.java-if", gl11Stream);

-        copy("stubs/GL11ExtHeader.java-if", gl11ExtStream);

-        copy("stubs/GL11ExtensionPackHeader.java-if", gl11ExtPackStream);

-        copy("stubs/GLImplHeader.java-impl", glImplStream);

-        copy("stubs/GLCHeader.cpp", cStream);

-

-        emit(0, false, false,

-             emitter, spec10Reader, gl10Stream, glImplStream, cStream);

-        emit(0, true, false,

-             emitter, spec10ExtReader, gl10ExtStream, glImplStream, cStream);

-        emit(1, false, false,

-             emitter, spec11Reader, gl11Stream, glImplStream, cStream);

-        emit(1, true, false,

-             emitter, spec11ExtReader, gl11ExtStream, glImplStream, cStream);

-        emit(1, true, true,

-             emitter, spec11ExtPackReader, gl11ExtPackStream, glImplStream,

-             cStream);

-

-        emitter.emitNativeRegistration();

-

-        gl10Stream.println("}");

-        gl10ExtStream.println("}");

-        gl11Stream.println("}");

-        gl11ExtStream.println("}");

-        gl11ExtPackStream.println("}");

-        glImplStream.println("}");

-    }

-}

+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.PrintStream;
+
+public class GenerateGL {
+
+    static void copy(String filename, PrintStream out) throws IOException {
+        BufferedReader br = new BufferedReader(new FileReader(filename));
+        String s;
+        while ((s = br.readLine()) != null) {
+            out.println(s);
+        }
+    }
+
+    private static void emit(int version, boolean ext, boolean pack,
+                             CodeEmitter emitter,
+                             BufferedReader specReader,
+                             PrintStream glStream,
+                             PrintStream glImplStream,
+                             PrintStream cStream) throws Exception {
+        String s = null;
+        while ((s = specReader.readLine()) != null) {
+            if (s.trim().startsWith("//")) {
+                continue;
+            }
+
+            CFunc cfunc = CFunc.parseCFunc(s);
+
+            String fname = cfunc.getName();
+            File f = new File("stubs/jsr239/" + fname +
+                              ".java-1" + version + "-if");
+            if (f.exists()) {
+                System.out.println("Special-casing function " + fname);
+                copy("stubs/jsr239/" + fname +
+                     ".java-1" + version + "-if", glStream);
+                copy("stubs/jsr239/" + fname + ".java-impl", glImplStream);
+                copy("stubs/jsr239/" + fname + ".cpp", cStream);
+
+                // Register native function names
+                // This should be improved to require fewer discrete files
+                String filename = "stubs/jsr239/" + fname + ".nativeReg";
+                BufferedReader br =
+                    new BufferedReader(new FileReader(filename));
+                String nfunc;
+                while ((nfunc = br.readLine()) != null) {
+                    emitter.addNativeRegistration(nfunc);
+                }
+            } else {
+                emitter.setVersion(version, ext, pack);
+                emitter.emitCode(cfunc, s);
+            }
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        String classPathName = "com/google/android/gles_jni/GLImpl";
+        boolean useContextPointer = true;
+
+        int aidx = 0;
+        while (args[aidx].charAt(0) == '-') {
+            switch (args[aidx].charAt(1)) {
+            case 'c':
+                useContextPointer = false;
+                break;
+
+            default:
+                System.err.println("Unknown flag: " + args[aidx]);
+                System.exit(1);
+            }
+
+            aidx++;
+        }
+
+        System.out.println("useContextPointer = " + useContextPointer);
+
+        BufferedReader spec10Reader =
+            new BufferedReader(new FileReader(args[aidx++]));
+        BufferedReader spec10ExtReader =
+            new BufferedReader(new FileReader(args[aidx++]));
+        BufferedReader spec11Reader =
+            new BufferedReader(new FileReader(args[aidx++]));
+        BufferedReader spec11ExtReader =
+            new BufferedReader(new FileReader(args[aidx++]));
+        BufferedReader spec11ExtPackReader =
+            new BufferedReader(new FileReader(args[aidx++]));
+        BufferedReader checksReader =
+            new BufferedReader(new FileReader(args[aidx++]));
+
+        String gl10Filename = "javax/microedition/khronos/opengles/GL10.java";
+        String gl10ExtFilename =
+            "javax/microedition/khronos/opengles/GL10Ext.java";
+        String gl11Filename = "javax/microedition/khronos/opengles/GL11.java";
+        String gl11ExtFilename =
+            "javax/microedition/khronos/opengles/GL11Ext.java";
+        String gl11ExtPackFilename =
+            "javax/microedition/khronos/opengles/GL11ExtensionPack.java";
+        String glImplFilename = "com/google/android/gles_jni/GLImpl.java";
+        String cFilename = "com_google_android_gles_jni_GLImpl.cpp";
+
+        PrintStream gl10Stream =
+            new PrintStream(new FileOutputStream("out/" + gl10Filename));
+        PrintStream gl10ExtStream =
+            new PrintStream(new FileOutputStream("out/" + gl10ExtFilename));
+        PrintStream gl11Stream =
+            new PrintStream(new FileOutputStream("out/" + gl11Filename));
+        PrintStream gl11ExtStream =
+            new PrintStream(new FileOutputStream("out/" + gl11ExtFilename));
+        PrintStream gl11ExtPackStream =
+            new PrintStream(new FileOutputStream("out/" + gl11ExtPackFilename));
+        PrintStream glImplStream =
+            new PrintStream(new FileOutputStream("out/" + glImplFilename));
+        PrintStream cStream =
+            new PrintStream(new FileOutputStream("out/" + cFilename));
+
+        ParameterChecker checker = new ParameterChecker(checksReader);
+
+        CodeEmitter emitter =
+            new Jsr239CodeEmitter(classPathName,
+                               checker,
+                               gl10Stream, gl10ExtStream,
+                               gl11Stream, gl11ExtStream, gl11ExtPackStream,
+                               glImplStream, cStream,
+                               useContextPointer);
+
+        gl10Stream.println("/* //device/java/android/" + gl10Filename);
+        gl10ExtStream.println("/* //device/java/android/" + gl10ExtFilename);
+        gl11Stream.println("/* //device/java/android/" + gl11Filename);
+        gl11ExtStream.println("/* //device/java/android/" + gl11ExtFilename);
+        gl11ExtPackStream.println("/* //device/java/android/" +
+            gl11ExtPackFilename);
+        glImplStream.println("/* //device/java/android/" + glImplFilename);
+        cStream.println("/* //device/libs/android_runtime/" + cFilename);
+
+        copy("stubs/jsr239/GL10Header.java-if", gl10Stream);
+        copy("stubs/jsr239/GL10ExtHeader.java-if", gl10ExtStream);
+        copy("stubs/jsr239/GL11Header.java-if", gl11Stream);
+        copy("stubs/jsr239/GL11ExtHeader.java-if", gl11ExtStream);
+        copy("stubs/jsr239/GL11ExtensionPackHeader.java-if", gl11ExtPackStream);
+        copy("stubs/jsr239/GLImplHeader.java-impl", glImplStream);
+        copy("stubs/jsr239/GLCHeader.cpp", cStream);
+
+        emit(0, false, false,
+             emitter, spec10Reader, gl10Stream, glImplStream, cStream);
+        emit(0, true, false,
+             emitter, spec10ExtReader, gl10ExtStream, glImplStream, cStream);
+        emit(1, false, false,
+             emitter, spec11Reader, gl11Stream, glImplStream, cStream);
+        emit(1, true, false,
+             emitter, spec11ExtReader, gl11ExtStream, glImplStream, cStream);
+        emit(1, true, true,
+             emitter, spec11ExtPackReader, gl11ExtPackStream, glImplStream,
+             cStream);
+
+        emitter.emitNativeRegistration();
+
+        gl10Stream.println("}");
+        gl10ExtStream.println("}");
+        gl11Stream.println("}");
+        gl11ExtStream.println("}");
+        gl11ExtPackStream.println("}");
+        glImplStream.println("}");
+    }
+}
diff --git a/opengl/tools/glgen/src/GenerateGLES.java b/opengl/tools/glgen/src/GenerateGLES.java
new file mode 100644
index 0000000..60775b7
--- /dev/null
+++ b/opengl/tools/glgen/src/GenerateGLES.java
@@ -0,0 +1,99 @@
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.PrintStream;
+
+public class GenerateGLES {
+
+    static void copy(String filename, PrintStream out) throws IOException {
+        BufferedReader br = new BufferedReader(new FileReader(filename));
+        String s;
+        while ((s = br.readLine()) != null) {
+            out.println(s);
+        }
+    }
+
+    private static void emit(GLESCodeEmitter emitter,
+                             BufferedReader specReader,
+                             PrintStream glStream,
+                             PrintStream cStream) throws Exception {
+        String s = null;
+        while ((s = specReader.readLine()) != null) {
+            if (s.trim().startsWith("//")) {
+                continue;
+            }
+
+            CFunc cfunc = CFunc.parseCFunc(s);
+
+            String fname = cfunc.getName();
+            String stubRoot = "stubs/gles11/" + fname;
+            String javaPath = stubRoot + ".java";
+            File f = new File(javaPath);
+            if (f.exists()) {
+                System.out.println("Special-casing function " + fname);
+                copy(javaPath, glStream);
+                copy(stubRoot + ".cpp", cStream);
+
+                // Register native function names
+                // This should be improved to require fewer discrete files
+                String filename = stubRoot + ".nativeReg";
+                BufferedReader br =
+                    new BufferedReader(new FileReader(filename));
+                String nfunc;
+                while ((nfunc = br.readLine()) != null) {
+                    emitter.addNativeRegistration(nfunc);
+                }
+            } else {
+                emitter.emitCode(cfunc, s);
+            }
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        int aidx = 0;
+        while ((aidx < args.length) && (args[aidx].charAt(0) == '-')) {
+            switch (args[aidx].charAt(1)) {
+            default:
+                System.err.println("Unknown flag: " + args[aidx]);
+                System.exit(1);
+            }
+
+            aidx++;
+        }
+
+        BufferedReader checksReader =
+            new BufferedReader(new FileReader("specs/gles11/checks.spec"));
+        ParameterChecker checker = new ParameterChecker(checksReader);
+
+        // Generate files
+        for(String suffix: new String[] {"GLES10", "GLES10Ext",
+                "GLES11", "GLES11Ext"})
+        {
+            BufferedReader spec11Reader =
+                new BufferedReader(new FileReader("specs/gles11/"
+                        + suffix + ".spec"));
+            String gl11Filename = "android/opengl/" + suffix + ".java";
+            String gl11cFilename = "android_opengl_" + suffix + ".cpp";
+            PrintStream gl11Stream =
+                new PrintStream(new FileOutputStream("out/" + gl11Filename));
+            PrintStream gl11cStream =
+                new PrintStream(new FileOutputStream("out/" + gl11cFilename));
+            gl11Stream.println("/*");
+            gl11cStream.println("/*");
+            copy("stubs/gles11/" + suffix + "Header.java-if", gl11Stream);
+            copy("stubs/gles11/" + suffix + "cHeader.cpp", gl11cStream);
+            GLESCodeEmitter emitter = new GLESCodeEmitter(
+                    "android/opengl/" + suffix,
+                    checker, gl11Stream, gl11cStream);
+            emit(emitter, spec11Reader, gl11Stream, gl11cStream);
+            emitter.emitNativeRegistration("register_android_opengl_jni_"
+                    + suffix);
+            gl11Stream.println("}");
+            gl11Stream.close();
+            gl11cStream.close();
+        }
+    }
+}
diff --git a/opengl/tools/glgen/src/JFunc.java b/opengl/tools/glgen/src/JFunc.java
index 42d466c..63c045b 100644
--- a/opengl/tools/glgen/src/JFunc.java
+++ b/opengl/tools/glgen/src/JFunc.java
@@ -1,148 +1,154 @@
-

-import java.util.ArrayList;

-import java.util.List;

-

-public class JFunc {

-

-    String className = "com.google.android.gles_jni.GL11Impl";

-

-    CFunc cfunc;

-    JType ftype;

-    String fname;

-

-    List<String> argNames = new ArrayList<String>();

-    List<JType> argTypes = new ArrayList<JType>();

-    List<Integer> argCIndices = new ArrayList<Integer>();

-

-    boolean hasBufferArg = false;

-    boolean hasTypedBufferArg = false;

-    ArrayList<String> bufferArgNames = new ArrayList<String>();

-

-    public JFunc(CFunc cfunc) {

-        this.cfunc = cfunc;

-    }

-

-    public CFunc getCFunc() {

-        return cfunc;

-    }

-

-    public void setName(String fname) {

-        this.fname = fname;

-    }

-

-    public String getName() {

-        return fname;

-    }

-

-    public void setType(JType ftype) {

-        this.ftype = ftype;

-    }

-

-    public JType getType() {

-        return ftype;

-    }

-

-    public void setClassName(String className) {

-        this.className = className;

-    }

-

-    public String getClassName() {

-        return className;

-    }

-    

-    public boolean hasBufferArg() {

-        return hasBufferArg;

-    }

-

-    public boolean hasTypedBufferArg() {

-        return hasTypedBufferArg;

-    }

-

-    public String getBufferArgName(int index) {

-        return bufferArgNames.get(index);

-    }

-

-    public void addArgument(String argName, JType argType, int cindex) {

-        argNames.add(argName);

-        argTypes.add(argType);

-        argCIndices.add(new Integer(cindex));

-

-        if (argType.isBuffer()) {

-            hasBufferArg = true;

-            bufferArgNames.add(argName);

-        }

-        if (argType.isTypedBuffer()) {

-            hasTypedBufferArg = true;

-            bufferArgNames.add(argName);

-        }

-    }

-

-    public int getNumArgs() {

-        return argNames.size();

-    }

-

-    public int getArgIndex(String name) {

-        int len = argNames.size();

-        for (int i = 0; i < len; i++) {

-            if (name.equals(argNames.get(i))) {

-                return i;

-            }

-        }

-        return -1;

-    }

-

-    public String getArgName(int index) {

-        return argNames.get(index);

-    }

-

-    public JType getArgType(int index) {

-        return argTypes.get(index);

-    }

-

-    public int getArgCIndex(int index) {

-        return argCIndices.get(index).intValue();

-    }

-

-    public static JFunc convert(CFunc cfunc, boolean useArray) {

-        JFunc jfunc = new JFunc(cfunc);

-        jfunc.setName(cfunc.getName());

-        jfunc.setType(JType.convert(cfunc.getType(), false));

-	

-        int numArgs = cfunc.getNumArgs();

-        int numOffsets = 0;

-        for (int i = 0; i < numArgs; i++) {

-            CType cArgType = cfunc.getArgType(i);

-            if (cArgType.isTypedPointer() && useArray) {

-                ++numOffsets;

-            }

-        }

-

-        for (int i = 0; i < numArgs; i++) {

-            String cArgName = cfunc.getArgName(i);

-            CType cArgType = cfunc.getArgType(i);

-

-            jfunc.addArgument(cArgName, JType.convert(cArgType, useArray), i);

-            if (cArgType.isTypedPointer() && useArray) {

-                if (numOffsets > 1) {

-                    jfunc.addArgument(cArgName + "Offset", new JType("int"), i);

-                } else {

-                    jfunc.addArgument("offset", new JType("int"), i);

-                }

-            }

-        }

-

-        return jfunc;

-    }

-

-    public String toString() {

-        String s =  "Function " + fname + " returns " + ftype + ": ";

-        for (int i = 0; i < argNames.size(); i++) {

-            if (i > 0) {

-                s += ", ";

-            }

-            s += argTypes.get(i) + " " + argNames.get(i);

-        }

-        return s;

-    }

-

-}

+
+import java.util.ArrayList;
+import java.util.List;
+
+public class JFunc {
+
+    String className = "com.google.android.gles_jni.GL11Impl";
+
+    CFunc cfunc;
+    JType ftype;
+    String fname;
+
+    List<String> argNames = new ArrayList<String>();
+    List<JType> argTypes = new ArrayList<JType>();
+    List<Integer> argCIndices = new ArrayList<Integer>();
+
+    boolean hasBufferArg = false;
+    boolean hasTypedBufferArg = false;
+    ArrayList<String> bufferArgNames = new ArrayList<String>();
+
+    public JFunc(CFunc cfunc) {
+        this.cfunc = cfunc;
+    }
+
+    public CFunc getCFunc() {
+        return cfunc;
+    }
+
+    public void setName(String fname) {
+        this.fname = fname;
+    }
+
+    public String getName() {
+        return fname;
+    }
+
+    public void setType(JType ftype) {
+        this.ftype = ftype;
+    }
+
+    public JType getType() {
+        return ftype;
+    }
+
+    public void setClassName(String className) {
+        this.className = className;
+    }
+
+    public String getClassName() {
+        return className;
+    }
+
+    public boolean hasBufferArg() {
+        return hasBufferArg;
+    }
+
+    public boolean hasTypedBufferArg() {
+        return hasTypedBufferArg;
+    }
+
+    public String getBufferArgName(int index) {
+        return bufferArgNames.get(index);
+    }
+
+    public void addArgument(String argName, JType argType, int cindex) {
+        argNames.add(argName);
+        argTypes.add(argType);
+        argCIndices.add(new Integer(cindex));
+
+        if (argType.isBuffer()) {
+            hasBufferArg = true;
+            bufferArgNames.add(argName);
+        }
+        if (argType.isTypedBuffer()) {
+            hasTypedBufferArg = true;
+            bufferArgNames.add(argName);
+        }
+    }
+
+    public int getNumArgs() {
+        return argNames.size();
+    }
+
+    public int getArgIndex(String name) {
+        int len = argNames.size();
+        for (int i = 0; i < len; i++) {
+            if (name.equals(argNames.get(i))) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    public String getArgName(int index) {
+        return argNames.get(index);
+    }
+
+    public JType getArgType(int index) {
+        return argTypes.get(index);
+    }
+
+    public int getArgCIndex(int index) {
+        return argCIndices.get(index).intValue();
+    }
+
+    public static JFunc convert(CFunc cfunc, boolean useArray) {
+        try {
+            JFunc jfunc = new JFunc(cfunc);
+            jfunc.setName(cfunc.getName());
+            jfunc.setType(JType.convert(cfunc.getType(), false));
+
+            int numArgs = cfunc.getNumArgs();
+            int numOffsets = 0;
+            for (int i = 0; i < numArgs; i++) {
+                CType cArgType = cfunc.getArgType(i);
+                if (cArgType.isTypedPointer() && useArray) {
+                    ++numOffsets;
+                }
+            }
+
+            for (int i = 0; i < numArgs; i++) {
+                String cArgName = cfunc.getArgName(i);
+                CType cArgType = cfunc.getArgType(i);
+
+                jfunc.addArgument(cArgName, JType.convert(cArgType, useArray), i);
+                if (cArgType.isTypedPointer() && useArray) {
+                    if (numOffsets > 1) {
+                        jfunc.addArgument(cArgName + "Offset", new JType("int"), i);
+                    } else {
+                        jfunc.addArgument("offset", new JType("int"), i);
+                    }
+                }
+            }
+
+            return jfunc;
+        } catch (RuntimeException e) {
+            System.err.println("Failed to convert function " + cfunc);
+            throw e;
+        }
+    }
+
+    @Override
+    public String toString() {
+        String s =  "Function " + fname + " returns " + ftype + ": ";
+        for (int i = 0; i < argNames.size(); i++) {
+            if (i > 0) {
+                s += ", ";
+            }
+            s += argTypes.get(i) + " " + argNames.get(i);
+        }
+        return s;
+    }
+
+}
diff --git a/opengl/tools/glgen/src/JType.java b/opengl/tools/glgen/src/JType.java
index a16d440..df1177b 100644
--- a/opengl/tools/glgen/src/JType.java
+++ b/opengl/tools/glgen/src/JType.java
@@ -1,139 +1,142 @@
-

-import java.util.HashMap;

-

-public class JType {

-    

-    String baseType;

-    boolean isArray;

-    boolean isClass;

-

-    static HashMap<CType,JType> typeMapping = new HashMap<CType,JType>();

-    static HashMap<CType,JType> arrayTypeMapping = new HashMap<CType,JType>();

-

-    static {

-	// Primitive types

-	typeMapping.put(new CType("GLbitfield"), new JType("int"));

-	typeMapping.put(new CType("GLboolean"), new JType("boolean"));

-	typeMapping.put(new CType("GLclampf"), new JType("float"));

-	typeMapping.put(new CType("GLclampx"), new JType("int"));

-	typeMapping.put(new CType("GLenum"), new JType("int"));

-	typeMapping.put(new CType("GLfloat"), new JType("float"));

-	typeMapping.put(new CType("GLfixed"), new JType("int"));

-	typeMapping.put(new CType("GLint"), new JType("int"));

-	typeMapping.put(new CType("GLintptr"), new JType("int"));

-	typeMapping.put(new CType("GLshort"), new JType("short"));

-	typeMapping.put(new CType("GLsizei"), new JType("int"));

-	typeMapping.put(new CType("GLsizeiptr"), new JType("int"));

-	typeMapping.put(new CType("GLubyte"), new JType("byte"));

-	typeMapping.put(new CType("GLuint"), new JType("int"));

-	typeMapping.put(new CType("void"), new JType("void"));

-	typeMapping.put(new CType("GLubyte", true, true), new JType("String"));

-

-	// Untyped pointers map to untyped Buffers

-	typeMapping.put(new CType("GLvoid", true, true),

-			new JType("java.nio.Buffer", true, false));

-	typeMapping.put(new CType("GLvoid", false, true),

-			new JType("java.nio.Buffer", true, false));

-	typeMapping.put(new CType("void", false, true),

-			new JType("java.nio.Buffer", true, false));

-

-	// Typed pointers map to typed Buffers

-	typeMapping.put(new CType("GLboolean", false, true),

-			new JType("java.nio.IntBuffer", true, false));

-	typeMapping.put(new CType("GLfixed", false, true),

-			new JType("java.nio.IntBuffer", true, false));

-	typeMapping.put(new CType("GLfixed", true, true),

-			new JType("java.nio.IntBuffer", true, false));

-	typeMapping.put(new CType("GLfloat", false, true),

-			new JType("java.nio.FloatBuffer", true, false));

-	typeMapping.put(new CType("GLfloat", true, true),

-			new JType("java.nio.FloatBuffer", true, false));

-	typeMapping.put(new CType("GLint", false, true),

-			new JType("java.nio.IntBuffer", true, false));

-	typeMapping.put(new CType("GLint", true, true),

-			new JType("java.nio.IntBuffer", true, false));

-	typeMapping.put(new CType("GLuint", false, true),

-			new JType("java.nio.IntBuffer", true, false));

-	typeMapping.put(new CType("GLuint", true, true),

-			new JType("java.nio.IntBuffer", true, false));

-	typeMapping.put(new CType("GLshort", true, true),

-			new JType("java.nio.ShortBuffer", true, false));

-

-	// Typed pointers map to arrays + offsets

-	arrayTypeMapping.put(new CType("GLboolean", false, true),

-			     new JType("boolean", false, true));

-	arrayTypeMapping.put(new CType("GLfixed", true, true), new JType("int", false, true));

-	arrayTypeMapping.put(new CType("GLfixed", false, true), new JType("int", false, true));

-	arrayTypeMapping.put(new CType("GLfloat", false, true), new JType("float", false, true));

-	arrayTypeMapping.put(new CType("GLfloat", true, true), new JType("float", false, true));

-	arrayTypeMapping.put(new CType("GLint", false, true), new JType("int", false, true));

-	arrayTypeMapping.put(new CType("GLint", true, true), new JType("int", false, true));

-	arrayTypeMapping.put(new CType("GLshort", true, true), new JType("short", false, true));

-	arrayTypeMapping.put(new CType("GLuint", false, true), new JType("int", false, true));

-	arrayTypeMapping.put(new CType("GLuint", true, true), new JType("int", false, true));

-	arrayTypeMapping.put(new CType("GLintptr"), new JType("int", false, true));

-	arrayTypeMapping.put(new CType("GLsizeiptr"), new JType("int", false, true));

-    }

-

-    public JType() {

-    }

-

-    public JType(String primitiveTypeName) {

-	this.baseType = primitiveTypeName;

-	this.isClass = false;

-	this.isArray = false;

-    }

-

-    public JType(String primitiveTypeName, boolean isClass, boolean isArray) {

-	this.baseType = primitiveTypeName;

-	this.isClass = isClass;

-	this.isArray = isArray;

-    }

-

-    public String getBaseType() {

-	return baseType;

-    }

-

-    public String toString() {

-	return baseType + (isArray ? "[]" : "");

-    }

-

-    public boolean isArray() {

-	return isArray;

-    }

-

-    public boolean isClass() {

-	return isClass;

-    }

-

-    public boolean isPrimitive() {

-	return !isClass() && !isArray();

-    }

-

-    public boolean isVoid() {

-	return baseType.equals("void");

-    }

-

-    public boolean isBuffer() {

-	return baseType.indexOf("Buffer") != -1;

-    }

-

-    public boolean isTypedBuffer() {

-	return !baseType.equals("java.nio.Buffer") &&

-	    (baseType.indexOf("Buffer") != -1);

-    }

-

-    public static JType convert(CType ctype, boolean useArray) {

- 	JType javaType = null;

- 	if (useArray) {

- 	    javaType = arrayTypeMapping.get(ctype);

- 	}

- 	if (javaType == null) {

- 	    javaType = typeMapping.get(ctype);

- 	}

- 	if (javaType == null) {

- 	    throw new RuntimeException("Unsupported C type: " + ctype);

- 	}

- 	return javaType;

-    }

-}

+
+import java.util.HashMap;
+
+public class JType {
+
+    String baseType;
+    boolean isArray;
+    boolean isClass;
+
+    static HashMap<CType,JType> typeMapping = new HashMap<CType,JType>();
+    static HashMap<CType,JType> arrayTypeMapping = new HashMap<CType,JType>();
+
+    static {
+    // Primitive types
+    typeMapping.put(new CType("GLbitfield"), new JType("int"));
+    typeMapping.put(new CType("GLboolean"), new JType("boolean"));
+    typeMapping.put(new CType("GLclampf"), new JType("float"));
+    typeMapping.put(new CType("GLclampx"), new JType("int"));
+    typeMapping.put(new CType("GLenum"), new JType("int"));
+    typeMapping.put(new CType("GLfloat"), new JType("float"));
+    typeMapping.put(new CType("GLfixed"), new JType("int"));
+    typeMapping.put(new CType("GLint"), new JType("int"));
+    typeMapping.put(new CType("GLintptr"), new JType("int"));
+    typeMapping.put(new CType("GLshort"), new JType("short"));
+    typeMapping.put(new CType("GLsizei"), new JType("int"));
+    typeMapping.put(new CType("GLsizeiptr"), new JType("int"));
+    typeMapping.put(new CType("GLubyte"), new JType("byte"));
+    typeMapping.put(new CType("GLuint"), new JType("int"));
+    typeMapping.put(new CType("void"), new JType("void"));
+    typeMapping.put(new CType("GLubyte", true, true), new JType("String"));
+
+    // Untyped pointers map to untyped Buffers
+    typeMapping.put(new CType("GLvoid", true, true),
+            new JType("java.nio.Buffer", true, false));
+    typeMapping.put(new CType("GLvoid", false, true),
+            new JType("java.nio.Buffer", true, false));
+    typeMapping.put(new CType("void", false, true),
+            new JType("java.nio.Buffer", true, false));
+    typeMapping.put(new CType("GLeglImageOES", false, false),
+            new JType("java.nio.Buffer", true, false));
+
+    // Typed pointers map to typed Buffers
+    typeMapping.put(new CType("GLboolean", false, true),
+            new JType("java.nio.IntBuffer", true, false));
+    typeMapping.put(new CType("GLfixed", false, true),
+            new JType("java.nio.IntBuffer", true, false));
+    typeMapping.put(new CType("GLfixed", true, true),
+            new JType("java.nio.IntBuffer", true, false));
+    typeMapping.put(new CType("GLfloat", false, true),
+            new JType("java.nio.FloatBuffer", true, false));
+    typeMapping.put(new CType("GLfloat", true, true),
+            new JType("java.nio.FloatBuffer", true, false));
+    typeMapping.put(new CType("GLint", false, true),
+            new JType("java.nio.IntBuffer", true, false));
+    typeMapping.put(new CType("GLint", true, true),
+            new JType("java.nio.IntBuffer", true, false));
+    typeMapping.put(new CType("GLuint", false, true),
+            new JType("java.nio.IntBuffer", true, false));
+    typeMapping.put(new CType("GLuint", true, true),
+            new JType("java.nio.IntBuffer", true, false));
+    typeMapping.put(new CType("GLshort", true, true),
+            new JType("java.nio.ShortBuffer", true, false));
+
+    // Typed pointers map to arrays + offsets
+    arrayTypeMapping.put(new CType("GLboolean", false, true),
+                 new JType("boolean", false, true));
+    arrayTypeMapping.put(new CType("GLfixed", true, true), new JType("int", false, true));
+    arrayTypeMapping.put(new CType("GLfixed", false, true), new JType("int", false, true));
+    arrayTypeMapping.put(new CType("GLfloat", false, true), new JType("float", false, true));
+    arrayTypeMapping.put(new CType("GLfloat", true, true), new JType("float", false, true));
+    arrayTypeMapping.put(new CType("GLint", false, true), new JType("int", false, true));
+    arrayTypeMapping.put(new CType("GLint", true, true), new JType("int", false, true));
+    arrayTypeMapping.put(new CType("GLshort", true, true), new JType("short", false, true));
+    arrayTypeMapping.put(new CType("GLuint", false, true), new JType("int", false, true));
+    arrayTypeMapping.put(new CType("GLuint", true, true), new JType("int", false, true));
+    arrayTypeMapping.put(new CType("GLintptr"), new JType("int", false, true));
+    arrayTypeMapping.put(new CType("GLsizeiptr"), new JType("int", false, true));
+    }
+
+    public JType() {
+    }
+
+    public JType(String primitiveTypeName) {
+    this.baseType = primitiveTypeName;
+    this.isClass = false;
+    this.isArray = false;
+    }
+
+    public JType(String primitiveTypeName, boolean isClass, boolean isArray) {
+    this.baseType = primitiveTypeName;
+    this.isClass = isClass;
+    this.isArray = isArray;
+    }
+
+    public String getBaseType() {
+    return baseType;
+    }
+
+    @Override
+    public String toString() {
+    return baseType + (isArray ? "[]" : "");
+    }
+
+    public boolean isArray() {
+    return isArray;
+    }
+
+    public boolean isClass() {
+    return isClass;
+    }
+
+    public boolean isPrimitive() {
+    return !isClass() && !isArray();
+    }
+
+    public boolean isVoid() {
+    return baseType.equals("void");
+    }
+
+    public boolean isBuffer() {
+    return baseType.indexOf("Buffer") != -1;
+    }
+
+    public boolean isTypedBuffer() {
+    return !baseType.equals("java.nio.Buffer") &&
+        (baseType.indexOf("Buffer") != -1);
+    }
+
+    public static JType convert(CType ctype, boolean useArray) {
+     JType javaType = null;
+     if (useArray) {
+         javaType = arrayTypeMapping.get(ctype);
+     }
+     if (javaType == null) {
+         javaType = typeMapping.get(ctype);
+     }
+     if (javaType == null) {
+         throw new RuntimeException("Unsupported C type: " + ctype);
+     }
+     return javaType;
+    }
+}
diff --git a/opengl/tools/glgen/src/JniCodeEmitter.java b/opengl/tools/glgen/src/JniCodeEmitter.java
index 33b9a3e..7340357 100644
--- a/opengl/tools/glgen/src/JniCodeEmitter.java
+++ b/opengl/tools/glgen/src/JniCodeEmitter.java
@@ -1,99 +1,55 @@
 import java.io.PrintStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 
-/**
- * Emits a Java interface and Java & C implementation for a C function.
- *
- * <p> The Java interface will have Buffer and array variants for functions that
- * have a typed pointer argument.  The array variant will convert a single "<type> *data"
- * argument to a pair of arguments "<type>[] data, int offset".
- */
-public class JniCodeEmitter implements CodeEmitter {
+public class JniCodeEmitter {
 
-    // If true, use C++ style for calling through a JNIEnv *:
-    // env->Func(...)
-    // If false, use C style:
-    // (*env)->Func(env, ...)
     static final boolean mUseCPlusPlus = true;
-
-    boolean mUseContextPointer = true;
-
-    String mClassPathName;
-    
-    ParameterChecker mChecker;
-    PrintStream mJava10InterfaceStream;
-    PrintStream mJava10ExtInterfaceStream;
-    PrintStream mJava11InterfaceStream;
-    PrintStream mJava11ExtInterfaceStream;
-    PrintStream mJava11ExtPackInterfaceStream;
-    PrintStream mJavaImplStream;
-    PrintStream mCStream;
-
-    PrintStream mJavaInterfaceStream;
-
-    List<String> nativeRegistrations = new ArrayList<String>();
-
+    protected boolean mUseContextPointer = true;
+    protected boolean mUseStaticMethods = false;
+    protected String mClassPathName;
+    protected ParameterChecker mChecker;
+    protected List<String> nativeRegistrations = new ArrayList<String>();
     boolean needsExit;
-
-    static String indent = "    ";
-
+    protected static String indent = "    ";
     HashSet<String> mFunctionsEmitted = new HashSet<String>();
 
-    /**
-     * @param java10InterfaceStream the PrintStream to which to emit the Java interface for GL 1.0 functions
-     * @param java10ExtInterfaceStream the PrintStream to which to emit the Java interface for GL 1.0 extension functions
-     * @param java11InterfaceStream the PrintStream to which to emit the Java interface for GL 1.1 functions 
-     * @param java11ExtInterfaceStream the PrintStream to which to emit the Java interface for GL 1.1 Extension functions
-     * @param java11ExtPackInterfaceStream the PrintStream to which to emit the Java interface for GL 1.1 Extension Pack functions
-     * @param javaImplStream the PrintStream to which to emit the Java implementation
-     * @param cStream the PrintStream to which to emit the C implementation
-     */
-    public JniCodeEmitter(String classPathName,
-                          ParameterChecker checker,
-                          PrintStream java10InterfaceStream,
-                          PrintStream java10ExtInterfaceStream,
-                          PrintStream java11InterfaceStream,
-                          PrintStream java11ExtInterfaceStream,
-                          PrintStream java11ExtPackInterfaceStream,
-                          PrintStream javaImplStream,
-                          PrintStream cStream,
-                          boolean useContextPointer) {
-        mClassPathName = classPathName;
-        mChecker = checker;
-        mJava10InterfaceStream = java10InterfaceStream;
-        mJava10ExtInterfaceStream = java10ExtInterfaceStream;
-        mJava11InterfaceStream = java11InterfaceStream;
-        mJava11ExtInterfaceStream = java11ExtInterfaceStream;
-        mJava11ExtPackInterfaceStream = java11ExtPackInterfaceStream;
-        mJavaImplStream = javaImplStream;
-        mCStream = cStream;
-        mUseContextPointer = useContextPointer;
-    }
-
-    public void setVersion(int version, boolean ext, boolean pack) {
-        if (version == 0) {
-            mJavaInterfaceStream = ext ? mJava10ExtInterfaceStream :
-                mJava10InterfaceStream;
-        } else if (version == 1) {
-            mJavaInterfaceStream = ext ?
-                (pack ? mJava11ExtPackInterfaceStream :
-                 mJava11ExtInterfaceStream) :
-                mJava11InterfaceStream;
-        } else {
-            throw new RuntimeException("Bad version: " + version);
+    public static String getJniName(JType jType) {
+        String jniName = "";
+        if (jType.isClass()) {
+            return "L" + jType.getBaseType() + ";";
+        } else if (jType.isArray()) {
+            jniName = "[";
         }
+
+        String baseType = jType.getBaseType();
+        if (baseType.equals("int")) {
+            jniName += "I";
+        } else if (baseType.equals("float")) {
+            jniName += "F";
+        } else if (baseType.equals("boolean")) {
+            jniName += "Z";
+        } else if (baseType.equals("short")) {
+            jniName += "S";
+        } else if (baseType.equals("long")) {
+            jniName += "L";
+        } else if (baseType.equals("byte")) {
+            jniName += "B";
+        }
+        return jniName;
     }
 
-    public void emitCode(CFunc cfunc, String original) {
+
+    public void emitCode(CFunc cfunc, String original,
+            PrintStream javaInterfaceStream,
+            PrintStream javaImplStream,
+            PrintStream cStream) {
         JFunc jfunc;
         String signature;
         boolean duplicate;
-        
+
         if (cfunc.hasTypedPointerArg()) {
             jfunc = JFunc.convert(cfunc, true);
 
@@ -109,12 +65,14 @@
             }
 
             if (!duplicate) {
-                emitNativeDeclaration(jfunc, mJavaImplStream);
-                emitJavaCode(jfunc, mJavaImplStream);
+                emitNativeDeclaration(jfunc, javaImplStream);
+                emitJavaCode(jfunc, javaImplStream);
             }
-            emitJavaInterfaceCode(jfunc, mJavaInterfaceStream);
+            if (javaInterfaceStream != null) {
+                emitJavaInterfaceCode(jfunc, javaInterfaceStream);
+            }
             if (!duplicate) {
-                emitJniCode(jfunc, mCStream);
+                emitJniCode(jfunc, cStream);
             }
         }
 
@@ -129,12 +87,14 @@
         }
 
         if (!duplicate) {
-            emitNativeDeclaration(jfunc, mJavaImplStream);
+            emitNativeDeclaration(jfunc, javaImplStream);
         }
-        emitJavaInterfaceCode(jfunc, mJavaInterfaceStream);
+        if (javaInterfaceStream != null) {
+            emitJavaInterfaceCode(jfunc, javaInterfaceStream);
+        }
         if (!duplicate) {
-            emitJavaCode(jfunc, mJavaImplStream);
-            emitJniCode(jfunc, mCStream);
+            emitJavaCode(jfunc, javaImplStream);
+            emitJniCode(jfunc, cStream);
         }
     }
 
@@ -152,8 +112,8 @@
     public void emitJavaCode(JFunc jfunc, PrintStream out) {
         emitFunction(jfunc, out, false, false);
     }
-    
-    void emitFunctionCall(JFunc jfunc, PrintStream out, String iii, boolean grabArray ) {
+
+    void emitFunctionCall(JFunc jfunc, PrintStream out, String iii, boolean grabArray) {
         boolean isVoid = jfunc.getType().isVoid();
         boolean isPointerFunc = jfunc.getName().endsWith("Pointer") &&
             jfunc.getCFunc().hasPointerArg();
@@ -167,7 +127,7 @@
                     jfunc.getName() +
                     (isPointerFunc ? "Bounds" : "" ) +
                     "(");
-	
+
         int numArgs = jfunc.getNumArgs();
         for (int i = 0; i < numArgs; i++) {
             String argName = jfunc.getArgName(i);
@@ -177,7 +137,7 @@
                 String typeName = argType.getBaseType();
                 typeName = typeName.substring(9, typeName.length() - 6);
                 out.println(iii + indent + "get" + typeName + "Array(" + argName + "),");
-                out.print(iii + indent + "getOffset(" + argName + ")"); 
+                out.print(iii + indent + "getOffset(" + argName + ")");
             } else {
                 out.print(iii + indent + argName);
             }
@@ -192,41 +152,40 @@
                 out.println(",");
             }
         }
-	
+
         out.println(iii + ");");
     }
 
-    void printIfcheckPostamble(PrintStream out, boolean isBuffer,
-                               boolean emitExceptionCheck, String iii) {
-        printIfcheckPostamble(out, isBuffer, emitExceptionCheck,
-                              "offset", "_remaining", iii);
-    }
+    void printIfcheckPostamble(PrintStream out, boolean isBuffer, boolean emitExceptionCheck,
+            String iii) {
+                printIfcheckPostamble(out, isBuffer, emitExceptionCheck,
+                                      "offset", "_remaining", iii);
+            }
 
-    void printIfcheckPostamble(PrintStream out, boolean isBuffer,
-                               boolean emitExceptionCheck,
-                               String offset, String remaining, String iii) {
-        out.println(iii + "    default:");
-        out.println(iii + "        _needed = 0;");
-        out.println(iii + "        break;");
-        out.println(iii + "}");
+    void printIfcheckPostamble(PrintStream out, boolean isBuffer, boolean emitExceptionCheck,
+            String offset, String remaining, String iii) {
+                out.println(iii + "    default:");
+                out.println(iii + "        _needed = 0;");
+                out.println(iii + "        break;");
+                out.println(iii + "}");
 
-        out.println(iii + "if (" + remaining + " < _needed) {");
-        if (emitExceptionCheck) {
-            out.println(iii + indent + "_exception = 1;");
-        }
-        out.println(iii + indent +
-                    (mUseCPlusPlus ? "_env" : "(*_env)") +
-                    "->ThrowNew(" +
-                    (mUseCPlusPlus ? "" : "_env, ") +
-                    "IAEClass, " +
-                    "\"" +
-                    (isBuffer ? 
-                     "remaining()" : "length - " + offset) +
-                    " < needed\");");
-        out.println(iii + indent + "goto exit;");
-        needsExit = true;
-        out.println(iii + "}");
-    }
+                out.println(iii + "if (" + remaining + " < _needed) {");
+                if (emitExceptionCheck) {
+                    out.println(iii + indent + "_exception = 1;");
+                }
+                out.println(iii + indent +
+                            (mUseCPlusPlus ? "_env" : "(*_env)") +
+                            "->ThrowNew(" +
+                            (mUseCPlusPlus ? "" : "_env, ") +
+                            "IAEClass, " +
+                            "\"" +
+                            (isBuffer ?
+                             "remaining()" : "length - " + offset) +
+                            " < needed\");");
+                out.println(iii + indent + "goto exit;");
+                needsExit = true;
+                out.println(iii + "}");
+            }
 
     boolean isNullAllowed(CFunc cfunc) {
         String[] checks = mChecker.getChecks(cfunc.getName());
@@ -312,115 +271,106 @@
     }
 
     void emitNativeBoundsChecks(CFunc cfunc, String cname, PrintStream out,
-                                boolean isBuffer, boolean emitExceptionCheck,
-                                String offset, String remaining, String iii) {
-        CType returnType = cfunc.getType();
-        boolean isVoid = returnType.isVoid();
+            boolean isBuffer, boolean emitExceptionCheck, String offset, String remaining, String iii) {
 
-        String[] checks = mChecker.getChecks(cfunc.getName());
-        String checkVar;
-        String retval = getErrorReturnValue(cfunc);
+                String[] checks = mChecker.getChecks(cfunc.getName());
 
-        boolean lastWasIfcheck = false;
+                boolean lastWasIfcheck = false;
 
-        int index = 1;
-        if (checks != null) {
-            boolean remainingDeclared = false;
-            boolean nullCheckDeclared = false;
-            boolean offsetChecked = false;
-            while (index < checks.length) {
-                if (checks[index].startsWith("check")) {
-                    if (lastWasIfcheck) {
-                        printIfcheckPostamble(out, isBuffer, emitExceptionCheck,
-                                              offset, remaining, iii);
+                int index = 1;
+                if (checks != null) {
+                    while (index < checks.length) {
+                        if (checks[index].startsWith("check")) {
+                            if (lastWasIfcheck) {
+                                printIfcheckPostamble(out, isBuffer, emitExceptionCheck,
+                                                      offset, remaining, iii);
+                            }
+                            lastWasIfcheck = false;
+                            if (cname != null && !cname.equals(checks[index + 1])) {
+                                index += 3;
+                                continue;
+                            }
+                            out.println(iii + "if (" + remaining + " < " +
+                                        checks[index + 2] +
+                                        ") {");
+                            if (emitExceptionCheck) {
+                                out.println(iii + indent + "_exception = 1;");
+                            }
+                    String exceptionClassName = "IAEClass";
+                    // If the "check" keyword was of the form
+                    // "check_<class name>", use the class name in the
+                    // exception to be thrown
+                    int underscore = checks[index].indexOf('_');
+                    if (underscore >= 0) {
+                    exceptionClassName = checks[index].substring(underscore + 1) + "Class";
                     }
-                    lastWasIfcheck = false;
-                    if (cname != null && !cname.equals(checks[index + 1])) {
-                        index += 3;
-                        continue;
-                    }
-                    out.println(iii + "if (" + remaining + " < " +
-                                checks[index + 2] +
-                                ") {");
-                    if (emitExceptionCheck) {
-                        out.println(iii + indent + "_exception = 1;");
-                    }
-		    String exceptionClassName = "IAEClass";
-		    // If the "check" keyword was of the form
-		    // "check_<class name>", use the class name in the
-		    // exception to be thrown
-		    int underscore = checks[index].indexOf('_');
-		    if (underscore >= 0) {
-			exceptionClassName = checks[index].substring(underscore + 1) + "Class";
-		    }
-                    out.println(iii + indent +
-                                (mUseCPlusPlus ? "_env" : "(*_env)") +
-                                "->ThrowNew(" +
-                                (mUseCPlusPlus ? "" : "_env, ") +
-				exceptionClassName + ", " +
-                                "\"" +
-                                (isBuffer ? 
-                                 "remaining()" : "length - " + offset) +
-                                " < " + checks[index + 2] +
-                                "\");");
+                            out.println(iii + indent +
+                                        (mUseCPlusPlus ? "_env" : "(*_env)") +
+                                        "->ThrowNew(" +
+                                        (mUseCPlusPlus ? "" : "_env, ") +
+                        exceptionClassName + ", " +
+                                        "\"" +
+                                        (isBuffer ?
+                                         "remaining()" : "length - " + offset) +
+                                        " < " + checks[index + 2] +
+                                        "\");");
 
-                    out.println(iii + indent + "goto exit;");
-                    needsExit = true;
-                    out.println(iii + "}");
-                
-                    index += 3;
-                } else if (checks[index].equals("ifcheck")) {
-                    String[] matches = checks[index + 4].split(",");
+                            out.println(iii + indent + "goto exit;");
+                            needsExit = true;
+                            out.println(iii + "}");
 
-                    if (!lastWasIfcheck) {
-                        out.println(iii + "int _needed;");
-                        out.println(iii +
-                                    "switch (" +
-                                    checks[index + 3] +
-                                    ") {");
+                            index += 3;
+                        } else if (checks[index].equals("ifcheck")) {
+                            String[] matches = checks[index + 4].split(",");
+
+                            if (!lastWasIfcheck) {
+                                out.println(iii + "int _needed;");
+                                out.println(iii +
+                                            "switch (" +
+                                            checks[index + 3] +
+                                            ") {");
+                            }
+
+                            for (int i = 0; i < matches.length; i++) {
+                                out.println("#if defined(" + matches[i] + ")");
+                                out.println(iii +
+                                            "    case " +
+                                            matches[i] +
+                                            ":");
+                                out.println("#endif // defined(" + matches[i] + ")");
+                            }
+                            out.println(iii +
+                                        "        _needed = " +
+                                        checks[index + 2] +
+                                        ";");
+                            out.println(iii +
+                                        "        break;");
+
+                            lastWasIfcheck = true;
+                            index += 5;
+                        } else if (checks[index].equals("return")) {
+                            // ignore
+                            index += 2;
+                        } else if (checks[index].equals("unsupported")) {
+                            // ignore
+                            index += 1;
+                        } else if (checks[index].equals("nullAllowed")) {
+                            // ignore
+                            index += 1;
+                        } else {
+                            System.out.println("Error: unknown keyword \"" +
+                                               checks[index] + "\"");
+                            System.exit(0);
+                        }
                     }
-                    
-                    for (int i = 0; i < matches.length; i++) {
-                        out.println("#if defined(" + matches[i] + ")");
-                        out.println(iii +
-                                    "    case " +
-                                    matches[i] +
-                                    ":");
-                        out.println("#endif // defined(" + matches[i] + ")");
-                    }
-                    out.println(iii +
-                                "        _needed = " +
-                                checks[index + 2] +
-                                ";");
-                    out.println(iii +
-                                "        break;");
-                
-                    lastWasIfcheck = true;
-                    index += 5;
-                } else if (checks[index].equals("return")) {
-                    // ignore
-                    index += 2;
-                } else if (checks[index].equals("unsupported")) {
-                    // ignore
-                    index += 1;
-                } else if (checks[index].equals("nullAllowed")) {
-                    // ignore
-                    index += 1;
-                } else {
-                    System.out.println("Error: unknown keyword \"" +
-                                       checks[index] + "\"");
-                    System.exit(0);
+                }
+
+                if (lastWasIfcheck) {
+                    printIfcheckPostamble(out, isBuffer, emitExceptionCheck, iii);
                 }
             }
-        }
 
-        if (lastWasIfcheck) {
-            printIfcheckPostamble(out, isBuffer, emitExceptionCheck, iii);
-        }
-    }
-
-    boolean hasNonConstArg(JFunc jfunc, CFunc cfunc,
-        List<Integer> nonPrimitiveArgs) {
+    boolean hasNonConstArg(JFunc jfunc, CFunc cfunc, List<Integer> nonPrimitiveArgs) {
         if (nonPrimitiveArgs.size() > 0) {
             for (int i = nonPrimitiveArgs.size() - 1; i >= 0; i--) {
                 int idx = nonPrimitiveArgs.get(i).intValue();
@@ -439,7 +389,7 @@
 
         return false;
     }
-    
+
     /**
      * Emit a function in several variants:
      *
@@ -449,9 +399,7 @@
      *   if interfaceDecl:  public <returntype> func(args);
      *   if !interfaceDecl: public <returntype> func(args) { body }
      */
-    void emitFunction(JFunc jfunc,
-                      PrintStream out,
-                      boolean nativeDecl, boolean interfaceDecl) {
+    void emitFunction(JFunc jfunc, PrintStream out, boolean nativeDecl, boolean interfaceDecl) {
         boolean isPointerFunc =
             jfunc.getName().endsWith("Pointer") &&
             jfunc.getCFunc().hasPointerArg();
@@ -462,28 +410,30 @@
             return;
         }
 
+        String maybeStatic = mUseStaticMethods ? "static " : "";
+
         if (isPointerFunc) {
             out.println(indent +
-                        (nativeDecl ? "private native " :
-                         (interfaceDecl ? "" : "public ")) +
+                        (nativeDecl ? "private " + maybeStatic +"native " :
+                         (interfaceDecl ? "" : "public ") + maybeStatic) +
                         jfunc.getType() + " " +
                         jfunc.getName() +
                         (nativeDecl ? "Bounds" : "") +
                         "(");
         } else {
             out.println(indent +
-                        (nativeDecl ? "public native " :
-                         (interfaceDecl ? "" : "public ")) +
+                        (nativeDecl ? "public " + maybeStatic +"native " :
+                         (interfaceDecl ? "" : "public ") + maybeStatic) +
                         jfunc.getType() + " " +
                         jfunc.getName() +
                         "(");
         }
-	
+
         int numArgs = jfunc.getNumArgs();
         for (int i = 0; i < numArgs; i++) {
             String argName = jfunc.getArgName(i);
             JType argType = jfunc.getArgType(i);
-	    
+
             out.print(indent + indent + argType + " " + argName);
             if (i == numArgs - 1) {
                 if (isPointerFunc && nativeDecl) {
@@ -504,6 +454,15 @@
 
             String iii = indent + indent;
 
+            // emitBoundsChecks(jfunc, out, iii);
+            emitFunctionCall(jfunc, out, iii, false);
+
+            // Set the pointer after we call the native code, so that if
+            // the native code throws an exception we don't modify the
+            // pointer. We assume that the native code is written so that
+            // if an exception is thrown, then the underlying glXXXPointer
+            // function will not have been called.
+
             String fname = jfunc.getName();
             if (isPointerFunc) {
                 // TODO - deal with VBO variants
@@ -548,9 +507,6 @@
                 }
             }
 
-            // emitBoundsChecks(jfunc, out, iii);
-            emitFunctionCall(jfunc, out, iii, false);
-
             boolean isVoid = jfunc.getType().isVoid();
 
             if (!isVoid) {
@@ -561,29 +517,44 @@
         out.println();
     }
 
-    public static String getJniName(JType jType) {
-        String jniName = "";
-        if (jType.isClass()) {
-            return "L" + jType.getBaseType() + ";";
-        } else if (jType.isArray()) {
-            jniName = "[";
+    public void addNativeRegistration(String s) {
+        nativeRegistrations.add(s);
+    }
+
+    public void emitNativeRegistration(String registrationFunctionName,
+            PrintStream cStream) {
+        cStream.println("static const char *classPathName = \"" +
+                        mClassPathName +
+                        "\";");
+        cStream.println();
+
+        cStream.println("static JNINativeMethod methods[] = {");
+
+        cStream.println("{\"_nativeClassInit\", \"()V\", (void*)nativeClassInit },");
+
+        Iterator<String> i = nativeRegistrations.iterator();
+        while (i.hasNext()) {
+            cStream.println(i.next());
         }
-	
-        String baseType = jType.getBaseType();
-        if (baseType.equals("int")) {
-            jniName += "I";
-        } else if (baseType.equals("float")) {
-            jniName += "F";
-        } else if (baseType.equals("boolean")) {
-            jniName += "Z";
-        } else if (baseType.equals("short")) {
-            jniName += "S";
-        } else if (baseType.equals("long")) {
-            jniName += "L";
-        } else if (baseType.equals("byte")) {
-            jniName += "B";
-        }
-        return jniName;
+
+        cStream.println("};");
+        cStream.println();
+
+
+        cStream.println("int " + registrationFunctionName + "(JNIEnv *_env)");
+        cStream.println("{");
+        cStream.println(indent +
+                        "int err;");
+
+        cStream.println(indent +
+                        "err = android::AndroidRuntime::registerNativeMethods(_env, classPathName, methods, NELEM(methods));");
+
+        cStream.println(indent + "return err;");
+        cStream.println("}");
+    }
+
+    public JniCodeEmitter() {
+        super();
     }
 
     String getJniType(JType jType) {
@@ -604,7 +575,7 @@
             return "jobject";
         }
     }
-    
+
     String getJniMangledName(String name) {
         name = name.replaceAll("_", "_1");
         name = name.replaceAll(";", "_2");
@@ -614,7 +585,7 @@
 
     public void emitJniCode(JFunc jfunc, PrintStream out) {
         CFunc cfunc = jfunc.getCFunc();
-	
+
         // Emit comment identifying original C function
         //
         // Example:
@@ -658,13 +629,13 @@
         }
 
         // Append signature to function name
-        String sig = getJniMangledName(signature).replace('.', '_');        
+        String sig = getJniMangledName(signature).replace('.', '_');
         out.print("__" + sig);
         outName += "__" + sig;
-	
+
         signature = signature.replace('.', '/');
         rsignature = rsignature.replace('.', '/');
-	
+
         out.println();
         if (rsignature.length() == 0) {
             rsignature = "V";
@@ -718,13 +689,11 @@
             out.print(", jint remaining");
         }
         out.println(") {");
-	
+
         int numArrays = 0;
         int numBuffers = 0;
         for (int i = 0; i < nonPrimitiveArgs.size(); i++) {
             int idx = nonPrimitiveArgs.get(i).intValue();
-            int cIndex = jfunc.getArgCIndex(idx);
-            String cname = cfunc.getArgName(cIndex);
             if (jfunc.getArgType(idx).isArray()) {
                 ++numArrays;
             }
@@ -740,7 +709,7 @@
         // Example:
         //
         // android::gl::ogles_context_t *ctx;
-        // 
+        //
         // jint _exception;
         // GLenum _returnValue;
         //
@@ -827,15 +796,13 @@
                 out.println(indent +
                             decl +
                             (decl.endsWith("*") ? "" : " ") +
-                            jfunc.getArgName(idx) + 
+                            jfunc.getArgName(idx) +
                             " = (" + decl + ") 0;");
             }
 
             out.println();
         }
 
-        String retval = isVoid ? "" : " _returnValue";
-
         // Emit 'GetPrimitiveArrayCritical' for arrays
         // Emit 'GetPointer' calls for Buffer pointers
         int bufArgIdx = 0;
@@ -843,7 +810,7 @@
             for (int i = 0; i < nonPrimitiveArgs.size(); i++) {
                 int idx = nonPrimitiveArgs.get(i).intValue();
                 int cIndex = jfunc.getArgCIndex(idx);
-		
+
                 String cname = cfunc.getArgName(cIndex);
                 offset = numArrays <= 1 ? "offset" :
                     cname + "Offset";
@@ -852,7 +819,7 @@
 
                 if (jfunc.getArgType(idx).isArray()) {
                     out.println(indent +
-                                "if (!" + 
+                                "if (!" +
                                 cname +
                                 "_ref) {");
                     if (emitExceptionCheck) {
@@ -884,7 +851,7 @@
                     out.println(indent + "}");
 
                     out.println(indent + remaining + " = " +
-                                    (mUseCPlusPlus ? "_env" : "(*_env)") + 
+                                    (mUseCPlusPlus ? "_env" : "(*_env)") +
                                     "->GetArrayLength(" +
                                     (mUseCPlusPlus ? "" : "_env, ") +
                                     cname + "_ref) - " + offset + ";");
@@ -901,7 +868,7 @@
                     out.println(indent + "    " +
                                 (mUseCPlusPlus ? "_env" : "(*_env)") +
                                 "->GetPrimitiveArrayCritical(" +
-                                (mUseCPlusPlus ? "" : "_env, ") + 
+                                (mUseCPlusPlus ? "" : "_env, ") +
                                 jfunc.getArgName(idx) +
                                 "_ref, (jboolean *)0);");
                     out.println(indent +
@@ -912,19 +879,33 @@
                     String array = numBufferArgs <= 1 ? "_array" :
                         "_" + bufferArgNames.get(bufArgIdx++) + "Array";
 
-                    boolean nullAllowed = isNullAllowed(cfunc);
+                    boolean nullAllowed = isNullAllowed(cfunc) || isPointerFunc;
                     if (nullAllowed) {
                         out.println(indent + "if (" + cname + "_buf) {");
                         out.print(indent);
                     }
-                    
-                    out.println(indent +
+
+                    if (isPointerFunc) {
+                        out.println(indent +
                                 cname +
                                 " = (" +
                                 cfunc.getArgType(cIndex).getDeclaration() +
-                                ")getPointer(_env, " +
-                                cname +
-                                "_buf, &" + array + ", &" + remaining + ");");
+                                ") getDirectBufferPointer(_env, " +
+                                cname + "_buf);");
+                        String iii = "    ";
+                        out.println(iii + indent + "if ( ! " + cname + " ) {");	
+                        out.println(iii + iii + indent + "return;");
+                        out.println(iii + indent + "}");
+                    } else {
+                        out.println(indent +
+                                    cname +
+                                    " = (" +
+                                    cfunc.getArgType(cIndex).getDeclaration() +
+                                    ")getPointer(_env, " +
+                                    cname +
+                                    "_buf, &" + array + ", &" + remaining +
+                                    ");");
+                    }
 
                     if (nullAllowed) {
                         out.println(indent + "}");
@@ -950,10 +931,10 @@
                 name.substring(1, name.length());
             out.print("ctx->procs.");
         }
-        
+
         out.print(name + (isPointerFunc ? "Bounds" : "") + "(");
 
-        numArgs = cfunc.getNumArgs();    
+        numArgs = cfunc.getNumArgs();
         if (numArgs == 0) {
             if (mUseContextPointer) {
                 out.println("ctx);");
@@ -1006,7 +987,7 @@
 
                 int cIndex = jfunc.getArgCIndex(idx);
                 if (jfunc.getArgType(idx).isArray()) {
-		    
+
                     // If the argument is 'const', GL will not write to it.
                     // In this case, we can use the 'JNI_ABORT' flag to avoid
                     // the need to write back to the Java array
@@ -1015,7 +996,7 @@
                     out.println(indent + indent +
                                 (mUseCPlusPlus ? "_env" : "(*_env)") +
                                 "->ReleasePrimitiveArrayCritical(" +
-                                (mUseCPlusPlus ? "" : "_env, ") + 
+                                (mUseCPlusPlus ? "" : "_env, ") +
                                 jfunc.getArgName(idx) + "_ref, " +
                                 cfunc.getArgName(cIndex) +
                                 "_base,");
@@ -1026,17 +1007,20 @@
                                 ");");
                     out.println(indent + "}");
                 } else if (jfunc.getArgType(idx).isBuffer()) {
-                    String array = numBufferArgs <= 1 ? "_array" :
-                        "_" + bufferArgNames.get(bufArgIdx++) + "Array";
-                    out.println(indent + "if (" + array + ") {");
-                    out.println(indent + indent +
-                                "releasePointer(_env, " + array + ", " +
-                                cfunc.getArgName(cIndex) +
-                                ", " +
-                                (cfunc.getArgType(cIndex).isConst() ?
-                                 "JNI_FALSE" : "_exception ? JNI_FALSE : JNI_TRUE") +
-                                ");");
-                    out.println(indent + "}");
+                    if (! isPointerFunc) {
+                        String array = numBufferArgs <= 1 ? "_array" :
+                            "_" + bufferArgNames.get(bufArgIdx++) + "Array";
+                        out.println(indent + "if (" + array + ") {");
+                        out.println(indent + indent +
+                                    "releasePointer(_env, " + array + ", " +
+                                    cfunc.getArgName(cIndex) +
+                                    ", " +
+                                    (cfunc.getArgType(cIndex).isConst() ?
+                                     "JNI_FALSE" : "_exception ? JNI_FALSE :" +
+                                             " JNI_TRUE") +
+                                    ");");
+                        out.println(indent + "}");
+                    }
                 }
             }
         }
@@ -1049,38 +1033,4 @@
         out.println();
     }
 
-    public void addNativeRegistration(String s) {
-        nativeRegistrations.add(s);
-    }
-
-    public void emitNativeRegistration() {
-        mCStream.println("static const char *classPathName = \"" +
-                        mClassPathName +
-                        "\";");
-        mCStream.println();
-
-        mCStream.println("static JNINativeMethod methods[] = {");
-
-        mCStream.println("{\"_nativeClassInit\", \"()V\", (void*)nativeClassInit },");
-
-        Iterator<String> i = nativeRegistrations.iterator();
-        while (i.hasNext()) {
-            mCStream.println(i.next());
-        }
-
-        mCStream.println("};");
-        mCStream.println();
-    
-
-        mCStream.println("int register_com_google_android_gles_jni_GLImpl(JNIEnv *_env)");
-        mCStream.println("{");
-        mCStream.println(indent +
-                        "int err;");
-
-        mCStream.println(indent +
-                        "err = android::AndroidRuntime::registerNativeMethods(_env, classPathName, methods, NELEM(methods));");
-
-        mCStream.println(indent + "return err;");
-        mCStream.println("}");
-    }
 }
diff --git a/opengl/tools/glgen/src/Jsr239CodeEmitter.java b/opengl/tools/glgen/src/Jsr239CodeEmitter.java
new file mode 100644
index 0000000..335d226
--- /dev/null
+++ b/opengl/tools/glgen/src/Jsr239CodeEmitter.java
@@ -0,0 +1,74 @@
+import java.io.PrintStream;
+
+/**
+ * Emits a Java interface and Java & C implementation for a C function.
+ *
+ * <p> The Java interface will have Buffer and array variants for functions that
+ * have a typed pointer argument.  The array variant will convert a single "<type> *data"
+ * argument to a pair of arguments "<type>[] data, int offset".
+ */
+public class Jsr239CodeEmitter extends JniCodeEmitter implements CodeEmitter {
+
+    PrintStream mJava10InterfaceStream;
+    PrintStream mJava10ExtInterfaceStream;
+    PrintStream mJava11InterfaceStream;
+    PrintStream mJava11ExtInterfaceStream;
+    PrintStream mJava11ExtPackInterfaceStream;
+    PrintStream mJavaImplStream;
+    PrintStream mCStream;
+
+    PrintStream mJavaInterfaceStream;
+
+    /**
+     * @param java10InterfaceStream the PrintStream to which to emit the Java interface for GL 1.0 functions
+     * @param java10ExtInterfaceStream the PrintStream to which to emit the Java interface for GL 1.0 extension functions
+     * @param java11InterfaceStream the PrintStream to which to emit the Java interface for GL 1.1 functions
+     * @param java11ExtInterfaceStream the PrintStream to which to emit the Java interface for GL 1.1 Extension functions
+     * @param java11ExtPackInterfaceStream the PrintStream to which to emit the Java interface for GL 1.1 Extension Pack functions
+     * @param javaImplStream the PrintStream to which to emit the Java implementation
+     * @param cStream the PrintStream to which to emit the C implementation
+     */
+    public Jsr239CodeEmitter(String classPathName,
+                          ParameterChecker checker,
+                          PrintStream java10InterfaceStream,
+                          PrintStream java10ExtInterfaceStream,
+                          PrintStream java11InterfaceStream,
+                          PrintStream java11ExtInterfaceStream,
+                          PrintStream java11ExtPackInterfaceStream,
+                          PrintStream javaImplStream,
+                          PrintStream cStream,
+                          boolean useContextPointer) {
+        mClassPathName = classPathName;
+        mChecker = checker;
+        mJava10InterfaceStream = java10InterfaceStream;
+        mJava10ExtInterfaceStream = java10ExtInterfaceStream;
+        mJava11InterfaceStream = java11InterfaceStream;
+        mJava11ExtInterfaceStream = java11ExtInterfaceStream;
+        mJava11ExtPackInterfaceStream = java11ExtPackInterfaceStream;
+        mJavaImplStream = javaImplStream;
+        mCStream = cStream;
+        mUseContextPointer = useContextPointer;
+    }
+
+    public void setVersion(int version, boolean ext, boolean pack) {
+        if (version == 0) {
+            mJavaInterfaceStream = ext ? mJava10ExtInterfaceStream :
+                mJava10InterfaceStream;
+        } else if (version == 1) {
+            mJavaInterfaceStream = ext ?
+                (pack ? mJava11ExtPackInterfaceStream :
+                 mJava11ExtInterfaceStream) :
+                mJava11InterfaceStream;
+        } else {
+            throw new RuntimeException("Bad version: " + version);
+        }
+    }
+
+    public void emitCode(CFunc cfunc, String original) {
+        emitCode(cfunc, original, mJavaInterfaceStream, mJavaImplStream, mCStream);
+    }
+
+    public void emitNativeRegistration() {
+        emitNativeRegistration("register_com_google_android_gles_jni_GLImpl", mCStream);
+    }
+}
diff --git a/opengl/tools/glgen/stubs/GLImplHeader.java-impl b/opengl/tools/glgen/stubs/GLImplHeader.java-impl
deleted file mode 100644
index db3a41c..0000000
--- a/opengl/tools/glgen/stubs/GLImplHeader.java-impl
+++ /dev/null
@@ -1,48 +0,0 @@
-**
-** 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 source file is automatically generated
-
-package com.google.android.gles_jni;
-
-import java.nio.Buffer;
-import javax.microedition.khronos.opengles.GL10;
-import javax.microedition.khronos.opengles.GL10Ext;
-import javax.microedition.khronos.opengles.GL11;
-import javax.microedition.khronos.opengles.GL11Ext;
-import javax.microedition.khronos.opengles.GL11ExtensionPack;
-
-public class GLImpl implements GL10, GL10Ext, GL11, GL11Ext, GL11ExtensionPack {
-
-    // Private accessors for native code
-
-    native private static void _nativeClassInit();
-    static {
-	_nativeClassInit();
-    }
-
-    Buffer _colorPointer = null;
-    Buffer _normalPointer = null;
-    Buffer _texCoordPointer = null;
-    Buffer _vertexPointer = null;
-
-    public GLImpl() {
-    }
-
-     public void glGetPointerv(int pname, java.nio.Buffer[] params) {
-         throw new UnsupportedOperationException("glGetPointerv");
-     }
-
diff --git a/opengl/tools/glgen/stubs/gles11/GLES10ExtHeader.java-if b/opengl/tools/glgen/stubs/gles11/GLES10ExtHeader.java-if
new file mode 100644
index 0000000..42891ea
--- /dev/null
+++ b/opengl/tools/glgen/stubs/gles11/GLES10ExtHeader.java-if
@@ -0,0 +1,26 @@
+**
+** 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.
+*/
+
+// This source file is automatically generated
+
+package android.opengl;
+
+public class GLES10Ext {
+    native private static void _nativeClassInit();
+    static {
+	    _nativeClassInit();
+    }
+    
\ No newline at end of file
diff --git a/opengl/tools/glgen/stubs/GLCHeader.cpp b/opengl/tools/glgen/stubs/gles11/GLES10ExtcHeader.cpp
similarity index 94%
rename from opengl/tools/glgen/stubs/GLCHeader.cpp
rename to opengl/tools/glgen/stubs/gles11/GLES10ExtcHeader.cpp
index 6495686..294d1ce 100644
--- a/opengl/tools/glgen/stubs/GLCHeader.cpp
+++ b/opengl/tools/glgen/stubs/gles11/GLES10ExtcHeader.cpp
@@ -1,5 +1,5 @@
 **
-** Copyright 2006, The Android Open Source Project
+** 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. 
@@ -21,11 +21,7 @@
 
 #include <assert.h>
 #include <GLES/gl.h>
-
-#include <private/opengles/gl_context.h>
-
-#define _NUM_COMPRESSED_TEXTURE_FORMATS \
-        (::android::OGLES_NUM_COMPRESSED_TEXTURE_FORMATS)
+#include <GLES/glext.h>
 
 static int initialized = 0;
 
@@ -44,7 +40,7 @@
 
 /* Cache method IDs each time the class is loaded. */
 
-void
+static void
 nativeClassInitBuffer(JNIEnv *_env)
 {
     jclass nioAccessClassLocal = _env->FindClass("java/nio/NIOAccess");
diff --git a/opengl/tools/glgen/stubs/gles11/GLES10Header.java-if b/opengl/tools/glgen/stubs/gles11/GLES10Header.java-if
new file mode 100644
index 0000000..4b2a831
--- /dev/null
+++ b/opengl/tools/glgen/stubs/gles11/GLES10Header.java-if
@@ -0,0 +1,271 @@
+**
+** 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.
+*/
+
+// This source file is automatically generated
+
+package android.opengl;
+
+import java.nio.Buffer;
+
+public class GLES10 {
+    public static final int GL_ADD                                   = 0x0104;
+    public static final int GL_ALIASED_LINE_WIDTH_RANGE              = 0x846E;
+    public static final int GL_ALIASED_POINT_SIZE_RANGE              = 0x846D;
+    public static final int GL_ALPHA                                 = 0x1906;
+    public static final int GL_ALPHA_BITS                            = 0x0D55;
+    public static final int GL_ALPHA_TEST                            = 0x0BC0;
+    public static final int GL_ALWAYS                                = 0x0207;
+    public static final int GL_AMBIENT                               = 0x1200;
+    public static final int GL_AMBIENT_AND_DIFFUSE                   = 0x1602;
+    public static final int GL_AND                                   = 0x1501;
+    public static final int GL_AND_INVERTED                          = 0x1504;
+    public static final int GL_AND_REVERSE                           = 0x1502;
+    public static final int GL_BACK                                  = 0x0405;
+    public static final int GL_BLEND                                 = 0x0BE2;
+    public static final int GL_BLUE_BITS                             = 0x0D54;
+    public static final int GL_BYTE                                  = 0x1400;
+    public static final int GL_CCW                                   = 0x0901;
+    public static final int GL_CLAMP_TO_EDGE                         = 0x812F;
+    public static final int GL_CLEAR                                 = 0x1500;
+    public static final int GL_COLOR_ARRAY                           = 0x8076;
+    public static final int GL_COLOR_BUFFER_BIT                      = 0x4000;
+    public static final int GL_COLOR_LOGIC_OP                        = 0x0BF2;
+    public static final int GL_COLOR_MATERIAL                        = 0x0B57;
+    public static final int GL_COMPRESSED_TEXTURE_FORMATS            = 0x86A3;
+    public static final int GL_CONSTANT_ATTENUATION                  = 0x1207;
+    public static final int GL_COPY                                  = 0x1503;
+    public static final int GL_COPY_INVERTED                         = 0x150C;
+    public static final int GL_CULL_FACE                             = 0x0B44;
+    public static final int GL_CW                                    = 0x0900;
+    public static final int GL_DECAL                                 = 0x2101;
+    public static final int GL_DECR                                  = 0x1E03;
+    public static final int GL_DEPTH_BITS                            = 0x0D56;
+    public static final int GL_DEPTH_BUFFER_BIT                      = 0x0100;
+    public static final int GL_DEPTH_TEST                            = 0x0B71;
+    public static final int GL_DIFFUSE                               = 0x1201;
+    public static final int GL_DITHER                                = 0x0BD0;
+    public static final int GL_DONT_CARE                             = 0x1100;
+    public static final int GL_DST_ALPHA                             = 0x0304;
+    public static final int GL_DST_COLOR                             = 0x0306;
+    public static final int GL_EMISSION                              = 0x1600;
+    public static final int GL_EQUAL                                 = 0x0202;
+    public static final int GL_EQUIV                                 = 0x1509;
+    public static final int GL_EXP                                   = 0x0800;
+    public static final int GL_EXP2                                  = 0x0801;
+    public static final int GL_EXTENSIONS                            = 0x1F03;
+    public static final int GL_FALSE                                 = 0;
+    public static final int GL_FASTEST                               = 0x1101;
+    public static final int GL_FIXED                                 = 0x140C;
+    public static final int GL_FLAT                                  = 0x1D00;
+    public static final int GL_FLOAT                                 = 0x1406;
+    public static final int GL_FOG                                   = 0x0B60;
+    public static final int GL_FOG_COLOR                             = 0x0B66;
+    public static final int GL_FOG_DENSITY                           = 0x0B62;
+    public static final int GL_FOG_END                               = 0x0B64;
+    public static final int GL_FOG_HINT                              = 0x0C54;
+    public static final int GL_FOG_MODE                              = 0x0B65;
+    public static final int GL_FOG_START                             = 0x0B63;
+    public static final int GL_FRONT                                 = 0x0404;
+    public static final int GL_FRONT_AND_BACK                        = 0x0408;
+    public static final int GL_GEQUAL                                = 0x0206;
+    public static final int GL_GREATER                               = 0x0204;
+    public static final int GL_GREEN_BITS                            = 0x0D53;
+    public static final int GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES  = 0x8B9B;
+    public static final int GL_IMPLEMENTATION_COLOR_READ_TYPE_OES    = 0x8B9A;
+    public static final int GL_INCR                                  = 0x1E02;
+    public static final int GL_INVALID_ENUM                          = 0x0500;
+    public static final int GL_INVALID_OPERATION                     = 0x0502;
+    public static final int GL_INVALID_VALUE                         = 0x0501;
+    public static final int GL_INVERT                                = 0x150A;
+    public static final int GL_KEEP                                  = 0x1E00;
+    public static final int GL_LEQUAL                                = 0x0203;
+    public static final int GL_LESS                                  = 0x0201;
+    public static final int GL_LIGHT_MODEL_AMBIENT                   = 0x0B53;
+    public static final int GL_LIGHT_MODEL_TWO_SIDE                  = 0x0B52;
+    public static final int GL_LIGHT0                                = 0x4000;
+    public static final int GL_LIGHT1                                = 0x4001;
+    public static final int GL_LIGHT2                                = 0x4002;
+    public static final int GL_LIGHT3                                = 0x4003;
+    public static final int GL_LIGHT4                                = 0x4004;
+    public static final int GL_LIGHT5                                = 0x4005;
+    public static final int GL_LIGHT6                                = 0x4006;
+    public static final int GL_LIGHT7                                = 0x4007;
+    public static final int GL_LIGHTING                              = 0x0B50;
+    public static final int GL_LINE_LOOP                             = 0x0002;
+    public static final int GL_LINE_SMOOTH                           = 0x0B20;
+    public static final int GL_LINE_SMOOTH_HINT                      = 0x0C52;
+    public static final int GL_LINE_STRIP                            = 0x0003;
+    public static final int GL_LINEAR                                = 0x2601;
+    public static final int GL_LINEAR_ATTENUATION                    = 0x1208;
+    public static final int GL_LINEAR_MIPMAP_LINEAR                  = 0x2703;
+    public static final int GL_LINEAR_MIPMAP_NEAREST                 = 0x2701;
+    public static final int GL_LINES                                 = 0x0001;
+    public static final int GL_LUMINANCE                             = 0x1909;
+    public static final int GL_LUMINANCE_ALPHA                       = 0x190A;
+    public static final int GL_MAX_ELEMENTS_INDICES                  = 0x80E9;
+    public static final int GL_MAX_ELEMENTS_VERTICES                 = 0x80E8;
+    public static final int GL_MAX_LIGHTS                            = 0x0D31;
+    public static final int GL_MAX_MODELVIEW_STACK_DEPTH             = 0x0D36;
+    public static final int GL_MAX_PROJECTION_STACK_DEPTH            = 0x0D38;
+    public static final int GL_MAX_TEXTURE_SIZE                      = 0x0D33;
+    public static final int GL_MAX_TEXTURE_STACK_DEPTH               = 0x0D39;
+    public static final int GL_MAX_TEXTURE_UNITS                     = 0x84E2;
+    public static final int GL_MAX_VIEWPORT_DIMS                     = 0x0D3A;
+    public static final int GL_MODELVIEW                             = 0x1700;
+    public static final int GL_MODULATE                              = 0x2100;
+    public static final int GL_MULTISAMPLE                           = 0x809D;
+    public static final int GL_NAND                                  = 0x150E;
+    public static final int GL_NEAREST                               = 0x2600;
+    public static final int GL_NEAREST_MIPMAP_LINEAR                 = 0x2702;
+    public static final int GL_NEAREST_MIPMAP_NEAREST                = 0x2700;
+    public static final int GL_NEVER                                 = 0x0200;
+    public static final int GL_NICEST                                = 0x1102;
+    public static final int GL_NO_ERROR                              = 0;
+    public static final int GL_NOOP                                  = 0x1505;
+    public static final int GL_NOR                                   = 0x1508;
+    public static final int GL_NORMAL_ARRAY                          = 0x8075;
+    public static final int GL_NORMALIZE                             = 0x0BA1;
+    public static final int GL_NOTEQUAL                              = 0x0205;
+    public static final int GL_NUM_COMPRESSED_TEXTURE_FORMATS        = 0x86A2;
+    public static final int GL_ONE                                   = 1;
+    public static final int GL_ONE_MINUS_DST_ALPHA                   = 0x0305;
+    public static final int GL_ONE_MINUS_DST_COLOR                   = 0x0307;
+    public static final int GL_ONE_MINUS_SRC_ALPHA                   = 0x0303;
+    public static final int GL_ONE_MINUS_SRC_COLOR                   = 0x0301;
+    public static final int GL_OR                                    = 0x1507;
+    public static final int GL_OR_INVERTED                           = 0x150D;
+    public static final int GL_OR_REVERSE                            = 0x150B;
+    public static final int GL_OUT_OF_MEMORY                         = 0x0505;
+    public static final int GL_PACK_ALIGNMENT                        = 0x0D05;
+    public static final int GL_PALETTE4_R5_G6_B5_OES                 = 0x8B92;
+    public static final int GL_PALETTE4_RGB5_A1_OES                  = 0x8B94;
+    public static final int GL_PALETTE4_RGB8_OES                     = 0x8B90;
+    public static final int GL_PALETTE4_RGBA4_OES                    = 0x8B93;
+    public static final int GL_PALETTE4_RGBA8_OES                    = 0x8B91;
+    public static final int GL_PALETTE8_R5_G6_B5_OES                 = 0x8B97;
+    public static final int GL_PALETTE8_RGB5_A1_OES                  = 0x8B99;
+    public static final int GL_PALETTE8_RGB8_OES                     = 0x8B95;
+    public static final int GL_PALETTE8_RGBA4_OES                    = 0x8B98;
+    public static final int GL_PALETTE8_RGBA8_OES                    = 0x8B96;
+    public static final int GL_PERSPECTIVE_CORRECTION_HINT           = 0x0C50;
+    public static final int GL_POINT_SMOOTH                          = 0x0B10;
+    public static final int GL_POINT_SMOOTH_HINT                     = 0x0C51;
+    public static final int GL_POINTS                                = 0x0000;
+    public static final int GL_POINT_FADE_THRESHOLD_SIZE             = 0x8128;
+    public static final int GL_POINT_SIZE                            = 0x0B11;
+    public static final int GL_POLYGON_OFFSET_FILL                   = 0x8037;
+    public static final int GL_POLYGON_SMOOTH_HINT                   = 0x0C53;
+    public static final int GL_POSITION                              = 0x1203;
+    public static final int GL_PROJECTION                            = 0x1701;
+    public static final int GL_QUADRATIC_ATTENUATION                 = 0x1209;
+    public static final int GL_RED_BITS                              = 0x0D52;
+    public static final int GL_RENDERER                              = 0x1F01;
+    public static final int GL_REPEAT                                = 0x2901;
+    public static final int GL_REPLACE                               = 0x1E01;
+    public static final int GL_RESCALE_NORMAL                        = 0x803A;
+    public static final int GL_RGB                                   = 0x1907;
+    public static final int GL_RGBA                                  = 0x1908;
+    public static final int GL_SAMPLE_ALPHA_TO_COVERAGE              = 0x809E;
+    public static final int GL_SAMPLE_ALPHA_TO_ONE                   = 0x809F;
+    public static final int GL_SAMPLE_COVERAGE                       = 0x80A0;
+    public static final int GL_SCISSOR_TEST                          = 0x0C11;
+    public static final int GL_SET                                   = 0x150F;
+    public static final int GL_SHININESS                             = 0x1601;
+    public static final int GL_SHORT                                 = 0x1402;
+    public static final int GL_SMOOTH                                = 0x1D01;
+    public static final int GL_SMOOTH_LINE_WIDTH_RANGE               = 0x0B22;
+    public static final int GL_SMOOTH_POINT_SIZE_RANGE               = 0x0B12;
+    public static final int GL_SPECULAR                              = 0x1202;
+    public static final int GL_SPOT_CUTOFF                           = 0x1206;
+    public static final int GL_SPOT_DIRECTION                        = 0x1204;
+    public static final int GL_SPOT_EXPONENT                         = 0x1205;
+    public static final int GL_SRC_ALPHA                             = 0x0302;
+    public static final int GL_SRC_ALPHA_SATURATE                    = 0x0308;
+    public static final int GL_SRC_COLOR                             = 0x0300;
+    public static final int GL_STACK_OVERFLOW                        = 0x0503;
+    public static final int GL_STACK_UNDERFLOW                       = 0x0504;
+    public static final int GL_STENCIL_BITS                          = 0x0D57;
+    public static final int GL_STENCIL_BUFFER_BIT                    = 0x0400;
+    public static final int GL_STENCIL_TEST                          = 0x0B90;
+    public static final int GL_SUBPIXEL_BITS                         = 0x0D50;
+    public static final int GL_TEXTURE                               = 0x1702;
+    public static final int GL_TEXTURE_2D                            = 0x0DE1;
+    public static final int GL_TEXTURE_COORD_ARRAY                   = 0x8078;
+    public static final int GL_TEXTURE_ENV                           = 0x2300;
+    public static final int GL_TEXTURE_ENV_COLOR                     = 0x2201;
+    public static final int GL_TEXTURE_ENV_MODE                      = 0x2200;
+    public static final int GL_TEXTURE_MAG_FILTER                    = 0x2800;
+    public static final int GL_TEXTURE_MIN_FILTER                    = 0x2801;
+    public static final int GL_TEXTURE_WRAP_S                        = 0x2802;
+    public static final int GL_TEXTURE_WRAP_T                        = 0x2803;
+    public static final int GL_TEXTURE0                              = 0x84C0;
+    public static final int GL_TEXTURE1                              = 0x84C1;
+    public static final int GL_TEXTURE2                              = 0x84C2;
+    public static final int GL_TEXTURE3                              = 0x84C3;
+    public static final int GL_TEXTURE4                              = 0x84C4;
+    public static final int GL_TEXTURE5                              = 0x84C5;
+    public static final int GL_TEXTURE6                              = 0x84C6;
+    public static final int GL_TEXTURE7                              = 0x84C7;
+    public static final int GL_TEXTURE8                              = 0x84C8;
+    public static final int GL_TEXTURE9                              = 0x84C9;
+    public static final int GL_TEXTURE10                             = 0x84CA;
+    public static final int GL_TEXTURE11                             = 0x84CB;
+    public static final int GL_TEXTURE12                             = 0x84CC;
+    public static final int GL_TEXTURE13                             = 0x84CD;
+    public static final int GL_TEXTURE14                             = 0x84CE;
+    public static final int GL_TEXTURE15                             = 0x84CF;
+    public static final int GL_TEXTURE16                             = 0x84D0;
+    public static final int GL_TEXTURE17                             = 0x84D1;
+    public static final int GL_TEXTURE18                             = 0x84D2;
+    public static final int GL_TEXTURE19                             = 0x84D3;
+    public static final int GL_TEXTURE20                             = 0x84D4;
+    public static final int GL_TEXTURE21                             = 0x84D5;
+    public static final int GL_TEXTURE22                             = 0x84D6;
+    public static final int GL_TEXTURE23                             = 0x84D7;
+    public static final int GL_TEXTURE24                             = 0x84D8;
+    public static final int GL_TEXTURE25                             = 0x84D9;
+    public static final int GL_TEXTURE26                             = 0x84DA;
+    public static final int GL_TEXTURE27                             = 0x84DB;
+    public static final int GL_TEXTURE28                             = 0x84DC;
+    public static final int GL_TEXTURE29                             = 0x84DD;
+    public static final int GL_TEXTURE30                             = 0x84DE;
+    public static final int GL_TEXTURE31                             = 0x84DF;
+    public static final int GL_TRIANGLE_FAN                          = 0x0006;
+    public static final int GL_TRIANGLE_STRIP                        = 0x0005;
+    public static final int GL_TRIANGLES                             = 0x0004;
+    public static final int GL_TRUE                                  = 1;
+    public static final int GL_UNPACK_ALIGNMENT                      = 0x0CF5;
+    public static final int GL_UNSIGNED_BYTE                         = 0x1401;
+    public static final int GL_UNSIGNED_SHORT                        = 0x1403;
+    public static final int GL_UNSIGNED_SHORT_4_4_4_4                = 0x8033;
+    public static final int GL_UNSIGNED_SHORT_5_5_5_1                = 0x8034;
+    public static final int GL_UNSIGNED_SHORT_5_6_5                  = 0x8363;
+    public static final int GL_VENDOR                                = 0x1F00;
+    public static final int GL_VERSION                               = 0x1F02;
+    public static final int GL_VERTEX_ARRAY                          = 0x8074;
+    public static final int GL_XOR                                   = 0x1506;
+    public static final int GL_ZERO                                  = 0;
+
+    native private static void _nativeClassInit();
+    static {
+	    _nativeClassInit();
+    }
+
+    private static Buffer _colorPointer;
+    private static Buffer _normalPointer;
+    private static Buffer _texCoordPointer;
+    private static Buffer _vertexPointer;
+
diff --git a/opengl/tools/glgen/stubs/GLCHeader.cpp b/opengl/tools/glgen/stubs/gles11/GLES10cHeader.cpp
similarity index 73%
copy from opengl/tools/glgen/stubs/GLCHeader.cpp
copy to opengl/tools/glgen/stubs/gles11/GLES10cHeader.cpp
index 6495686..e1c09f4 100644
--- a/opengl/tools/glgen/stubs/GLCHeader.cpp
+++ b/opengl/tools/glgen/stubs/gles11/GLES10cHeader.cpp
@@ -1,5 +1,5 @@
 **
-** Copyright 2006, The Android Open Source Project
+** 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. 
@@ -21,11 +21,20 @@
 
 #include <assert.h>
 #include <GLES/gl.h>
+#include <GLES/glext.h>
 
-#include <private/opengles/gl_context.h>
-
-#define _NUM_COMPRESSED_TEXTURE_FORMATS \
-        (::android::OGLES_NUM_COMPRESSED_TEXTURE_FORMATS)
+/* special calls implemented in Android's GLES wrapper used to more
+ * efficiently bound-check passed arrays */
+extern "C" {
+GL_API void GL_APIENTRY glColorPointerBounds(GLint size, GLenum type, GLsizei stride,
+        const GLvoid *ptr, GLsizei count);
+GL_API void GL_APIENTRY glNormalPointerBounds(GLenum type, GLsizei stride,
+        const GLvoid *pointer, GLsizei count);
+GL_API void GL_APIENTRY glTexCoordPointerBounds(GLint size, GLenum type,
+        GLsizei stride, const GLvoid *pointer, GLsizei count);
+GL_API void GL_APIENTRY glVertexPointerBounds(GLint size, GLenum type,
+        GLsizei stride, const GLvoid *pointer, GLsizei count);
+}
 
 static int initialized = 0;
 
@@ -44,7 +53,7 @@
 
 /* Cache method IDs each time the class is loaded. */
 
-void
+static void
 nativeClassInitBuffer(JNIEnv *_env)
 {
     jclass nioAccessClassLocal = _env->FindClass("java/nio/NIOAccess");
@@ -66,7 +75,6 @@
         _env->GetFieldID(bufferClass, "_elementSizeShift", "I");
 }
 
-
 static void
 nativeClassInit(JNIEnv *_env, jclass glImplClass)
 {
@@ -117,7 +125,6 @@
     return (void *) ((char *) data + offset);
 }
 
-
 static void
 releasePointer(JNIEnv *_env, jarray array, void *data, jboolean commit)
 {
@@ -125,5 +132,25 @@
 					   commit ? 0 : JNI_ABORT);
 }
 
+static void *
+getDirectBufferPointer(JNIEnv *_env, jobject buffer) {
+    char* buf = (char*) _env->GetDirectBufferAddress(buffer);
+    if (buf) {
+        jint position = _env->GetIntField(buffer, positionID);
+        jint elementSizeShift = _env->GetIntField(buffer, elementSizeShiftID);
+        buf += position << elementSizeShift;
+    } else {
+        _env->ThrowNew(IAEClass, "Must use a native order direct Buffer");
+    }
+    return (void*) buf;
+}
+
+static int
+getNumCompressedTextureFormats() {
+    int numCompressedTextureFormats = 0;
+    glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numCompressedTextureFormats);
+    return numCompressedTextureFormats;
+}
+
 // --------------------------------------------------------------------------
 
diff --git a/opengl/tools/glgen/stubs/gles11/GLES11ExtHeader.java-if b/opengl/tools/glgen/stubs/gles11/GLES11ExtHeader.java-if
new file mode 100644
index 0000000..428ccee
--- /dev/null
+++ b/opengl/tools/glgen/stubs/gles11/GLES11ExtHeader.java-if
@@ -0,0 +1,130 @@
+**
+** 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.
+*/
+
+// This source file is automatically generated
+
+package android.opengl;
+
+public class GLES11Ext {
+    public static final int GL_BLEND_EQUATION_RGB_OES                               = 0x8009;
+    public static final int GL_BLEND_EQUATION_ALPHA_OES                             = 0x883D;
+    public static final int GL_BLEND_DST_RGB_OES                                    = 0x80C8;
+    public static final int GL_BLEND_SRC_RGB_OES                                    = 0x80C9;
+    public static final int GL_BLEND_DST_ALPHA_OES                                  = 0x80CA;
+    public static final int GL_BLEND_SRC_ALPHA_OES                                  = 0x80CB;
+    public static final int GL_BLEND_EQUATION_OES                                   = 0x8009;
+    public static final int GL_FUNC_ADD_OES                                         = 0x8006;
+    public static final int GL_FUNC_SUBTRACT_OES                                    = 0x800A;
+    public static final int GL_FUNC_REVERSE_SUBTRACT_OES                            = 0x800B;
+    public static final int GL_ETC1_RGB8_OES                                        = 0x8D64;
+    public static final int GL_DEPTH_COMPONENT24_OES                                = 0x81A6;
+    public static final int GL_DEPTH_COMPONENT32_OES                                = 0x81A7;
+    public static final int GL_TEXTURE_CROP_RECT_OES                                = 0x8B9D;
+    public static final int GL_FIXED_OES                                            = 0x140C;
+    public static final int GL_NONE_OES                                             = 0;
+    public static final int GL_FRAMEBUFFER_OES                                      = 0x8D40;
+    public static final int GL_RENDERBUFFER_OES                                     = 0x8D41;
+    public static final int GL_RGBA4_OES                                            = 0x8056;
+    public static final int GL_RGB5_A1_OES                                          = 0x8057;
+    public static final int GL_RGB565_OES                                           = 0x8D62;
+    public static final int GL_DEPTH_COMPONENT16_OES                                = 0x81A5;
+    public static final int GL_RENDERBUFFER_WIDTH_OES                               = 0x8D42;
+    public static final int GL_RENDERBUFFER_HEIGHT_OES                              = 0x8D43;
+    public static final int GL_RENDERBUFFER_INTERNAL_FORMAT_OES                     = 0x8D44;
+    public static final int GL_RENDERBUFFER_RED_SIZE_OES                            = 0x8D50;
+    public static final int GL_RENDERBUFFER_GREEN_SIZE_OES                          = 0x8D51;
+    public static final int GL_RENDERBUFFER_BLUE_SIZE_OES                           = 0x8D52;
+    public static final int GL_RENDERBUFFER_ALPHA_SIZE_OES                          = 0x8D53;
+    public static final int GL_RENDERBUFFER_DEPTH_SIZE_OES                          = 0x8D54;
+    public static final int GL_RENDERBUFFER_STENCIL_SIZE_OES                        = 0x8D55;
+    public static final int GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_OES               = 0x8CD0;
+    public static final int GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_OES               = 0x8CD1;
+    public static final int GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_OES             = 0x8CD2;
+    public static final int GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_OES     = 0x8CD3;
+    public static final int GL_COLOR_ATTACHMENT0_OES                                = 0x8CE0;
+    public static final int GL_DEPTH_ATTACHMENT_OES                                 = 0x8D00;
+    public static final int GL_STENCIL_ATTACHMENT_OES                               = 0x8D20;
+    public static final int GL_FRAMEBUFFER_COMPLETE_OES                             = 0x8CD5;
+    public static final int GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES                = 0x8CD6;
+    public static final int GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_OES        = 0x8CD7;
+    public static final int GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_OES                = 0x8CD9;
+    public static final int GL_FRAMEBUFFER_INCOMPLETE_FORMATS_OES                   = 0x8CDA;
+    public static final int GL_FRAMEBUFFER_UNSUPPORTED_OES                          = 0x8CDD;
+    public static final int GL_FRAMEBUFFER_BINDING_OES                              = 0x8CA6;
+    public static final int GL_RENDERBUFFER_BINDING_OES                             = 0x8CA7;
+    public static final int GL_MAX_RENDERBUFFER_SIZE_OES                            = 0x84E8;
+    public static final int GL_INVALID_FRAMEBUFFER_OPERATION_OES                    = 0x0506;
+    public static final int GL_WRITE_ONLY_OES                                       = 0x88B9;
+    public static final int GL_BUFFER_ACCESS_OES                                    = 0x88BB;
+    public static final int GL_BUFFER_MAPPED_OES                                    = 0x88BC;
+    public static final int GL_BUFFER_MAP_POINTER_OES                               = 0x88BD;
+    public static final int GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES               = 0x898D;
+    public static final int GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES              = 0x898E;
+    public static final int GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES                 = 0x898F;
+    public static final int GL_MAX_VERTEX_UNITS_OES                                 = 0x86A4;
+    public static final int GL_MAX_PALETTE_MATRICES_OES                             = 0x8842;
+    public static final int GL_MATRIX_PALETTE_OES                                   = 0x8840;
+    public static final int GL_MATRIX_INDEX_ARRAY_OES                               = 0x8844;
+    public static final int GL_WEIGHT_ARRAY_OES                                     = 0x86AD;
+    public static final int GL_CURRENT_PALETTE_MATRIX_OES                           = 0x8843;
+    public static final int GL_MATRIX_INDEX_ARRAY_SIZE_OES                          = 0x8846;
+    public static final int GL_MATRIX_INDEX_ARRAY_TYPE_OES                          = 0x8847;
+    public static final int GL_MATRIX_INDEX_ARRAY_STRIDE_OES                        = 0x8848;
+    public static final int GL_MATRIX_INDEX_ARRAY_POINTER_OES                       = 0x8849;
+    public static final int GL_MATRIX_INDEX_ARRAY_BUFFER_BINDING_OES                = 0x8B9E;
+    public static final int GL_WEIGHT_ARRAY_SIZE_OES                                = 0x86AB;
+    public static final int GL_WEIGHT_ARRAY_TYPE_OES                                = 0x86A9;
+    public static final int GL_WEIGHT_ARRAY_STRIDE_OES                              = 0x86AA;
+    public static final int GL_WEIGHT_ARRAY_POINTER_OES                             = 0x86AC;
+    public static final int GL_WEIGHT_ARRAY_BUFFER_BINDING_OES                      = 0x889E;
+    public static final int GL_DEPTH_STENCIL_OES                                    = 0x84F9;
+    public static final int GL_UNSIGNED_INT_24_8_OES                                = 0x84FA;
+    public static final int GL_DEPTH24_STENCIL8_OES                                 = 0x88F0;
+    public static final int GL_RGB8_OES                                             = 0x8051;
+    public static final int GL_RGBA8_OES                                            = 0x8058;
+    public static final int GL_STENCIL_INDEX1_OES                                   = 0x8D46;
+    public static final int GL_STENCIL_INDEX4_OES                                   = 0x8D47;
+    public static final int GL_STENCIL_INDEX8_OES                                   = 0x8D48;
+    public static final int GL_INCR_WRAP_OES                                        = 0x8507;
+    public static final int GL_DECR_WRAP_OES                                        = 0x8508;
+    public static final int GL_NORMAL_MAP_OES                                       = 0x8511;
+    public static final int GL_REFLECTION_MAP_OES                                   = 0x8512;
+    public static final int GL_TEXTURE_CUBE_MAP_OES                                 = 0x8513;
+    public static final int GL_TEXTURE_BINDING_CUBE_MAP_OES                         = 0x8514;
+    public static final int GL_TEXTURE_CUBE_MAP_POSITIVE_X_OES                      = 0x8515;
+    public static final int GL_TEXTURE_CUBE_MAP_NEGATIVE_X_OES                      = 0x8516;
+    public static final int GL_TEXTURE_CUBE_MAP_POSITIVE_Y_OES                      = 0x8517;
+    public static final int GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_OES                      = 0x8518;
+    public static final int GL_TEXTURE_CUBE_MAP_POSITIVE_Z_OES                      = 0x8519;
+    public static final int GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_OES                      = 0x851A;
+    public static final int GL_MAX_CUBE_MAP_TEXTURE_SIZE_OES                        = 0x851C;
+    public static final int GL_TEXTURE_GEN_MODE_OES                                 = 0x2500;
+    public static final int GL_TEXTURE_GEN_STR_OES                                  = 0x8D60;
+    public static final int GL_MIRRORED_REPEAT_OES                                  = 0x8370;
+    public static final int GL_3DC_X_AMD                                            = 0x87F9;
+    public static final int GL_3DC_XY_AMD                                           = 0x87FA;
+    public static final int GL_ATC_RGB_AMD                                          = 0x8C92;
+    public static final int GL_ATC_RGBA_EXPLICIT_ALPHA_AMD                          = 0x8C93;
+    public static final int GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD                      = 0x87EE;
+    public static final int GL_TEXTURE_MAX_ANISOTROPY_EXT                           = 0x84FE;
+    public static final int GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT                       = 0x84FF;
+    public static final int GL_BGRA                                                 = 0x80E1;
+
+    native private static void _nativeClassInit();
+    static {
+	    _nativeClassInit();
+    }
+    
\ No newline at end of file
diff --git a/opengl/tools/glgen/stubs/GLCHeader.cpp b/opengl/tools/glgen/stubs/gles11/GLES11ExtcHeader.cpp
similarity index 94%
copy from opengl/tools/glgen/stubs/GLCHeader.cpp
copy to opengl/tools/glgen/stubs/gles11/GLES11ExtcHeader.cpp
index 6495686..294d1ce 100644
--- a/opengl/tools/glgen/stubs/GLCHeader.cpp
+++ b/opengl/tools/glgen/stubs/gles11/GLES11ExtcHeader.cpp
@@ -1,5 +1,5 @@
 **
-** Copyright 2006, The Android Open Source Project
+** 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. 
@@ -21,11 +21,7 @@
 
 #include <assert.h>
 #include <GLES/gl.h>
-
-#include <private/opengles/gl_context.h>
-
-#define _NUM_COMPRESSED_TEXTURE_FORMATS \
-        (::android::OGLES_NUM_COMPRESSED_TEXTURE_FORMATS)
+#include <GLES/glext.h>
 
 static int initialized = 0;
 
@@ -44,7 +40,7 @@
 
 /* Cache method IDs each time the class is loaded. */
 
-void
+static void
 nativeClassInitBuffer(JNIEnv *_env)
 {
     jclass nioAccessClassLocal = _env->FindClass("java/nio/NIOAccess");
diff --git a/opengl/tools/glgen/stubs/gles11/GLES11Header.java-if b/opengl/tools/glgen/stubs/gles11/GLES11Header.java-if
new file mode 100644
index 0000000..26f466f
--- /dev/null
+++ b/opengl/tools/glgen/stubs/gles11/GLES11Header.java-if
@@ -0,0 +1,151 @@
+**
+** 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.
+*/
+
+// This source file is automatically generated
+
+package android.opengl;
+
+import java.nio.Buffer;
+
+public class GLES11 extends GLES10 {
+    public static final int GL_ACTIVE_TEXTURE                          = 0x84E0;
+    public static final int GL_ADD_SIGNED                              = 0x8574;
+    public static final int GL_ALPHA_SCALE                             = 0x0D1C;
+    public static final int GL_ALPHA_TEST_FUNC                         = 0x0BC1;
+    public static final int GL_ALPHA_TEST_REF                          = 0x0BC2;
+    public static final int GL_ARRAY_BUFFER                            = 0x8892;
+    public static final int GL_ARRAY_BUFFER_BINDING                    = 0x8894;
+    public static final int GL_BLEND_DST                               = 0x0BE0;
+    public static final int GL_BLEND_SRC                               = 0x0BE1;
+    public static final int GL_BUFFER_ACCESS                           = 0x88BB;
+    public static final int GL_BUFFER_SIZE                             = 0x8764;
+    public static final int GL_BUFFER_USAGE                            = 0x8765;
+    public static final int GL_CLIENT_ACTIVE_TEXTURE                   = 0x84E1;
+    public static final int GL_CLIP_PLANE0                             = 0x3000;
+    public static final int GL_CLIP_PLANE1                             = 0x3001;
+    public static final int GL_CLIP_PLANE2                             = 0x3002;
+    public static final int GL_CLIP_PLANE3                             = 0x3003;
+    public static final int GL_CLIP_PLANE4                             = 0x3004;
+    public static final int GL_CLIP_PLANE5                             = 0x3005;
+    public static final int GL_COLOR_ARRAY_BUFFER_BINDING              = 0x8898;
+    public static final int GL_COLOR_ARRAY_POINTER                     = 0x8090;
+    public static final int GL_COLOR_ARRAY_SIZE                        = 0x8081;
+    public static final int GL_COLOR_ARRAY_STRIDE                      = 0x8083;
+    public static final int GL_COLOR_ARRAY_TYPE                        = 0x8082;
+    public static final int GL_COLOR_CLEAR_VALUE                       = 0x0C22;
+    public static final int GL_COLOR_WRITEMASK                         = 0x0C23;
+    public static final int GL_COMBINE                                 = 0x8570;
+    public static final int GL_COMBINE_ALPHA                           = 0x8572;
+    public static final int GL_COMBINE_RGB                             = 0x8571;
+    public static final int GL_CONSTANT                                = 0x8576;
+    public static final int GL_COORD_REPLACE_OES                       = 0x8862;
+    public static final int GL_CULL_FACE_MODE                          = 0x0B45;
+    public static final int GL_CURRENT_COLOR                           = 0x0B00;
+    public static final int GL_CURRENT_NORMAL                          = 0x0B02;
+    public static final int GL_CURRENT_TEXTURE_COORDS                  = 0x0B03;
+    public static final int GL_DEPTH_CLEAR_VALUE                       = 0x0B73;
+    public static final int GL_DEPTH_FUNC                              = 0x0B74;
+    public static final int GL_DEPTH_RANGE                             = 0x0B70;
+    public static final int GL_DEPTH_WRITEMASK                         = 0x0B72;
+    public static final int GL_DOT3_RGB                                = 0x86AE;
+    public static final int GL_DOT3_RGBA                               = 0x86AF;
+    public static final int GL_DYNAMIC_DRAW                            = 0x88E8;
+    public static final int GL_ELEMENT_ARRAY_BUFFER                    = 0x8893;
+    public static final int GL_ELEMENT_ARRAY_BUFFER_BINDING            = 0x8895;
+    public static final int GL_FRONT_FACE                              = 0x0B46;
+    public static final int GL_GENERATE_MIPMAP                         = 0x8191;
+    public static final int GL_GENERATE_MIPMAP_HINT                    = 0x8192;
+    public static final int GL_INTERPOLATE                             = 0x8575;
+    public static final int GL_LINE_WIDTH                              = 0x0B21;
+    public static final int GL_LOGIC_OP_MODE                           = 0x0BF0;
+    public static final int GL_MATRIX_MODE                             = 0x0BA0;
+    public static final int GL_MAX_CLIP_PLANES                         = 0x0D32;
+    public static final int GL_MODELVIEW_MATRIX                        = 0x0BA6;
+    public static final int GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES  = 0x898D;
+    public static final int GL_MODELVIEW_STACK_DEPTH                   = 0x0BA3;
+    public static final int GL_NORMAL_ARRAY_BUFFER_BINDING             = 0x8897;
+    public static final int GL_NORMAL_ARRAY_POINTER                    = 0x808F;
+    public static final int GL_NORMAL_ARRAY_STRIDE                     = 0x807F;
+    public static final int GL_NORMAL_ARRAY_TYPE                       = 0x807E;
+    public static final int GL_OPERAND0_ALPHA                          = 0x8598;
+    public static final int GL_OPERAND0_RGB                            = 0x8590;
+    public static final int GL_OPERAND1_ALPHA                          = 0x8599;
+    public static final int GL_OPERAND1_RGB                            = 0x8591;
+    public static final int GL_OPERAND2_ALPHA                          = 0x859A;
+    public static final int GL_OPERAND2_RGB                            = 0x8592;
+    public static final int GL_POINT_DISTANCE_ATTENUATION              = 0x8129;
+    public static final int GL_POINT_FADE_THRESHOLD_SIZE               = 0x8128;
+    public static final int GL_POINT_SIZE                              = 0x0B11;
+    public static final int GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES     = 0x8B9F;
+    public static final int GL_POINT_SIZE_ARRAY_OES                    = 0x8B9C;
+    public static final int GL_POINT_SIZE_ARRAY_POINTER_OES            = 0x898C;
+    public static final int GL_POINT_SIZE_ARRAY_STRIDE_OES             = 0x898B;
+    public static final int GL_POINT_SIZE_ARRAY_TYPE_OES               = 0x898A;
+    public static final int GL_POINT_SIZE_MAX                          = 0x8127;
+    public static final int GL_POINT_SIZE_MIN                          = 0x8126;
+    public static final int GL_POINT_SPRITE_OES                        = 0x8861;
+    public static final int GL_POLYGON_OFFSET_FACTOR                   = 0x8038;
+    public static final int GL_POLYGON_OFFSET_UNITS                    = 0x2A00;
+    public static final int GL_PREVIOUS                                = 0x8578;
+    public static final int GL_PRIMARY_COLOR                           = 0x8577;
+    public static final int GL_PROJECTION_MATRIX                       = 0x0BA7;
+    public static final int GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES = 0x898E;
+    public static final int GL_PROJECTION_STACK_DEPTH                  = 0x0BA4;
+    public static final int GL_RGB_SCALE                               = 0x8573;
+    public static final int GL_SAMPLE_BUFFERS                          = 0x80A8;
+    public static final int GL_SAMPLE_COVERAGE_INVERT                  = 0x80AB;
+    public static final int GL_SAMPLE_COVERAGE_VALUE                   = 0x80AA;
+    public static final int GL_SAMPLES                                 = 0x80A9;
+    public static final int GL_SCISSOR_BOX                             = 0x0C10;
+    public static final int GL_SHADE_MODEL                             = 0x0B54;
+    public static final int GL_SRC0_ALPHA                              = 0x8588;
+    public static final int GL_SRC0_RGB                                = 0x8580;
+    public static final int GL_SRC1_ALPHA                              = 0x8589;
+    public static final int GL_SRC1_RGB                                = 0x8581;
+    public static final int GL_SRC2_ALPHA                              = 0x858A;
+    public static final int GL_SRC2_RGB                                = 0x8582;
+    public static final int GL_STATIC_DRAW                             = 0x88E4;
+    public static final int GL_STENCIL_CLEAR_VALUE                     = 0x0B91;
+    public static final int GL_STENCIL_FAIL                            = 0x0B94;
+    public static final int GL_STENCIL_FUNC                            = 0x0B92;
+    public static final int GL_STENCIL_PASS_DEPTH_FAIL                 = 0x0B95;
+    public static final int GL_STENCIL_PASS_DEPTH_PASS                 = 0x0B96;
+    public static final int GL_STENCIL_REF                             = 0x0B97;
+    public static final int GL_STENCIL_VALUE_MASK                      = 0x0B93;
+    public static final int GL_STENCIL_WRITEMASK                       = 0x0B98;
+    public static final int GL_SUBTRACT                                = 0x84E7;
+    public static final int GL_TEXTURE_BINDING_2D                      = 0x8069;
+    public static final int GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING      = 0x889A;
+    public static final int GL_TEXTURE_COORD_ARRAY_POINTER             = 0x8092;
+    public static final int GL_TEXTURE_COORD_ARRAY_SIZE                = 0x8088;
+    public static final int GL_TEXTURE_COORD_ARRAY_STRIDE              = 0x808A;
+    public static final int GL_TEXTURE_COORD_ARRAY_TYPE                = 0x8089;
+    public static final int GL_TEXTURE_MATRIX                          = 0x0BA8;
+    public static final int GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES    = 0x898F;
+    public static final int GL_TEXTURE_STACK_DEPTH                     = 0x0BA5;
+    public static final int GL_VERTEX_ARRAY_BUFFER_BINDING             = 0x8896;
+    public static final int GL_VERTEX_ARRAY_POINTER                    = 0x808E;
+    public static final int GL_VERTEX_ARRAY_SIZE                       = 0x807A;
+    public static final int GL_VERTEX_ARRAY_STRIDE                     = 0x807C;
+    public static final int GL_VERTEX_ARRAY_TYPE                       = 0x807B;
+    public static final int GL_VIEWPORT                                = 0x0BA2;
+    public static final int GL_WRITE_ONLY                              = 0x88B9;
+
+    native private static void _nativeClassInit();
+    static {
+	    _nativeClassInit();
+    }
+
diff --git a/opengl/tools/glgen/stubs/GLCHeader.cpp b/opengl/tools/glgen/stubs/gles11/GLES11cHeader.cpp
similarity index 94%
copy from opengl/tools/glgen/stubs/GLCHeader.cpp
copy to opengl/tools/glgen/stubs/gles11/GLES11cHeader.cpp
index 6495686..294d1ce 100644
--- a/opengl/tools/glgen/stubs/GLCHeader.cpp
+++ b/opengl/tools/glgen/stubs/gles11/GLES11cHeader.cpp
@@ -1,5 +1,5 @@
 **
-** Copyright 2006, The Android Open Source Project
+** 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. 
@@ -21,11 +21,7 @@
 
 #include <assert.h>
 #include <GLES/gl.h>
-
-#include <private/opengles/gl_context.h>
-
-#define _NUM_COMPRESSED_TEXTURE_FORMATS \
-        (::android::OGLES_NUM_COMPRESSED_TEXTURE_FORMATS)
+#include <GLES/glext.h>
 
 static int initialized = 0;
 
@@ -44,7 +40,7 @@
 
 /* Cache method IDs each time the class is loaded. */
 
-void
+static void
 nativeClassInitBuffer(JNIEnv *_env)
 {
     jclass nioAccessClassLocal = _env->FindClass("java/nio/NIOAccess");
diff --git a/opengl/tools/glgen/stubs/glGetString.cpp b/opengl/tools/glgen/stubs/gles11/glGetString.cpp
similarity index 97%
rename from opengl/tools/glgen/stubs/glGetString.cpp
rename to opengl/tools/glgen/stubs/gles11/glGetString.cpp
index 22e1297..a400859 100644
--- a/opengl/tools/glgen/stubs/glGetString.cpp
+++ b/opengl/tools/glgen/stubs/gles11/glGetString.cpp
@@ -1,6 +1,7 @@
 #include <string.h>

 

 /* const GLubyte * glGetString ( GLenum name ) */

+static

 jstring

 android_glGetString

   (JNIEnv *_env, jobject _this, jint name) {

diff --git a/opengl/tools/glgen/stubs/gles11/glGetString.java b/opengl/tools/glgen/stubs/gles11/glGetString.java
new file mode 100644
index 0000000..fba249b
--- /dev/null
+++ b/opengl/tools/glgen/stubs/gles11/glGetString.java
@@ -0,0 +1,5 @@
+    // C function const GLubyte * glGetString ( GLenum name )

+

+    public static native String glGetString(

+        int name

+    );

diff --git a/opengl/tools/glgen/stubs/gles11/glGetString.nativeReg b/opengl/tools/glgen/stubs/gles11/glGetString.nativeReg
new file mode 100644
index 0000000..a4af31f
--- /dev/null
+++ b/opengl/tools/glgen/stubs/gles11/glGetString.nativeReg
@@ -0,0 +1 @@
+{"glGetString", "(I)Ljava/lang/String;", (void *) android_glGetString },

diff --git a/opengl/tools/glgen/stubs/GL10ExtHeader.java-if b/opengl/tools/glgen/stubs/jsr239/GL10ExtHeader.java-if
similarity index 100%
rename from opengl/tools/glgen/stubs/GL10ExtHeader.java-if
rename to opengl/tools/glgen/stubs/jsr239/GL10ExtHeader.java-if
diff --git a/opengl/tools/glgen/stubs/GL10Header.java-if b/opengl/tools/glgen/stubs/jsr239/GL10Header.java-if
similarity index 100%
rename from opengl/tools/glgen/stubs/GL10Header.java-if
rename to opengl/tools/glgen/stubs/jsr239/GL10Header.java-if
diff --git a/opengl/tools/glgen/stubs/GL11ExtHeader.java-if b/opengl/tools/glgen/stubs/jsr239/GL11ExtHeader.java-if
similarity index 100%
rename from opengl/tools/glgen/stubs/GL11ExtHeader.java-if
rename to opengl/tools/glgen/stubs/jsr239/GL11ExtHeader.java-if
diff --git a/opengl/tools/glgen/stubs/GL11ExtensionPackHeader.java-if b/opengl/tools/glgen/stubs/jsr239/GL11ExtensionPackHeader.java-if
similarity index 100%
rename from opengl/tools/glgen/stubs/GL11ExtensionPackHeader.java-if
rename to opengl/tools/glgen/stubs/jsr239/GL11ExtensionPackHeader.java-if
diff --git a/opengl/tools/glgen/stubs/GL11Header.java-if b/opengl/tools/glgen/stubs/jsr239/GL11Header.java-if
similarity index 100%
rename from opengl/tools/glgen/stubs/GL11Header.java-if
rename to opengl/tools/glgen/stubs/jsr239/GL11Header.java-if
diff --git a/opengl/tools/glgen/stubs/GL11ImplHeader.java-impl b/opengl/tools/glgen/stubs/jsr239/GL11ImplHeader.java-impl
similarity index 100%
rename from opengl/tools/glgen/stubs/GL11ImplHeader.java-impl
rename to opengl/tools/glgen/stubs/jsr239/GL11ImplHeader.java-impl
diff --git a/opengl/tools/glgen/stubs/GLCHeader.cpp b/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp
similarity index 61%
copy from opengl/tools/glgen/stubs/GLCHeader.cpp
copy to opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp
index 6495686..4494643 100644
--- a/opengl/tools/glgen/stubs/GLCHeader.cpp
+++ b/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp
@@ -21,11 +21,20 @@
 
 #include <assert.h>
 #include <GLES/gl.h>
+#include <GLES/glext.h>
 
-#include <private/opengles/gl_context.h>
-
-#define _NUM_COMPRESSED_TEXTURE_FORMATS \
-        (::android::OGLES_NUM_COMPRESSED_TEXTURE_FORMATS)
+/* special calls implemented in Android's GLES wrapper used to more
+ * efficiently bound-check passed arrays */
+extern "C" {
+GL_API void GL_APIENTRY glColorPointerBounds(GLint size, GLenum type, GLsizei stride,
+        const GLvoid *ptr, GLsizei count);
+GL_API void GL_APIENTRY glNormalPointerBounds(GLenum type, GLsizei stride,
+        const GLvoid *pointer, GLsizei count);
+GL_API void GL_APIENTRY glTexCoordPointerBounds(GLint size, GLenum type,
+        GLsizei stride, const GLvoid *pointer, GLsizei count);
+GL_API void GL_APIENTRY glVertexPointerBounds(GLint size, GLenum type,
+        GLsizei stride, const GLvoid *pointer, GLsizei count);
+}
 
 static int initialized = 0;
 
@@ -35,16 +44,18 @@
 static jclass UOEClass;
 static jclass IAEClass;
 static jclass AIOOBEClass;
+static jclass G11ImplClass;
 static jmethodID getBasePointerID;
 static jmethodID getBaseArrayID;
 static jmethodID getBaseArrayOffsetID;
+static jmethodID allowIndirectBuffersID;
 static jfieldID positionID;
 static jfieldID limitID;
 static jfieldID elementSizeShiftID;
 
 /* Cache method IDs each time the class is loaded. */
 
-void
+static void
 nativeClassInitBuffer(JNIEnv *_env)
 {
     jclass nioAccessClassLocal = _env->FindClass("java/nio/NIOAccess");
@@ -53,20 +64,23 @@
     jclass bufferClassLocal = _env->FindClass("java/nio/Buffer");
     bufferClass = (jclass) _env->NewGlobalRef(bufferClassLocal);
 
+    jclass g11impClassLocal = _env->FindClass("com/google/android/gles_jni/GLImpl");
+    G11ImplClass = (jclass) _env->NewGlobalRef(g11impClassLocal);
+
     getBasePointerID = _env->GetStaticMethodID(nioAccessClass,
             "getBasePointer", "(Ljava/nio/Buffer;)J");
     getBaseArrayID = _env->GetStaticMethodID(nioAccessClass,
             "getBaseArray", "(Ljava/nio/Buffer;)Ljava/lang/Object;");
     getBaseArrayOffsetID = _env->GetStaticMethodID(nioAccessClass,
             "getBaseArrayOffset", "(Ljava/nio/Buffer;)I");
-
+    allowIndirectBuffersID = _env->GetStaticMethodID(g11impClassLocal,
+            "allowIndirectBuffers", "(Ljava/lang/String;)Z");
     positionID = _env->GetFieldID(bufferClass, "position", "I");
     limitID = _env->GetFieldID(bufferClass, "limit", "I");
     elementSizeShiftID =
         _env->GetFieldID(bufferClass, "_elementSizeShift", "I");
 }
 
-
 static void
 nativeClassInit(JNIEnv *_env, jclass glImplClass)
 {
@@ -110,6 +124,9 @@
     
     *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
             getBaseArrayID, buffer);
+    if (*array == NULL) {
+        return (void*) NULL;
+    }
     offset = _env->CallStaticIntMethod(nioAccessClass,
             getBaseArrayOffsetID, buffer);
     data = _env->GetPrimitiveArrayCritical(*array, (jboolean *) 0);
@@ -117,7 +134,6 @@
     return (void *) ((char *) data + offset);
 }
 
-
 static void
 releasePointer(JNIEnv *_env, jarray array, void *data, jboolean commit)
 {
@@ -125,5 +141,51 @@
 					   commit ? 0 : JNI_ABORT);
 }
 
+extern "C" {
+extern char*  __progname;
+}
+
+static bool
+allowIndirectBuffers(JNIEnv *_env) {
+    static jint sIndirectBufferCompatability;
+    if (sIndirectBufferCompatability == 0) {
+        jobject appName = _env->NewStringUTF(::__progname);
+        sIndirectBufferCompatability = _env->CallStaticBooleanMethod(G11ImplClass, allowIndirectBuffersID, appName) ? 2 : 1;
+    }
+    return sIndirectBufferCompatability == 2;
+}
+
+static void *
+getDirectBufferPointer(JNIEnv *_env, jobject buffer) {
+    if (!buffer) {
+        return NULL;
+    }
+    void* buf = _env->GetDirectBufferAddress(buffer);
+    if (buf) {
+        jint position = _env->GetIntField(buffer, positionID);
+        jint elementSizeShift = _env->GetIntField(buffer, elementSizeShiftID);
+        buf = ((char*) buf) + (position << elementSizeShift);
+    } else {
+        if (allowIndirectBuffers(_env)) {
+            jarray array = 0;
+            jint remaining;
+            buf = getPointer(_env, buffer, &array, &remaining);
+            if (array) {
+                releasePointer(_env, array, buf, 0);
+            }
+        } else {
+            _env->ThrowNew(IAEClass, "Must use a native order direct Buffer");
+        }
+    }
+    return buf;
+}
+
+static int
+getNumCompressedTextureFormats() {
+    int numCompressedTextureFormats = 0;
+    glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numCompressedTextureFormats);
+    return numCompressedTextureFormats;
+}
+
 // --------------------------------------------------------------------------
 
diff --git a/opengl/tools/glgen/stubs/GLHeader.java-if b/opengl/tools/glgen/stubs/jsr239/GLHeader.java-if
similarity index 100%
rename from opengl/tools/glgen/stubs/GLHeader.java-if
rename to opengl/tools/glgen/stubs/jsr239/GLHeader.java-if
diff --git a/opengl/tools/glgen/stubs/jsr239/GLImplHeader.java-impl b/opengl/tools/glgen/stubs/jsr239/GLImplHeader.java-impl
new file mode 100644
index 0000000..fe60c5d
--- /dev/null
+++ b/opengl/tools/glgen/stubs/jsr239/GLImplHeader.java-impl
@@ -0,0 +1,75 @@
+**
+** 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 source file is automatically generated
+
+package com.google.android.gles_jni;
+
+import android.app.ActivityThread;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageManager;
+import android.os.Build;
+import android.util.Log;
+
+import java.nio.Buffer;
+import javax.microedition.khronos.opengles.GL10;
+import javax.microedition.khronos.opengles.GL10Ext;
+import javax.microedition.khronos.opengles.GL11;
+import javax.microedition.khronos.opengles.GL11Ext;
+import javax.microedition.khronos.opengles.GL11ExtensionPack;
+
+public class GLImpl implements GL10, GL10Ext, GL11, GL11Ext, GL11ExtensionPack {
+
+    // Private accessors for native code
+
+    native private static void _nativeClassInit();
+    static {
+	_nativeClassInit();
+    }
+
+    Buffer _colorPointer = null;
+    Buffer _normalPointer = null;
+    Buffer _texCoordPointer = null;
+    Buffer _vertexPointer = null;
+
+    public GLImpl() {
+    }
+
+    public void glGetPointerv(int pname, java.nio.Buffer[] params) {
+        throw new UnsupportedOperationException("glGetPointerv");
+    }
+
+    private static boolean allowIndirectBuffers(String appName) {
+        boolean result = false;
+        int version = 0;
+        IPackageManager pm = ActivityThread.getPackageManager();
+        try {
+            ApplicationInfo applicationInfo = pm.getApplicationInfo(appName, 0);
+            if (applicationInfo != null) {
+                version = applicationInfo.targetSdkVersion;
+            }
+        } catch (android.os.RemoteException e) {
+            // ignore
+        }
+        Log.e("OpenGLES", String.format(
+            "Application %s (SDK target %d) called a GL11 Pointer method with an indirect Buffer.",
+            appName, version));
+        if (version <= Build.VERSION_CODES.CUPCAKE) {
+            result = true;
+        }
+        return result;
+    }
+
diff --git a/opengl/tools/glgen/stubs/glGetString.cpp b/opengl/tools/glgen/stubs/jsr239/glGetString.cpp
similarity index 97%
copy from opengl/tools/glgen/stubs/glGetString.cpp
copy to opengl/tools/glgen/stubs/jsr239/glGetString.cpp
index 22e1297..a400859 100644
--- a/opengl/tools/glgen/stubs/glGetString.cpp
+++ b/opengl/tools/glgen/stubs/jsr239/glGetString.cpp
@@ -1,6 +1,7 @@
 #include <string.h>

 

 /* const GLubyte * glGetString ( GLenum name ) */

+static

 jstring

 android_glGetString

   (JNIEnv *_env, jobject _this, jint name) {

diff --git a/opengl/tools/glgen/stubs/glGetString.java-10-if b/opengl/tools/glgen/stubs/jsr239/glGetString.java-10-if
similarity index 100%
rename from opengl/tools/glgen/stubs/glGetString.java-10-if
rename to opengl/tools/glgen/stubs/jsr239/glGetString.java-10-if
diff --git a/opengl/tools/glgen/stubs/glGetString.java-if b/opengl/tools/glgen/stubs/jsr239/glGetString.java-if
similarity index 100%
rename from opengl/tools/glgen/stubs/glGetString.java-if
rename to opengl/tools/glgen/stubs/jsr239/glGetString.java-if
diff --git a/opengl/tools/glgen/stubs/glGetString.java-impl b/opengl/tools/glgen/stubs/jsr239/glGetString.java-impl
similarity index 100%
rename from opengl/tools/glgen/stubs/glGetString.java-impl
rename to opengl/tools/glgen/stubs/jsr239/glGetString.java-impl
diff --git a/opengl/tools/glgen/stubs/glGetString.nativeReg b/opengl/tools/glgen/stubs/jsr239/glGetString.nativeReg
similarity index 100%
rename from opengl/tools/glgen/stubs/glGetString.nativeReg
rename to opengl/tools/glgen/stubs/jsr239/glGetString.nativeReg
diff --git a/vpn/java/android/net/vpn/IVpnService.aidl b/vpn/java/android/net/vpn/IVpnService.aidl
new file mode 100644
index 0000000..fedccb0
--- /dev/null
+++ b/vpn/java/android/net/vpn/IVpnService.aidl
@@ -0,0 +1,43 @@
+/*
+ * 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 android.net.vpn;
+
+import android.net.vpn.VpnProfile;
+
+/**
+ * Interface to access a VPN service.
+ * {@hide}
+ */
+interface IVpnService {
+    /**
+     * Sets up the VPN connection.
+     * @param profile the profile object
+     * @param username the username for authentication
+     * @param password the corresponding password for authentication
+     */
+    boolean connect(in VpnProfile profile, String username, String password);
+
+    /**
+     * Tears down the VPN connection.
+     */
+    void disconnect();
+
+    /**
+     * Makes the service broadcast the connectivity state.
+     */
+    void checkStatus(in VpnProfile profile);
+}
diff --git a/vpn/java/android/net/vpn/L2tpIpsecProfile.java b/vpn/java/android/net/vpn/L2tpIpsecProfile.java
new file mode 100644
index 0000000..4ae2dec
--- /dev/null
+++ b/vpn/java/android/net/vpn/L2tpIpsecProfile.java
@@ -0,0 +1,65 @@
+/*
+ * 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 android.net.vpn;
+
+import android.os.Parcel;
+
+/**
+ * The profile for certificate-based L2TP-over-IPSec type of VPN.
+ * {@hide}
+ */
+public class L2tpIpsecProfile extends L2tpProfile {
+    private static final long serialVersionUID = 1L;
+
+    private String mUserCertificate;
+    private String mCaCertificate;
+
+    @Override
+    public VpnType getType() {
+        return VpnType.L2TP_IPSEC;
+    }
+
+    public void setCaCertificate(String name) {
+        mCaCertificate = name;
+    }
+
+    public String getCaCertificate() {
+        return mCaCertificate;
+    }
+
+    public void setUserCertificate(String name) {
+        mUserCertificate = name;
+    }
+
+    public String getUserCertificate() {
+        return mUserCertificate;
+    }
+
+    @Override
+    protected void readFromParcel(Parcel in) {
+        super.readFromParcel(in);
+        mCaCertificate = in.readString();
+        mUserCertificate = in.readString();
+    }
+
+    @Override
+    public void writeToParcel(Parcel parcel, int flags) {
+        super.writeToParcel(parcel, flags);
+        parcel.writeString(mCaCertificate);
+        parcel.writeString(mUserCertificate);
+    }
+}
diff --git a/vpn/java/android/net/vpn/L2tpIpsecPskProfile.java b/vpn/java/android/net/vpn/L2tpIpsecPskProfile.java
new file mode 100644
index 0000000..7a03018
--- /dev/null
+++ b/vpn/java/android/net/vpn/L2tpIpsecPskProfile.java
@@ -0,0 +1,54 @@
+/*
+ * 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 android.net.vpn;
+
+import android.os.Parcel;
+
+/**
+ * The profile for pre-shared-key-based L2TP-over-IPSec type of VPN.
+ * {@hide}
+ */
+public class L2tpIpsecPskProfile extends L2tpProfile {
+    private static final long serialVersionUID = 1L;
+
+    private String mPresharedKey;
+
+    @Override
+    public VpnType getType() {
+        return VpnType.L2TP_IPSEC_PSK;
+    }
+
+    public void setPresharedKey(String key) {
+        mPresharedKey = key;
+    }
+
+    public String getPresharedKey() {
+        return mPresharedKey;
+    }
+
+    @Override
+    protected void readFromParcel(Parcel in) {
+        super.readFromParcel(in);
+        mPresharedKey = in.readString();
+    }
+
+    @Override
+    public void writeToParcel(Parcel parcel, int flags) {
+        super.writeToParcel(parcel, flags);
+        parcel.writeString(mPresharedKey);
+    }
+}
diff --git a/vpn/java/android/net/vpn/L2tpProfile.java b/vpn/java/android/net/vpn/L2tpProfile.java
new file mode 100644
index 0000000..dbba0c5
--- /dev/null
+++ b/vpn/java/android/net/vpn/L2tpProfile.java
@@ -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.
+ */
+
+package android.net.vpn;
+
+import android.os.Parcel;
+
+/**
+ * The profile for L2TP type of VPN.
+ * {@hide}
+ */
+public class L2tpProfile extends VpnProfile {
+    private static final long serialVersionUID = 1L;
+
+    private boolean mSecret;
+    private String mSecretString;
+
+    @Override
+    public VpnType getType() {
+        return VpnType.L2TP;
+    }
+
+    /**
+     * Enables/disables the secret for authenticating tunnel connection.
+     */
+    public void setSecretEnabled(boolean enabled) {
+        mSecret = enabled;
+    }
+
+    public boolean isSecretEnabled() {
+        return mSecret;
+    }
+
+    public void setSecretString(String secret) {
+        mSecretString = secret;
+    }
+
+    public String getSecretString() {
+        return mSecretString;
+    }
+
+    @Override
+    protected void readFromParcel(Parcel in) {
+        super.readFromParcel(in);
+        mSecret = in.readInt() > 0;
+        mSecretString = in.readString();
+    }
+
+    @Override
+    public void writeToParcel(Parcel parcel, int flags) {
+        super.writeToParcel(parcel, flags);
+        parcel.writeInt(mSecret ? 1 : 0);
+        parcel.writeString(mSecretString);
+    }
+}
diff --git a/vpn/java/android/net/vpn/PptpProfile.java b/vpn/java/android/net/vpn/PptpProfile.java
new file mode 100644
index 0000000..b4b7be5
--- /dev/null
+++ b/vpn/java/android/net/vpn/PptpProfile.java
@@ -0,0 +1,56 @@
+/*
+ * 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 android.net.vpn;
+
+import android.os.Parcel;
+
+/**
+ * The profile for PPTP type of VPN.
+ * {@hide}
+ */
+public class PptpProfile extends VpnProfile {
+    private static final long serialVersionUID = 1L;
+    private boolean mEncryption = true;
+
+    @Override
+    public VpnType getType() {
+        return VpnType.PPTP;
+    }
+
+    /**
+     * Enables/disables the encryption for PPTP tunnel.
+     */
+    public void setEncryptionEnabled(boolean enabled) {
+        mEncryption = enabled;
+    }
+
+    public boolean isEncryptionEnabled() {
+        return mEncryption;
+    }
+
+    @Override
+    protected void readFromParcel(Parcel in) {
+        super.readFromParcel(in);
+        mEncryption = in.readInt() > 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel parcel, int flags) {
+        super.writeToParcel(parcel, flags);
+        parcel.writeInt(mEncryption ? 1 : 0);
+    }
+}
diff --git a/vpn/java/android/net/vpn/VpnManager.java b/vpn/java/android/net/vpn/VpnManager.java
new file mode 100644
index 0000000..f71bbea
--- /dev/null
+++ b/vpn/java/android/net/vpn/VpnManager.java
@@ -0,0 +1,187 @@
+/*
+ * 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 android.net.vpn;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.ServiceConnection;
+import android.util.Log;
+
+/**
+ * The class provides interface to manage all VPN-related tasks, including:
+ * <ul>
+ * <li>The list of supported VPN types.
+ * <li>API's to start/stop the service of a particular type.
+ * <li>API's to start the settings activity.
+ * <li>API's to create a profile.
+ * <li>API's to register/unregister a connectivity receiver and the keys to
+ *      access the fields in a connectivity broadcast event.
+ * </ul>
+ * {@hide}
+ */
+public class VpnManager {
+    // Action for broadcasting a connectivity state.
+    private static final String ACTION_VPN_CONNECTIVITY = "vpn.connectivity";
+    /** Key to the profile name of a connectivity broadcast event. */
+    public static final String BROADCAST_PROFILE_NAME = "profile_name";
+    /** Key to the connectivity state of a connectivity broadcast event. */
+    public static final String BROADCAST_CONNECTION_STATE = "connection_state";
+    /** 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;
+    /** Error code to indicate the connection attempt failed. */
+    public static final int VPN_ERROR_CONNECTION_FAILED = 2;
+    /** Error code to indicate the server is not known. */
+    public static final int VPN_ERROR_UNKNOWN_SERVER = 3;
+    /** Error code to indicate an error from challenge response. */
+    public static final int VPN_ERROR_CHALLENGE = 4;
+    /** Error code to indicate an error of remote server hanging up. */
+    public static final int VPN_ERROR_REMOTE_HUNG_UP = 5;
+    /** 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 String PROFILES_PATH = "/data/misc/vpn/profiles";
+
+    private static final String PACKAGE_PREFIX =
+            VpnManager.class.getPackage().getName() + ".";
+
+    // Action to start VPN service
+    private static final String ACTION_VPN_SERVICE = PACKAGE_PREFIX + "SERVICE";
+
+    // Action to start VPN settings
+    private static final String ACTION_VPN_SETTINGS =
+            PACKAGE_PREFIX + "SETTINGS";
+
+    private static final String TAG = VpnManager.class.getSimpleName();
+
+    /**
+     * Returns all supported VPN types.
+     */
+    public static VpnType[] getSupportedVpnTypes() {
+        return VpnType.values();
+    }
+
+    private Context mContext;
+
+    /**
+     * Creates a manager object with the specified context.
+     */
+    public VpnManager(Context c) {
+        mContext = c;
+    }
+
+    /**
+     * Creates a VPN profile of the specified type.
+     *
+     * @param type the VPN type
+     * @return the profile object
+     */
+    public VpnProfile createVpnProfile(VpnType type) {
+        return createVpnProfile(type, false);
+    }
+
+    /**
+     * Creates a VPN profile of the specified type.
+     *
+     * @param type the VPN type
+     * @param customized true if the profile is custom made
+     * @return the profile object
+     */
+    public VpnProfile createVpnProfile(VpnType type, boolean customized) {
+        try {
+            VpnProfile p = (VpnProfile) type.getProfileClass().newInstance();
+            p.setCustomized(customized);
+            return p;
+        } catch (InstantiationException e) {
+            return null;
+        } catch (IllegalAccessException e) {
+            return null;
+        }
+    }
+
+    /**
+     * Starts the VPN service to establish VPN connection.
+     */
+    public void startVpnService() {
+        mContext.startService(new Intent(ACTION_VPN_SERVICE));
+    }
+
+    /**
+     * Stops the VPN service.
+     */
+    public void stopVpnService() {
+        mContext.stopService(new Intent(ACTION_VPN_SERVICE));
+    }
+
+    /**
+     * Binds the specified ServiceConnection with the VPN service.
+     */
+    public boolean bindVpnService(ServiceConnection c) {
+        if (!mContext.bindService(new Intent(ACTION_VPN_SERVICE), c, 0)) {
+            Log.w(TAG, "failed to connect to VPN service");
+            return false;
+        } else {
+            Log.d(TAG, "succeeded to connect to VPN service");
+            return true;
+        }
+    }
+
+    /** Broadcasts the connectivity state of the specified profile. */
+    public void broadcastConnectivity(String profileName, VpnState s) {
+        broadcastConnectivity(profileName, s, VPN_ERROR_NO_ERROR);
+    }
+
+    /** Broadcasts the connectivity state with an error code. */
+    public void broadcastConnectivity(String profileName, VpnState s,
+            int error) {
+        Intent intent = new Intent(ACTION_VPN_CONNECTIVITY);
+        intent.putExtra(BROADCAST_PROFILE_NAME, profileName);
+        intent.putExtra(BROADCAST_CONNECTION_STATE, s);
+        if (error != VPN_ERROR_NO_ERROR) {
+            intent.putExtra(BROADCAST_ERROR_CODE, error);
+        }
+        mContext.sendBroadcast(intent);
+    }
+
+    public void registerConnectivityReceiver(BroadcastReceiver r) {
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(VpnManager.ACTION_VPN_CONNECTIVITY);
+        mContext.registerReceiver(r, filter);
+    }
+
+    public void unregisterConnectivityReceiver(BroadcastReceiver r) {
+        mContext.unregisterReceiver(r);
+    }
+
+    /** Starts the VPN settings activity. */
+    public void startSettingsActivity() {
+        Intent intent = new Intent(ACTION_VPN_SETTINGS);
+        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        mContext.startActivity(intent);
+    }
+
+    /** Creates an intent to start the VPN settings activity. */
+    public Intent createSettingsActivityIntent() {
+        Intent intent = new Intent(ACTION_VPN_SETTINGS);
+        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        return intent;
+    }
+}
diff --git a/vpn/java/android/net/vpn/VpnProfile.aidl b/vpn/java/android/net/vpn/VpnProfile.aidl
new file mode 100644
index 0000000..edeaef0
--- /dev/null
+++ b/vpn/java/android/net/vpn/VpnProfile.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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 android.net.vpn;
+
+parcelable VpnProfile;
diff --git a/vpn/java/android/net/vpn/VpnProfile.java b/vpn/java/android/net/vpn/VpnProfile.java
new file mode 100644
index 0000000..bd6c809
--- /dev/null
+++ b/vpn/java/android/net/vpn/VpnProfile.java
@@ -0,0 +1,177 @@
+/*
+ * 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 android.net.vpn;
+
+import android.content.Context;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.io.IOException;
+import java.io.Serializable;
+
+/**
+ * A VPN profile.
+ * {@hide}
+ */
+public abstract class VpnProfile implements Parcelable, Serializable {
+    private static final long serialVersionUID = 1L;
+    private String mName; // unique display name
+    private String mId; // unique identifier
+    private String mServerName; // VPN server name
+    private String mDomainSuffices; // space separated list
+    private String mRouteList; // space separated list
+    private String mSavedUsername;
+    private boolean mIsCustomized;
+    private transient VpnState mState = VpnState.IDLE;
+
+    /** Sets a user-friendly name for this profile. */
+    public void setName(String name) {
+        mName = name;
+    }
+
+    public String getName() {
+        return mName;
+    }
+
+    /**
+     * Sets an ID for this profile.  The caller should make sure the
+     * uniqueness of the ID.
+     */
+    public void setId(String id) {
+        mId = id;
+    }
+
+    public String getId() {
+        return mId;
+    }
+
+    /**
+     * Sets the name of the VPN server. Used for DNS lookup.
+     */
+    public void setServerName(String name) {
+        mServerName = name;
+    }
+
+    public String getServerName() {
+        return mServerName;
+    }
+
+    /**
+     * Sets the domain suffices for DNS resolution.
+     *
+     * @param entries a comma-separated list of domain suffices
+     */
+    public void setDomainSuffices(String entries) {
+        mDomainSuffices = entries;
+    }
+
+    public String getDomainSuffices() {
+        return mDomainSuffices;
+    }
+
+    /**
+     * Sets the routing info for this VPN connection.
+     *
+     * @param entries a comma-separated list of routes; each entry is in the
+     *      format of "(network address)/(network mask)"
+     */
+    public void setRouteList(String entries) {
+        mRouteList = entries;
+    }
+
+    public String getRouteList() {
+        return mRouteList;
+    }
+
+    public void setSavedUsername(String name) {
+        mSavedUsername = name;
+    }
+
+    public String getSavedUsername() {
+        return mSavedUsername;
+    }
+
+    public void setState(VpnState state) {
+        mState = state;
+    }
+
+    public VpnState getState() {
+        return ((mState == null) ? VpnState.IDLE : mState);
+    }
+
+    public boolean isIdle() {
+        return (mState == VpnState.IDLE);
+    }
+
+    /**
+     * Returns whether this profile is custom made (as opposed to being
+     * created by provided user interface).
+     */
+    public boolean isCustomized() {
+        return mIsCustomized;
+    }
+
+    /**
+     * Returns the VPN type of the profile.
+     */
+    public abstract VpnType getType();
+
+    void setCustomized(boolean customized) {
+        mIsCustomized = customized;
+    }
+
+    protected void readFromParcel(Parcel in) {
+        mName = in.readString();
+        mId = in.readString();
+        mServerName = in.readString();
+        mDomainSuffices = in.readString();
+        mRouteList = in.readString();
+        mSavedUsername = in.readString();
+    }
+
+    public static final Parcelable.Creator<VpnProfile> CREATOR =
+            new Parcelable.Creator<VpnProfile>() {
+                public VpnProfile createFromParcel(Parcel in) {
+                    VpnType type = Enum.valueOf(VpnType.class, in.readString());
+                    boolean customized = in.readInt() > 0;
+                    VpnProfile p = new VpnManager(null).createVpnProfile(type,
+                            customized);
+                    if (p == null) return null;
+                    p.readFromParcel(in);
+                    return p;
+                }
+
+                public VpnProfile[] newArray(int size) {
+                    return new VpnProfile[size];
+                }
+            };
+
+    public void writeToParcel(Parcel parcel, int flags) {
+        parcel.writeString(getType().toString());
+        parcel.writeInt(mIsCustomized ? 1 : 0);
+        parcel.writeString(mName);
+        parcel.writeString(mId);
+        parcel.writeString(mServerName);
+        parcel.writeString(mDomainSuffices);
+        parcel.writeString(mRouteList);
+        parcel.writeString(mSavedUsername);
+    }
+
+    public int describeContents() {
+        return 0;
+    }
+}
diff --git a/vpn/java/android/net/vpn/VpnState.java b/vpn/java/android/net/vpn/VpnState.java
new file mode 100644
index 0000000..6e61f9c
--- /dev/null
+++ b/vpn/java/android/net/vpn/VpnState.java
@@ -0,0 +1,38 @@
+/*
+ * 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 android.net.vpn;
+
+/**
+ * Enumeration of all VPN states.
+ *
+ * A normal VPN connection lifetime starts in {@link IDLE}. When a new
+ * connection is about to be set up, it goes to {@link CONNECTING} and then
+ * {@link CONNECTED} if successful; back to {@link IDLE} if failed.
+ * When the connection is about to be torn down, it goes to
+ * {@link DISCONNECTING} and then {@link IDLE}.
+ * {@link CANCELLED} is a state when a VPN connection attempt is aborted, and
+ * is in transition to {@link IDLE}.
+ * The {@link UNUSABLE} state indicates that the profile is not in a state for
+ * connecting due to possibly the integrity of the fields or another profile is
+ * connecting etc.
+ * The {@link UNKNOWN} state indicates that the profile state is to be
+ * determined.
+ * {@hide}
+ */
+public enum VpnState {
+    CONNECTING, DISCONNECTING, CANCELLED, CONNECTED, IDLE, UNUSABLE, UNKNOWN
+}
diff --git a/vpn/java/android/net/vpn/VpnType.java b/vpn/java/android/net/vpn/VpnType.java
new file mode 100644
index 0000000..c7df943
--- /dev/null
+++ b/vpn/java/android/net/vpn/VpnType.java
@@ -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.
+ */
+
+package android.net.vpn;
+
+/**
+ * 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",
+            L2tpIpsecPskProfile.class),
+    L2TP_IPSEC("L2TP/IPSec CRT", "Certificate based L2TP/IPSec VPN",
+            L2tpIpsecProfile.class);
+
+    private String mDisplayName;
+    private String mDescription;
+    private Class<? extends VpnProfile> mClass;
+
+    VpnType(String displayName, String description,
+            Class<? extends VpnProfile> klass) {
+        mDisplayName = displayName;
+        mDescription = description;
+        mClass = klass;
+    }
+
+    public String getDisplayName() {
+        return mDisplayName;
+    }
+
+    public String getDescription() {
+        return mDescription;
+    }
+
+    public Class<? extends VpnProfile> getProfileClass() {
+        return mClass;
+    }
+}