Merge change 20146

* changes:
  Calendar attendee support: add columns.
diff --git a/cmds/keystore/netkeystore.c b/cmds/keystore/netkeystore.c
index eac455e..637e0d8 100644
--- a/cmds/keystore/netkeystore.c
+++ b/cmds/keystore/netkeystore.c
@@ -37,6 +37,7 @@
 #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);
@@ -397,12 +398,12 @@
 
         // read the command, execute and send the result back.
         if(read_marshal(s, &cmd)) goto err;
-        LOGI("new connection\n");
+        if (DBG) LOGD("new connection\n");
         execute(&cmd, &reply);
         write_marshal(s, &reply);
 err:
         memset(&reply, 0, sizeof(LPC_MARSHAL));
-        LOGI("closing connection\n");
+        if (DBG) LOGD("closing connection\n");
         close(s);
     }
 
diff --git a/include/ui/EventHub.h b/include/ui/EventHub.h
index d62fd7d..bffba07 100644
--- a/include/ui/EventHub.h
+++ b/include/ui/EventHub.h
@@ -55,7 +55,9 @@
         CLASS_KEYBOARD      = 0x00000001,
         CLASS_ALPHAKEY      = 0x00000002,
         CLASS_TOUCHSCREEN   = 0x00000004,
-        CLASS_TRACKBALL     = 0x00000008
+        CLASS_TRACKBALL     = 0x00000008,
+        CLASS_TOUCHSCREEN_MT= 0x00000010,
+        CLASS_DPAD          = 0x00000020
     };
     uint32_t getDeviceClasses(int32_t deviceId) const;
     
@@ -122,6 +124,7 @@
     };
 
     device_t* getDevice(int32_t deviceId) const;
+    bool hasKeycode(device_t* device, int keycode) const;
     
     // Protect all internal state.
     mutable Mutex   mLock;
diff --git a/include/ui/Surface.h b/include/ui/Surface.h
index 156d453..5665c1f 100644
--- a/include/ui/Surface.h
+++ b/include/ui/Surface.h
@@ -36,6 +36,7 @@
 
 class BufferMapper;
 class Rect;
+class MediaPlayerImpl;
 class Surface;
 class SurfaceComposerClient;
 struct per_client_cblk_t;
@@ -180,6 +181,7 @@
     // mediaplayer needs access to ISurface for display
     friend class MediaPlayer;
     friend class Test;
+    friend class MediaPlayerImpl;
     const sp<ISurface>& getISurface() const { return mSurface; }
 
     status_t getBufferLocked(int index);
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index f40e4bd..785a3c5 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -661,7 +661,7 @@
 
 status_t Parcel::writeNativeHandle(const native_handle* handle)
 {
-    if (handle->version != sizeof(native_handle))
+    if (!handle || handle->version != sizeof(native_handle))
         return BAD_TYPE;
 
     status_t err;
diff --git a/libs/surfaceflinger/LayerBitmap.cpp b/libs/surfaceflinger/LayerBitmap.cpp
index ff49c87..5221fed 100644
--- a/libs/surfaceflinger/LayerBitmap.cpp
+++ b/libs/surfaceflinger/LayerBitmap.cpp
@@ -178,6 +178,7 @@
 {
     Mutex::Autolock _l(mLock);
     surface_info_t* info = mInfo;
+    mBuffer.clear(); // free buffer before allocating a new one
     sp<Buffer> buffer = new Buffer(mWidth, mHeight, mFormat, mFlags);
     status_t err = buffer->initCheck();
     if (LIKELY(err == NO_ERROR)) {
diff --git a/libs/ui/EventHub.cpp b/libs/ui/EventHub.cpp
index 59c9476..27334b7 100644
--- a/libs/ui/EventHub.cpp
+++ b/libs/ui/EventHub.cpp
@@ -16,6 +16,7 @@
 //#define LOG_NDEBUG 0
 
 #include <ui/EventHub.h>
+#include <ui/KeycodeLabels.h>
 #include <hardware_legacy/power.h>
 
 #include <cutils/properties.h>
@@ -58,6 +59,18 @@
 #define SEQ_SHIFT 16
 #define id_to_index(id)         ((id&ID_MASK)+1)
 
+#ifndef ABS_MT_TOUCH_MAJOR
+#define ABS_MT_TOUCH_MAJOR      0x30    /* Major axis of touching ellipse */
+#endif
+
+#ifndef ABS_MT_POSITION_X
+#define ABS_MT_POSITION_X       0x35    /* Center X ellipse position */
+#endif
+
+#ifndef ABS_MT_POSITION_Y
+#define ABS_MT_POSITION_Y       0x36    /* Center Y ellipse position */
+#endif
+
 namespace android {
 
 static const char *WAKE_LOCK_ID = "KeyEvents";
@@ -590,6 +603,8 @@
     mFDs[mFDCount].events = POLLIN;
 
     // figure out the kinds of events the device reports
+    
+    // See if this is a keyboard, and classify it.
     uint8_t key_bitmask[(KEY_MAX+1)/8];
     memset(key_bitmask, 0, sizeof(key_bitmask));
     LOGV("Getting keys...");
@@ -601,15 +616,11 @@
         for (int i=0; i<((BTN_MISC+7)/8); i++) {
             if (key_bitmask[i] != 0) {
                 device->classes |= CLASS_KEYBOARD;
-                // 'Q' key support = cheap test of whether this is an alpha-capable kbd
-                if (test_bit(KEY_Q, key_bitmask)) {
-                    device->classes |= CLASS_ALPHAKEY;
-                }
                 break;
             }
         }
         if ((device->classes & CLASS_KEYBOARD) != 0) {
-            device->keyBitmask = new uint8_t[(KEY_MAX+1)/8];
+            device->keyBitmask = new uint8_t[sizeof(key_bitmask)];
             if (device->keyBitmask != NULL) {
                 memcpy(device->keyBitmask, key_bitmask, sizeof(key_bitmask));
             } else {
@@ -619,6 +630,8 @@
             }
         }
     }
+    
+    // See if this is a trackball.
     if (test_bit(BTN_MOUSE, key_bitmask)) {
         uint8_t rel_bitmask[(REL_MAX+1)/8];
         memset(rel_bitmask, 0, sizeof(rel_bitmask));
@@ -630,16 +643,22 @@
             }
         }
     }
-    if (test_bit(BTN_TOUCH, key_bitmask)) {
-        uint8_t abs_bitmask[(ABS_MAX+1)/8];
-        memset(abs_bitmask, 0, sizeof(abs_bitmask));
-        LOGV("Getting absolute controllers...");
-        if (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(abs_bitmask)), abs_bitmask) >= 0)
-        {
-            if (test_bit(ABS_X, abs_bitmask) && test_bit(ABS_Y, abs_bitmask)) {
-                device->classes |= CLASS_TOUCHSCREEN;
-            }
-        }
+    
+    uint8_t abs_bitmask[(ABS_MAX+1)/8];
+    memset(abs_bitmask, 0, sizeof(abs_bitmask));
+    LOGV("Getting absolute controllers...");
+    ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(abs_bitmask)), abs_bitmask);
+    
+    // Is this a new modern multi-touch driver?
+    if (test_bit(ABS_MT_TOUCH_MAJOR, abs_bitmask)
+            && test_bit(ABS_MT_POSITION_X, abs_bitmask)
+            && test_bit(ABS_MT_POSITION_Y, abs_bitmask)) {
+        device->classes |= CLASS_TOUCHSCREEN | CLASS_TOUCHSCREEN_MT;
+        
+    // Is this an old style single-touch driver?
+    } else if (test_bit(BTN_TOUCH, key_bitmask)
+            && test_bit(ABS_X, abs_bitmask) && test_bit(ABS_Y, abs_bitmask)) {
+        device->classes |= CLASS_TOUCHSCREEN;
     }
 
 #ifdef EV_SW
@@ -658,9 +677,6 @@
     }
 #endif
 
-    LOGI("New device: path=%s name=%s id=0x%x (of 0x%x) index=%d fd=%d classes=0x%x\n",
-         deviceName, name, device->id, mNumDevicesById, mFDCount, fd, device->classes);
-
     if ((device->classes&CLASS_KEYBOARD) != 0) {
         char devname[101];
         char tmpfn[101];
@@ -707,10 +723,27 @@
         sprintf(propName, "hw.keyboards.%u.devname", publicID);
         property_set(propName, devname);
 
-        LOGI("New keyboard: publicID=%d device->id=%d devname='%s' propName='%s' keylayout='%s'\n",
+        // 'Q' key support = cheap test of whether this is an alpha-capable kbd
+        if (hasKeycode(device, kKeyCodeQ)) {
+            device->classes |= CLASS_ALPHAKEY;
+        }
+        
+        // See if this has a DPAD.
+        if (hasKeycode(device, kKeyCodeDpadUp) &&
+                hasKeycode(device, kKeyCodeDpadDown) &&
+                hasKeycode(device, kKeyCodeDpadLeft) &&
+                hasKeycode(device, kKeyCodeDpadRight) &&
+                hasKeycode(device, kKeyCodeDpadCenter)) {
+            device->classes |= CLASS_DPAD;
+        }
+        
+        LOGI("New keyboard: publicID=%d device->id=0x%x devname='%s' propName='%s' keylayout='%s'\n",
                 publicID, device->id, devname, propName, keylayoutFilename);
     }
 
+    LOGI("New device: path=%s name=%s id=0x%x (of 0x%x) index=%d fd=%d classes=0x%x\n",
+         deviceName, name, device->id, mNumDevicesById, mFDCount, fd, device->classes);
+         
     LOGV("Adding device %s %p at %d, id = %d, classes = 0x%x\n",
          deviceName, device, mFDCount, devid, device->classes);
 
@@ -723,6 +756,25 @@
     return 0;
 }
 
+bool EventHub::hasKeycode(device_t* device, int keycode) const
+{
+    if (device->keyBitmask == NULL || device->layoutMap == NULL) {
+        return false;
+    }
+    
+    Vector<int32_t> scanCodes;
+    device->layoutMap->findScancodes(keycode, &scanCodes);
+    const size_t N = scanCodes.size();
+    for (size_t i=0; i<N && i<=KEY_MAX; i++) {
+        int32_t sc = scanCodes.itemAt(i);
+        if (sc >= 0 && sc <= KEY_MAX && test_bit(sc, device->keyBitmask)) {
+            return true;
+        }
+    }
+    
+    return false;
+}
+
 int EventHub::close_device(const char *deviceName)
 {
     AutoMutex _l(mLock);
diff --git a/libs/ui/Surface.cpp b/libs/ui/Surface.cpp
index 04ab64c..c73909f 100644
--- a/libs/ui/Surface.cpp
+++ b/libs/ui/Surface.cpp
@@ -108,6 +108,9 @@
 status_t SurfaceBuffer::writeToParcel(Parcel* reply, 
         android_native_buffer_t const* buffer)
 {
+    if (buffer == NULL) {
+        return BAD_VALUE;
+    }
     reply->writeInt32(buffer->width);
     reply->writeInt32(buffer->height);
     reply->writeInt32(buffer->stride);
@@ -558,14 +561,16 @@
 
     volatile const surface_info_t* const back = lcblk->surface + backIdx;
     if (back->flags & surface_info_t::eNeedNewBuffer) {
-        getBufferLocked(backIdx);
+        err = getBufferLocked(backIdx);
     }
 
-    const sp<SurfaceBuffer>& backBuffer(mBuffers[backIdx]);
-    mDirtyRegion.set(backBuffer->width, backBuffer->height);
-    *buffer = backBuffer.get();
+    if (err == NO_ERROR) {
+        const sp<SurfaceBuffer>& backBuffer(mBuffers[backIdx]);
+        mDirtyRegion.set(backBuffer->width, backBuffer->height);
+        *buffer = backBuffer.get();
+    }
   
-    return NO_ERROR;
+    return err;
 }
 
 int Surface::lockBuffer(android_native_buffer_t* buffer)
@@ -729,7 +734,7 @@
             currentBuffer.clear();
         }
         err = getBufferMapper().registerBuffer(buffer->handle);
-        LOGW_IF(err, "map(...) failed %d (%s)", err, strerror(-err));
+        LOGW_IF(err, "registerBuffer(...) failed %d (%s)", err, strerror(-err));
         if (err == NO_ERROR) {
             currentBuffer = buffer;
         }
diff --git a/libs/utils/Threads.cpp b/libs/utils/Threads.cpp
index 4036c49..6be372c 100644
--- a/libs/utils/Threads.cpp
+++ b/libs/utils/Threads.cpp
@@ -296,6 +296,19 @@
     // XXX: name not used for now
     HANDLE hMutex;
 
+    assert(sizeof(hMutex) == sizeof(mState));
+
+    hMutex = CreateMutex(NULL, FALSE, NULL);
+    mState = (void*) hMutex;
+}
+
+Mutex::Mutex(int type, const char* name)
+{
+    // XXX: type and name not used for now
+    HANDLE hMutex;
+
+    assert(sizeof(hMutex) == sizeof(mState));
+
     hMutex = CreateMutex(NULL, FALSE, NULL);
     mState = (void*) hMutex;
 }
@@ -486,7 +499,11 @@
 
 status_t Condition::waitRelative(Mutex& mutex, nsecs_t reltime)
 {
-    return wait(mutex, systemTime()+reltime);
+    WinCondition* condState = (WinCondition*) mState;
+    HANDLE hMutex = (HANDLE) mutex.mState;
+    nsecs_t absTime = systemTime()+reltime;
+
+    return ((WinCondition*)mState)->wait(condState, hMutex, &absTime);
 }
 
 /*
diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp
index b0e54d8..cf66be3 100644
--- a/opengl/libagl/egl.cpp
+++ b/opengl/libagl/egl.cpp
@@ -145,7 +145,7 @@
 
     virtual     EGLBoolean  bindDrawSurface(ogles_context_t* gl) = 0;
     virtual     EGLBoolean  bindReadSurface(ogles_context_t* gl) = 0;
-    virtual     void        connect() {}
+    virtual     EGLBoolean  connect() { return EGL_TRUE; }
     virtual     void        disconnect() {}
     virtual     EGLint      getWidth() const = 0;
     virtual     EGLint      getHeight() const = 0;
@@ -214,7 +214,7 @@
     virtual     EGLBoolean  swapBuffers();
     virtual     EGLBoolean  bindDrawSurface(ogles_context_t* gl);
     virtual     EGLBoolean  bindReadSurface(ogles_context_t* gl);
-    virtual     void        connect();
+    virtual     EGLBoolean  connect();
     virtual     void        disconnect();
     virtual     EGLint      getWidth() const    { return width;  }
     virtual     EGLint      getHeight() const   { return height; }
@@ -382,10 +382,12 @@
     }
 }
 
-void egl_window_surface_v2_t::connect() 
+EGLBoolean egl_window_surface_v2_t::connect() 
 {
     // dequeue a buffer
-    nativeWindow->dequeueBuffer(nativeWindow, &buffer);
+    if (nativeWindow->dequeueBuffer(nativeWindow, &buffer) != NO_ERROR) {
+        return setError(EGL_BAD_ALLOC, EGL_FALSE);
+    }
 
     // allocate a corresponding depth-buffer
     width = buffer->width;
@@ -396,8 +398,7 @@
         depth.stride  = depth.width; // use the width here
         depth.data    = (GGLubyte*)malloc(depth.stride*depth.height*2);
         if (depth.data == 0) {
-            setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
-            return;
+            return setError(EGL_BAD_ALLOC, EGL_FALSE);
         }
     }
 
@@ -411,9 +412,10 @@
             GRALLOC_USAGE_SW_WRITE_OFTEN, &bits) != NO_ERROR) {
         LOGE("connect() failed to lock buffer %p (%ux%u)",
                 buffer, buffer->width, buffer->height);
-        setError(EGL_BAD_ACCESS, EGL_NO_SURFACE);
+        return setError(EGL_BAD_ACCESS, EGL_FALSE);
         // FIXME: we should make sure we're not accessing the buffer anymore
     }
+    return EGL_TRUE;
 }
 
 void egl_window_surface_v2_t::disconnect() 
@@ -444,6 +446,7 @@
 
 status_t egl_window_surface_v2_t::unlock(android_native_buffer_t* buf)
 {
+    if (!buf) return BAD_VALUE;
     int err = module->unlock(module, buf->handle);
     return err;
 }
@@ -515,6 +518,10 @@
 
 EGLBoolean egl_window_surface_v2_t::swapBuffers()
 {
+    if (!buffer) {
+        return setError(EGL_BAD_ACCESS, EGL_FALSE);
+    }
+    
     /*
      * Handle eglSetSwapRectangleANDROID()
      * We copyback from the front buffer 
@@ -580,7 +587,7 @@
             GRALLOC_USAGE_SW_WRITE_OFTEN, &bits) != NO_ERROR) {
         LOGE("eglSwapBuffers() failed to lock buffer %p (%ux%u)",
                 buffer, buffer->width, buffer->height);
-        setError(EGL_BAD_ACCESS, EGL_NO_SURFACE);
+        return setError(EGL_BAD_ACCESS, EGL_FALSE);
         // FIXME: we should make sure we're not accessing the buffer anymore
     }
 
@@ -1748,7 +1755,9 @@
                 ogles_scissor(gl, 0, 0, w, h);
             }
             if (d) {
-                d->connect();
+                if (d->connect() == EGL_FALSE) {
+                    return EGL_FALSE;
+                }
                 d->ctx = ctx;
                 d->bindDrawSurface(gl);
             }
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index c2003dd..236d247 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -135,9 +135,10 @@
 
 struct tls_t
 {
-    tls_t() : error(EGL_SUCCESS), ctx(0) { }
+    tls_t() : error(EGL_SUCCESS), ctx(0), logCallWithNoContext(EGL_TRUE) { }
     EGLint      error;
     EGLContext  ctx;
+    EGLBoolean  logCallWithNoContext;
 };
 
 
@@ -352,8 +353,14 @@
 }
 
 static void gl_no_context() {
-    LOGE("call to OpenGL ES API with no current context");
+    tls_t* tls = getTLS();
+    if (tls->logCallWithNoContext == EGL_TRUE) {
+        tls->logCallWithNoContext = EGL_FALSE;
+        LOGE("call to OpenGL ES API with no current context "
+             "(logged once per thread)");
+    }
 }
+
 static void early_egl_init(void) 
 {
 #if !USE_FAST_TLS_KEY
diff --git a/opengl/tests/angeles/app-linux.c b/opengl/tests/angeles/app-linux.c
index 7d0d320..6be4876 100644
--- a/opengl/tests/angeles/app-linux.c
+++ b/opengl/tests/angeles/app-linux.c
@@ -132,6 +132,7 @@
      };
      
      EGLint numConfigs = -1;
+     EGLint n = 0;
      EGLint majorVersion;
      EGLint minorVersion;
      EGLConfig config;
@@ -148,15 +149,43 @@
      egl_error("eglInitialize");
 
      eglGetConfigs(dpy, NULL, 0, &numConfigs);
-     egl_error("eglGetConfigs");
-     fprintf(stderr,"num configs %d\n", numConfigs);
+
+     // Get all the "potential match" configs...
+     EGLConfig* const configs = malloc(sizeof(EGLConfig)*numConfigs);
+     eglChooseConfig(dpy, s_configAttribs, configs, numConfigs, &n);
+     config = configs[0];
+     if (n > 1) {
+         // if there is more than one candidate, go through the list
+         // and pick one that matches our framebuffer format
+         int fbSzA = 0; // should not hardcode
+         int fbSzR = 5; // should not hardcode
+         int fbSzG = 6; // should not hardcode
+         int fbSzB = 5; // should not hardcode
+         int i;
+         for (i=0 ; i<n ; i++) {
+             EGLint r,g,b,a;
+             eglGetConfigAttrib(dpy, configs[i], EGL_RED_SIZE,   &r);
+             eglGetConfigAttrib(dpy, configs[i], EGL_GREEN_SIZE, &g);
+             eglGetConfigAttrib(dpy, configs[i], EGL_BLUE_SIZE,  &b);
+             eglGetConfigAttrib(dpy, configs[i], EGL_ALPHA_SIZE, &a);
+             if (fbSzA == a && fbSzR == r && fbSzG == g && fbSzB  == b) {
+                 config = configs[i];
+                 break;
+             }
+         }
+     }
+     free(configs);
      
-     eglChooseConfig(dpy, s_configAttribs, &config, 1, &numConfigs);
-     egl_error("eglChooseConfig");
+     
+     //eglGetConfigs(dpy, NULL, 0, &numConfigs);
+     //egl_error("eglGetConfigs");
+     //fprintf(stderr,"num configs %d\n", numConfigs);     
+     //eglChooseConfig(dpy, s_configAttribs, &config, 1, &numConfigs);
+     //egl_error("eglChooseConfig");
 
      surface = eglCreateWindowSurface(dpy, config,
              android_createDisplaySurface(), NULL);
-     egl_error("eglMapWindowSurface");
+     egl_error("eglCreateWindowSurface");
 
      fprintf(stderr,"surface = %p\n", surface);
 
diff --git a/opengl/tests/fillrate/Android.mk b/opengl/tests/fillrate/Android.mk
new file mode 100644
index 0000000..a7d30c2
--- /dev/null
+++ b/opengl/tests/fillrate/Android.mk
@@ -0,0 +1,17 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+	fillrate.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+	libcutils \
+    libEGL \
+    libGLESv1_CM \
+    libui
+
+LOCAL_MODULE:= test-opengl-fillrate
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_EXECUTABLE)
diff --git a/opengl/tests/fillrate/fillrate.cpp b/opengl/tests/fillrate/fillrate.cpp
new file mode 100644
index 0000000..c814e8d
--- /dev/null
+++ b/opengl/tests/fillrate/fillrate.cpp
@@ -0,0 +1,149 @@
+/*
+**
+** Copyright 2006, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License"); 
+** you may not use this file except in compliance with the License. 
+** You may obtain a copy of the License at 
+**
+**     http://www.apache.org/licenses/LICENSE-2.0 
+**
+** Unless required by applicable law or agreed to in writing, software 
+** distributed under the License is distributed on an "AS IS" BASIS, 
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+** See the License for the specific language governing permissions and 
+** limitations under the License.
+*/
+
+#define LOG_TAG "fillrate"
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <EGL/egl.h>
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+
+#include <utils/StopWatch.h>
+#include <ui/FramebufferNativeWindow.h>
+
+using namespace android;
+
+int main(int argc, char** argv)
+{
+    EGLint configAttribs[] = {
+         EGL_DEPTH_SIZE, 0,
+         EGL_NONE
+     };
+     
+     EGLint numConfigs = -1, n=0;
+     EGLint majorVersion;
+     EGLint minorVersion;
+     EGLConfig config;
+     EGLContext context;
+     EGLSurface surface;
+     EGLint w, h;
+     
+     EGLDisplay dpy;
+
+     dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+     eglInitialize(dpy, &majorVersion, &minorVersion);
+     
+     // Get all the "potential match" configs...
+     eglGetConfigs(dpy, NULL, 0, &numConfigs);
+     EGLConfig* const configs = (EGLConfig*)malloc(sizeof(EGLConfig)*numConfigs);
+     eglChooseConfig(dpy, configAttribs, configs, numConfigs, &n);
+     config = configs[0];
+     if (n > 1) {
+         // if there is more than one candidate, go through the list
+         // and pick one that matches our framebuffer format
+         int fbSzA = 0; // should not hardcode
+         int fbSzR = 5; // should not hardcode
+         int fbSzG = 6; // should not hardcode
+         int fbSzB = 5; // should not hardcode
+         int i;
+         for (i=0 ; i<n ; i++) {
+             EGLint r,g,b,a;
+             eglGetConfigAttrib(dpy, configs[i], EGL_RED_SIZE,   &r);
+             eglGetConfigAttrib(dpy, configs[i], EGL_GREEN_SIZE, &g);
+             eglGetConfigAttrib(dpy, configs[i], EGL_BLUE_SIZE,  &b);
+             eglGetConfigAttrib(dpy, configs[i], EGL_ALPHA_SIZE, &a);
+             if (fbSzA == a && fbSzR == r && fbSzG == g && fbSzB  == b) {
+                 config = configs[i];
+                 break;
+             }
+         }
+     }
+     free(configs);
+     
+     surface = eglCreateWindowSurface(dpy, config,
+             android_createDisplaySurface(), NULL);
+     context = eglCreateContext(dpy, config, NULL, NULL);
+     eglMakeCurrent(dpy, surface, surface, context);   
+     eglQuerySurface(dpy, surface, EGL_WIDTH, &w);
+     eglQuerySurface(dpy, surface, EGL_HEIGHT, &h);
+     
+     printf("w=%d, h=%d\n", w, h);
+     
+     glBindTexture(GL_TEXTURE_2D, 0);
+     glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+     glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+     glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+     glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+     glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+     glDisable(GL_DITHER);
+     glDisable(GL_BLEND);
+     glEnable(GL_TEXTURE_2D);
+     glColor4f(1,1,1,1);
+
+     uint32_t* t32 = (uint32_t*)malloc(512*512*4); 
+     for (int y=0 ; y<512 ; y++) {
+         for (int x=0 ; x<512 ; x++) {
+             t32[x+y*512] = 0x10FFFFFF;
+         }
+     }
+
+     const GLfloat vertices[4][2] = {
+             { 0,  0 },
+             { 0,  h },
+             { w,  h },
+             { w,  0 }
+     };
+
+     const GLfloat texCoords[4][2] = {
+             { 0,  0 },
+             { 0,  1 },
+             { 1,  1 },
+             { 1,  0 }
+     };
+
+     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 512, 512, 0, GL_RGBA, GL_UNSIGNED_BYTE, t32);
+
+     glViewport(0, 0, w, h);
+     glMatrixMode(GL_PROJECTION);
+     glLoadIdentity();
+     glOrthof(0, w, 0, h, 0, 1);
+
+     glEnableClientState(GL_VERTEX_ARRAY);
+     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+     glVertexPointer(2, GL_FIXED, 0, vertices);
+     glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
+
+     glClearColor(1,0,0,0);
+     glClear(GL_COLOR_BUFFER_BIT);
+     glDrawArrays(GL_TRIANGLE_FAN, 0, 4); 
+     eglSwapBuffers(dpy, surface);
+     
+     for (int c=1 ; c<32 ; c++) {
+         glClear(GL_COLOR_BUFFER_BIT);
+         nsecs_t now = systemTime();
+         for (int i=0 ; i<c ; i++) {
+             glDrawArrays(GL_TRIANGLE_FAN, 0, 4); 
+         }
+         eglSwapBuffers(dpy, surface);
+         nsecs_t t = systemTime() - now;
+         printf("%lld\t%d\t%f\n", t, c, (double(t)/c)/1000000.0);
+     }
+     return 0;
+}
diff --git a/opengl/tests/textures/textures.c b/opengl/tests/textures/textures.c
index 214291b..d877e74 100644
--- a/opengl/tests/textures/textures.c
+++ b/opengl/tests/textures/textures.c
@@ -31,7 +31,7 @@
          EGL_NONE
      };
      
-     EGLint numConfigs = -1;
+     EGLint numConfigs = -1, n=0;
      EGLint majorVersion;
      EGLint minorVersion;
      EGLConfig config;
@@ -43,7 +43,36 @@
 
      dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
      eglInitialize(dpy, &majorVersion, &minorVersion);
-     eglChooseConfig(dpy, s_configAttribs, &config, 1, &numConfigs);
+     
+     // Get all the "potential match" configs...
+     eglGetConfigs(dpy, NULL, 0, &numConfigs);
+     EGLConfig* const configs = malloc(sizeof(EGLConfig)*numConfigs);
+     eglChooseConfig(dpy, s_configAttribs, configs, numConfigs, &n);
+     config = configs[0];
+     if (n > 1) {
+         // if there is more than one candidate, go through the list
+         // and pick one that matches our framebuffer format
+         int fbSzA = 0; // should not hardcode
+         int fbSzR = 5; // should not hardcode
+         int fbSzG = 6; // should not hardcode
+         int fbSzB = 5; // should not hardcode
+         int i;
+         for (i=0 ; i<n ; i++) {
+             EGLint r,g,b,a;
+             eglGetConfigAttrib(dpy, configs[i], EGL_RED_SIZE,   &r);
+             eglGetConfigAttrib(dpy, configs[i], EGL_GREEN_SIZE, &g);
+             eglGetConfigAttrib(dpy, configs[i], EGL_BLUE_SIZE,  &b);
+             eglGetConfigAttrib(dpy, configs[i], EGL_ALPHA_SIZE, &a);
+             if (fbSzA == a && fbSzR == r && fbSzG == g && fbSzB  == b) {
+                 config = configs[i];
+                 break;
+             }
+         }
+     }
+     free(configs);
+     
+     
+     
      surface = eglCreateWindowSurface(dpy, config,
              android_createDisplaySurface(), NULL);
      context = eglCreateContext(dpy, config, NULL, NULL);
diff --git a/vpn/java/android/net/vpn/VpnManager.java b/vpn/java/android/net/vpn/VpnManager.java
index e448e5a..f71bbea 100644
--- a/vpn/java/android/net/vpn/VpnManager.java
+++ b/vpn/java/android/net/vpn/VpnManager.java
@@ -54,6 +54,8 @@
     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";