Merge "Added Visualizer effect." into gingerbread
diff --git a/camera/libcameraservice/CameraService.cpp b/camera/libcameraservice/CameraService.cpp
index 75948a5..10668a4 100644
--- a/camera/libcameraservice/CameraService.cpp
+++ b/camera/libcameraservice/CameraService.cpp
@@ -1031,6 +1031,7 @@
             mHardware->getRawHeap());
 
         mSurface->registerBuffers(buffers);
+        IPCThreadState::self()->flushCommands();
     }
 
     mLock.unlock();
diff --git a/include/surfaceflinger/Surface.h b/include/surfaceflinger/Surface.h
index f333911..4fd0681 100644
--- a/include/surfaceflinger/Surface.h
+++ b/include/surfaceflinger/Surface.h
@@ -131,7 +131,7 @@
 // ---------------------------------------------------------------------------
 
 class Surface 
-    : public EGLNativeBase<android_native_window_t, Surface, RefBase>
+    : public EGLNativeBase<ANativeWindow, Surface, RefBase>
 {
 public:
     struct SurfaceInfo {
@@ -195,14 +195,14 @@
 
 
     /*
-     *  android_native_window_t hooks
+     *  ANativeWindow hooks
      */
-    static int setSwapInterval(android_native_window_t* window, int interval);
-    static int dequeueBuffer(android_native_window_t* window, android_native_buffer_t** buffer);
-    static int lockBuffer(android_native_window_t* window, android_native_buffer_t* buffer);
-    static int queueBuffer(android_native_window_t* window, android_native_buffer_t* buffer);
-    static int query(android_native_window_t* window, int what, int* value);
-    static int perform(android_native_window_t* window, int operation, ...);
+    static int setSwapInterval(ANativeWindow* window, int interval);
+    static int dequeueBuffer(ANativeWindow* window, android_native_buffer_t** buffer);
+    static int lockBuffer(ANativeWindow* window, android_native_buffer_t* buffer);
+    static int queueBuffer(ANativeWindow* window, android_native_buffer_t* buffer);
+    static int query(ANativeWindow* window, int what, int* value);
+    static int perform(ANativeWindow* window, int operation, ...);
 
     int dequeueBuffer(android_native_buffer_t** buffer);
     int lockBuffer(android_native_buffer_t* buffer);
diff --git a/include/ui/FramebufferNativeWindow.h b/include/ui/FramebufferNativeWindow.h
index 8ea3ab9..0f4594f 100644
--- a/include/ui/FramebufferNativeWindow.h
+++ b/include/ui/FramebufferNativeWindow.h
@@ -43,7 +43,7 @@
 
 class FramebufferNativeWindow 
     : public EGLNativeBase<
-        android_native_window_t, 
+        ANativeWindow, 
         FramebufferNativeWindow, 
         LightRefBase<FramebufferNativeWindow> >
 {
@@ -59,12 +59,12 @@
 private:
     friend class LightRefBase<FramebufferNativeWindow>;    
     ~FramebufferNativeWindow(); // this class cannot be overloaded
-    static int setSwapInterval(android_native_window_t* window, int interval);
-    static int dequeueBuffer(android_native_window_t* window, android_native_buffer_t** buffer);
-    static int lockBuffer(android_native_window_t* window, android_native_buffer_t* buffer);
-    static int queueBuffer(android_native_window_t* window, android_native_buffer_t* buffer);
-    static int query(android_native_window_t* window, int what, int* value);
-    static int perform(android_native_window_t* window, int operation, ...);
+    static int setSwapInterval(ANativeWindow* window, int interval);
+    static int dequeueBuffer(ANativeWindow* window, android_native_buffer_t** buffer);
+    static int lockBuffer(ANativeWindow* window, android_native_buffer_t* buffer);
+    static int queueBuffer(ANativeWindow* window, android_native_buffer_t* buffer);
+    static int query(ANativeWindow* window, int what, int* value);
+    static int perform(ANativeWindow* window, int operation, ...);
     
     framebuffer_device_t* fbDev;
     alloc_device_t* grDev;
diff --git a/include/ui/Input.h b/include/ui/Input.h
index 57b292b..a2e0ba0 100644
--- a/include/ui/Input.h
+++ b/include/ui/Input.h
@@ -43,7 +43,7 @@
 /*
  * Declare a concrete type for the NDK's input event forward declaration.
  */
-struct input_event_t { };
+struct AInputEvent { };
 
 namespace android {
 
@@ -87,9 +87,6 @@
     // Indicates that the screen was dim when the event was received and the event
     // should brighten the device.
     POLICY_FLAG_BRIGHT_HERE = 0x20000000,
-
-    // Indicates that the dispatcher should call back into the policy before dispatching. */
-    POLICY_FLAG_INTERCEPT_DISPATCH = 0x40000000,
 };
 
 /*
@@ -136,7 +133,7 @@
 /*
  * Input events.
  */
-class InputEvent : public input_event_t {
+class InputEvent : public AInputEvent {
 public:
     virtual ~InputEvent() { }
 
@@ -145,7 +142,7 @@
     inline int32_t getDeviceId() const { return mDeviceId; }
 
     inline int32_t getNature() const { return mNature; }
-
+    
 protected:
     void initialize(int32_t deviceId, int32_t nature);
 
@@ -179,6 +176,14 @@
 
     inline nsecs_t getEventTime() const { return mEventTime; }
 
+    // Return true if this event may have a default action implementation.
+    static bool hasDefaultAction(int32_t keyCode);
+    bool hasDefaultAction() const;
+
+    // Return true if this event represents a system key.
+    static bool isSystemKey(int32_t keyCode);
+    bool isSystemKey() const;
+    
     void initialize(
             int32_t deviceId,
             int32_t nature,
diff --git a/include/ui/InputReader.h b/include/ui/InputReader.h
index 2093560..781da35 100644
--- a/include/ui/InputReader.h
+++ b/include/ui/InputReader.h
@@ -53,6 +53,8 @@
  */
 struct InputDevice {
     struct AbsoluteAxisInfo {
+        bool valid;        // set to true if axis parameters are known, false otherwise
+
         int32_t minValue;  // minimum value
         int32_t maxValue;  // maximum value
         int32_t range;     // range of values, equal to maxValue - minValue
@@ -272,9 +274,16 @@
         } jumpyTouchFilter;
 
         struct Precalculated {
+            int32_t xOrigin;
             float xScale;
+
+            int32_t yOrigin;
             float yScale;
+
+            int32_t pressureOrigin;
             float pressureScale;
+
+            int32_t sizeOrigin;
             float sizeScale;
         } precalculated;
 
@@ -362,10 +371,6 @@
         // The input dispatcher should add POLICY_FLAG_BRIGHT_HERE to the policy flags it
         // passes through the dispatch pipeline.
         ACTION_BRIGHT_HERE = 0x00000008,
-
-        // The input dispatcher should add POLICY_FLAG_INTERCEPT_DISPATCH to the policy flags
-        // it passed through the dispatch pipeline.
-        ACTION_INTERCEPT_DISPATCH = 0x00000010
     };
 
     /* Describes a virtual key. */
diff --git a/include/ui/InputTransport.h b/include/ui/InputTransport.h
index d6bded6..11714d5 100644
--- a/include/ui/InputTransport.h
+++ b/include/ui/InputTransport.h
@@ -33,6 +33,7 @@
 #include <semaphore.h>
 #include <ui/Input.h>
 #include <utils/Errors.h>
+#include <utils/PollLoop.h>
 #include <utils/Timers.h>
 #include <utils/RefBase.h>
 #include <utils/String8.h>
@@ -333,21 +334,27 @@
 /*
  * NDK input queue API.
  */
-struct input_queue_t {
+struct AInputQueue {
 public:
     /* Creates a consumer associated with an input channel. */
-    explicit input_queue_t(const android::sp<android::InputChannel>& channel);
+    explicit AInputQueue(const android::sp<android::InputChannel>& channel);
 
     /* Destroys the consumer and releases its input channel. */
-    ~input_queue_t();
+    virtual ~AInputQueue();
 
     inline android::InputConsumer& getConsumer() { return mConsumer; }
     
     android::status_t consume(android::InputEvent** event);
     
+    void setPollLoop(const android::sp<android::PollLoop>& pollLoop) { mPollLoop = pollLoop; }
+    const android::sp<android::PollLoop> getPollLoop() const { return mPollLoop; }
+    
+    virtual void doDefaultKey(android::KeyEvent* keyEvent) = 0;
+    
 private:
     android::InputConsumer mConsumer;
     android::PreallocatedInputEventFactory mInputEventFactory;
+    android::sp<android::PollLoop> mPollLoop;
 };
 
 #endif // _UI_INPUT_TRANSPORT_H
diff --git a/include/ui/egl/android_natives.h b/include/ui/egl/android_natives.h
index 171f3df..ca89b06 100644
--- a/include/ui/egl/android_natives.h
+++ b/include/ui/egl/android_natives.h
@@ -22,6 +22,8 @@
 
 #include <hardware/gralloc.h>
 
+#include <android/native_window.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -90,19 +92,19 @@
     NATIVE_WINDOW_API_EGL = 1
 };
 
-typedef struct android_native_window_t 
+struct ANativeWindow 
 {
 #ifdef __cplusplus
-    android_native_window_t()
+    ANativeWindow()
         : flags(0), minSwapInterval(0), maxSwapInterval(0), xdpi(0), ydpi(0)
     {
         common.magic = ANDROID_NATIVE_WINDOW_MAGIC;
-        common.version = sizeof(android_native_window_t);
+        common.version = sizeof(ANativeWindow);
         memset(common.reserved, 0, sizeof(common.reserved));
     }
 
-    // Implement the methods that sp<android_native_window_t> expects so that it
-    // can be used to automatically refcount android_native_window_t's.
+    // Implement the methods that sp<ANativeWindow> expects so that it
+    // can be used to automatically refcount ANativeWindow's.
     void incStrong(const void* id) const {
         common.incRef(const_cast<android_native_base_t*>(&common));
     }
@@ -135,7 +137,7 @@
      * 
      * Returns 0 on success or -errno on error.
      */
-    int     (*setSwapInterval)(struct android_native_window_t* window,
+    int     (*setSwapInterval)(struct ANativeWindow* window,
                 int interval);
     
     /*
@@ -145,7 +147,7 @@
      * 
      * Returns 0 on success or -errno on error.
      */
-    int     (*dequeueBuffer)(struct android_native_window_t* window,
+    int     (*dequeueBuffer)(struct ANativeWindow* window,
                 struct android_native_buffer_t** buffer);
 
     /*
@@ -155,7 +157,7 @@
      * 
      * Returns 0 on success or -errno on error.
      */
-    int     (*lockBuffer)(struct android_native_window_t* window,
+    int     (*lockBuffer)(struct ANativeWindow* window,
                 struct android_native_buffer_t* buffer);
    /*
     * hook called by EGL when modifications to the render buffer are done. 
@@ -165,7 +167,7 @@
     * 
     * Returns 0 on success or -errno on error.
     */
-    int     (*queueBuffer)(struct android_native_window_t* window,
+    int     (*queueBuffer)(struct ANativeWindow* window,
                 struct android_native_buffer_t* buffer);
 
     /*
@@ -173,13 +175,13 @@
      * 
      * Returns 0 on success or -errno on error.
      */
-    int     (*query)(struct android_native_window_t* window,
+    int     (*query)(struct ANativeWindow* window,
                 int what, int* value);
     
     /*
      * hook used to perform various operations on the surface.
      * (*perform)() is a generic mechanism to add functionality to
-     * android_native_window_t while keeping backward binary compatibility.
+     * ANativeWindow while keeping backward binary compatibility.
      * 
      * This hook should not be called directly, instead use the helper functions
      * defined below.
@@ -197,12 +199,14 @@
      *  
      */
     
-    int     (*perform)(struct android_native_window_t* window,
+    int     (*perform)(struct ANativeWindow* window,
                 int operation, ... );
     
     void* reserved_proc[3];
-} android_native_window_t;
+};
 
+// Backwards compatibility...  please switch to ANativeWindow.
+typedef struct ANativeWindow android_native_window_t;
 
 /*
  *  native_window_set_usage(..., usage)
@@ -216,7 +220,7 @@
  */
 
 static inline int native_window_set_usage(
-        android_native_window_t* window, int usage)
+        ANativeWindow* window, int usage)
 {
     return window->perform(window, NATIVE_WINDOW_SET_USAGE, usage);
 }
@@ -228,7 +232,7 @@
  * can happen if it's connected to some other API.
  */
 static inline int native_window_connect(
-        android_native_window_t* window, int api)
+        ANativeWindow* window, int api)
 {
     return window->perform(window, NATIVE_WINDOW_CONNECT, api);
 }
@@ -240,7 +244,7 @@
  * first place.
  */
 static inline int native_window_disconnect(
-        android_native_window_t* window, int api)
+        ANativeWindow* window, int api)
 {
     return window->perform(window, NATIVE_WINDOW_DISCONNECT, api);
 }
@@ -258,7 +262,7 @@
  * out of the buffer's bound or if the window is invalid.
  */
 static inline int native_window_set_crop(
-        android_native_window_t* window,
+        ANativeWindow* window,
         android_native_rect_t const * crop)
 {
     return window->perform(window, NATIVE_WINDOW_SET_CROP, crop);
@@ -269,7 +273,7 @@
  * Sets the number of buffers associated with this native window.
  */
 static inline int native_window_set_buffer_count(
-        android_native_window_t* window,
+        ANativeWindow* window,
         size_t bufferCount)
 {
     return window->perform(window, NATIVE_WINDOW_SET_BUFFER_COUNT, bufferCount);
@@ -287,7 +291,7 @@
  *
  */
 static inline int native_window_set_buffers_geometry(
-        android_native_window_t* window,
+        ANativeWindow* window,
         int w, int h, int format)
 {
     return window->perform(window, NATIVE_WINDOW_SET_BUFFERS_GEOMETRY,
diff --git a/include/utils/PollLoop.h b/include/utils/PollLoop.h
index a95fb17..b3651ca 100644
--- a/include/utils/PollLoop.h
+++ b/include/utils/PollLoop.h
@@ -22,12 +22,22 @@
 
 #include <sys/poll.h>
 
+#include <android/looper.h>
+
+struct ALooper : public android::RefBase {
+protected:
+    virtual ~ALooper() { }
+
+public:
+    ALooper() { }
+};
+
 namespace android {
 
 /**
  * A basic file descriptor polling loop based on poll() with callbacks.
  */
-class PollLoop : public RefBase {
+class PollLoop : public ALooper {
 protected:
     virtual ~PollLoop();
 
@@ -83,6 +93,11 @@
     void setCallback(int fd, int events, Callback callback, void* data = NULL);
 
     /**
+     * Like setCallback(), but for the NDK callback function.
+     */
+    void setLooperCallback(int fd, int events, ALooper_callbackFunc* callback, void* data);
+    
+    /**
      * Removes the callback for a file descriptor, if one exists.
      *
      * When this method returns, it is safe to close the file descriptor since the poll loop
@@ -100,9 +115,22 @@
      */
     bool removeCallback(int fd);
 
+    /**
+     * Set the given PollLoop to be associated with the
+     * calling thread.  There must be a 1:1 relationship between
+     * PollLoop and thread.
+     */
+    static void setForThread(const sp<PollLoop>& pollLoop);
+    
+    /**
+     * Return the PollLoop associated with the calling thread.
+     */
+    static sp<PollLoop> getForThread();
+    
 private:
     struct RequestedCallback {
         Callback callback;
+        ALooper_callbackFunc* looperCallback;
         void* data;
     };
 
@@ -110,6 +138,7 @@
         int fd;
         int events;
         Callback callback;
+        ALooper_callbackFunc* looperCallback;
         void* data;
     };
 
@@ -130,8 +159,11 @@
     void openWakePipe();
     void closeWakePipe();
 
+    void setCallbackCommon(int fd, int events, Callback callback,
+            ALooper_callbackFunc* looperCallback, void* data);
     ssize_t getRequestIndexLocked(int fd);
     void wakeAndLock();
+    static void threadDestructor(void *st);
 };
 
 } // namespace android
diff --git a/libs/surfaceflinger/Android.mk b/libs/surfaceflinger/Android.mk
index 0879a66..a14bfb5 100644
--- a/libs/surfaceflinger/Android.mk
+++ b/libs/surfaceflinger/Android.mk
@@ -6,6 +6,7 @@
     DisplayHardware/DisplayHardware.cpp \
     DisplayHardware/DisplayHardwareBase.cpp \
     BlurFilter.cpp.arm \
+    GLExtensions.cpp \
     Layer.cpp \
     LayerBase.cpp \
     LayerBuffer.cpp \
@@ -19,8 +20,8 @@
 LOCAL_CFLAGS:= -DLOG_TAG=\"SurfaceFlinger\"
 LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
 
-ifeq ($(TARGET_BOARD_PLATFORM), msm7k)
-	LOCAL_CFLAGS += -DDIM_WITH_TEXTURE
+ifeq ($(TARGET_BOARD_PLATFORM), omap3)
+	LOCAL_CFLAGS += -DNO_RGBX_8888
 endif
 
 # need "-lrt" on Linux simulator to pick up clock_gettime
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
index 51de1da..2eac0a8 100644
--- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
+++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
@@ -40,6 +40,8 @@
 #include <hardware/overlay.h>
 #include <hardware/gralloc.h>
 
+#include "GLExtensions.h"
+
 using namespace android;
 
 
@@ -73,7 +75,8 @@
 DisplayHardware::DisplayHardware(
         const sp<SurfaceFlinger>& flinger,
         uint32_t dpy)
-    : DisplayHardwareBase(flinger, dpy), mFlags(0)
+    : DisplayHardwareBase(flinger, dpy),
+      mFlags(0)
 {
     init(dpy);
 }
@@ -97,6 +100,9 @@
 {
     mNativeWindow = new FramebufferNativeWindow();
     framebuffer_device_t const * fbDev = mNativeWindow->getDevice();
+    mDpiX = mNativeWindow->xdpi;
+    mDpiY = mNativeWindow->ydpi;
+    mRefreshRate = fbDev->fps;
 
     mOverlayEngine = NULL;
     hw_module_t const* module;
@@ -104,6 +110,11 @@
         overlay_control_open(module, &mOverlayEngine);
     }
 
+    EGLint w, h, dummy;
+    EGLint numConfigs=0;
+    EGLSurface surface;
+    EGLContext context;
+
     // initialize EGL
     EGLint attribs[] = {
             EGL_SURFACE_TYPE,   EGL_WINDOW_BIT,
@@ -121,11 +132,6 @@
         }
     }
 
-    EGLint w, h, dummy;
-    EGLint numConfigs=0;
-    EGLSurface surface;
-    EGLContext context;
-
     // TODO: all the extensions below should be queried through
     // eglGetProcAddress().
 
@@ -144,22 +150,6 @@
     eglGetConfigAttrib(display, config, EGL_BLUE_SIZE,  &b);
     eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &a);
 
-    /*
-     * Gather EGL extensions
-     */
-
-    const char* const egl_extensions = eglQueryString(
-            display, EGL_EXTENSIONS);
-    
-    LOGI("EGL informations:");
-    LOGI("# of configs : %d", numConfigs);
-    LOGI("vendor    : %s", eglQueryString(display, EGL_VENDOR));
-    LOGI("version   : %s", eglQueryString(display, EGL_VERSION));
-    LOGI("extensions: %s", egl_extensions);
-    LOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS)?:"Not Supported");
-    LOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, config);
-    
-
     if (mNativeWindow->isUpdateOnDemand()) {
         mFlags |= PARTIAL_UPDATES;
     }
@@ -174,6 +164,8 @@
      */
 
     surface = eglCreateWindowSurface(display, config, mNativeWindow.get(), NULL);
+    eglQuerySurface(display, surface, EGL_WIDTH,  &mWidth);
+    eglQuerySurface(display, surface, EGL_HEIGHT, &mHeight);
 
     if (mFlags & PARTIAL_UPDATES) {
         // if we have partial updates, we definitely don't need to
@@ -187,31 +179,6 @@
             mFlags |= BUFFER_PRESERVED;
         }
     }
-
-    eglQuerySurface(display, surface, EGL_WIDTH,  &mWidth);
-    eglQuerySurface(display, surface, EGL_HEIGHT, &mHeight);
-
-#ifdef EGL_ANDROID_swap_rectangle    
-    if (strstr(egl_extensions, "EGL_ANDROID_swap_rectangle")) {
-        if (eglSetSwapRectangleANDROID(display, surface,
-                0, 0, mWidth, mHeight) == EGL_TRUE) {
-            // This could fail if this extension is not supported by this
-            // specific surface (of config)
-            mFlags |= SWAP_RECTANGLE;
-        }
-    }
-    // when we have the choice between PARTIAL_UPDATES and SWAP_RECTANGLE
-    // choose PARTIAL_UPDATES, which should be more efficient
-    if (mFlags & PARTIAL_UPDATES)
-        mFlags &= ~SWAP_RECTANGLE;
-#endif
-    
-
-    LOGI("flags     : %08x", mFlags);
-    
-    mDpiX = mNativeWindow->xdpi;
-    mDpiY = mNativeWindow->ydpi;
-    mRefreshRate = fbDev->fps; 
     
     /* Read density from build-specific ro.sf.lcd_density property
      * except if it is overridden by qemu.sf.lcd_density.
@@ -234,49 +201,67 @@
     
     context = eglCreateContext(display, config, NULL, NULL);
     
-    /*
-     * Gather OpenGL ES extensions
-     */
-
-    eglMakeCurrent(display, surface, surface, context);
-    const char* const  gl_extensions = (const char*)glGetString(GL_EXTENSIONS);
-    const char* const  gl_renderer = (const char*)glGetString(GL_RENDERER);
-    LOGI("OpenGL informations:");
-    LOGI("vendor    : %s", glGetString(GL_VENDOR));
-    LOGI("renderer  : %s", gl_renderer);
-    LOGI("version   : %s", glGetString(GL_VERSION));
-    LOGI("extensions: %s", gl_extensions);
-
-    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
-    glGetIntegerv(GL_MAX_VIEWPORT_DIMS, &mMaxViewportDims);
-    LOGI("GL_MAX_TEXTURE_SIZE = %d", mMaxTextureSize);
-    LOGI("GL_MAX_VIEWPORT_DIMS = %d", mMaxViewportDims);
-
-
-    if (strstr(gl_extensions, "GL_ARB_texture_non_power_of_two")) {
-        mFlags |= NPOT_EXTENSION;
-    }
-#ifdef EGL_ANDROID_image_native_buffer
-    if (strstr( gl_extensions, "GL_OES_EGL_image") &&
-        (strstr(egl_extensions, "EGL_KHR_image_base") || 
-                strstr(egl_extensions, "EGL_KHR_image")) &&
-        strstr(egl_extensions, "EGL_ANDROID_image_native_buffer")) {
-        mFlags |= DIRECT_TEXTURE;
-    }
-#else
-#warning "EGL_ANDROID_image_native_buffer not supported"
-#endif
-
-
-    // Unbind the context from this thread
-    eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
-
     mDisplay = display;
     mConfig  = config;
     mSurface = surface;
     mContext = context;
     mFormat  = fbDev->format;
     mPageFlipCount = 0;
+
+    /*
+     * Gather OpenGL ES extensions
+     */
+
+    eglMakeCurrent(display, surface, surface, context);
+
+    GLExtensions& extensions(GLExtensions::getInstance());
+    extensions.initWithGLStrings(
+            glGetString(GL_VENDOR),
+            glGetString(GL_RENDERER),
+            glGetString(GL_VERSION),
+            glGetString(GL_EXTENSIONS),
+            eglQueryString(display, EGL_VENDOR),
+            eglQueryString(display, EGL_VERSION),
+            eglQueryString(display, EGL_EXTENSIONS));
+
+    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
+    glGetIntegerv(GL_MAX_VIEWPORT_DIMS, &mMaxViewportDims);
+
+
+#ifdef EGL_ANDROID_swap_rectangle
+    if (extensions.hasExtension("EGL_ANDROID_swap_rectangle")) {
+        if (eglSetSwapRectangleANDROID(display, surface,
+                0, 0, mWidth, mHeight) == EGL_TRUE) {
+            // This could fail if this extension is not supported by this
+            // specific surface (of config)
+            mFlags |= SWAP_RECTANGLE;
+        }
+    }
+    // when we have the choice between PARTIAL_UPDATES and SWAP_RECTANGLE
+    // choose PARTIAL_UPDATES, which should be more efficient
+    if (mFlags & PARTIAL_UPDATES)
+        mFlags &= ~SWAP_RECTANGLE;
+#endif
+
+    LOGI("EGL informations:");
+    LOGI("# of configs : %d", numConfigs);
+    LOGI("vendor    : %s", extensions.getEglVendor());
+    LOGI("version   : %s", extensions.getEglVersion());
+    LOGI("extensions: %s", extensions.getEglExtension());
+    LOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS)?:"Not Supported");
+    LOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, config);
+
+    LOGI("OpenGL informations:");
+    LOGI("vendor    : %s", extensions.getVendor());
+    LOGI("renderer  : %s", extensions.getRenderer());
+    LOGI("version   : %s", extensions.getVersion());
+    LOGI("extensions: %s", extensions.getExtension());
+    LOGI("GL_MAX_TEXTURE_SIZE = %d", mMaxTextureSize);
+    LOGI("GL_MAX_VIEWPORT_DIMS = %d", mMaxViewportDims);
+    LOGI("flags = %08x", mFlags);
+
+    // Unbind the context from this thread
+    eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
 }
 
 /*
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.h b/libs/surfaceflinger/DisplayHardware/DisplayHardware.h
index ebd7c42..66bf521 100644
--- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.h
+++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.h
@@ -29,6 +29,8 @@
 
 #include <pixelflinger/pixelflinger.h>
 
+#include "GLExtensions.h"
+
 #include "DisplayHardware/DisplayHardwareBase.h"
 
 struct overlay_control_device_t;
@@ -43,13 +45,11 @@
 {
 public:
     enum {
-        DIRECT_TEXTURE          = 0x00000002,
-        COPY_BITS_EXTENSION     = 0x00000008,
-        NPOT_EXTENSION          = 0x00000100,
-        BUFFER_PRESERVED        = 0x00010000,
-        PARTIAL_UPDATES         = 0x00020000,   // video driver feature
-        SLOW_CONFIG             = 0x00040000,   // software
-        SWAP_RECTANGLE          = 0x00080000,
+        COPY_BITS_EXTENSION         = 0x00000008,
+        BUFFER_PRESERVED            = 0x00010000,
+        PARTIAL_UPDATES             = 0x00020000,   // video driver feature
+        SLOW_CONFIG                 = 0x00040000,   // software
+        SWAP_RECTANGLE              = 0x00080000,
     };
 
     DisplayHardware(
diff --git a/libs/surfaceflinger/GLExtensions.cpp b/libs/surfaceflinger/GLExtensions.cpp
new file mode 100644
index 0000000..7f4f9fc
--- /dev/null
+++ b/libs/surfaceflinger/GLExtensions.cpp
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+
+#include "GLExtensions.h"
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+ANDROID_SINGLETON_STATIC_INSTANCE( GLExtensions )
+
+GLExtensions::GLExtensions()
+    : mHaveTextureExternal(false),
+      mHaveNpot(false),
+      mHaveDirectTexture(false)
+{
+}
+
+void GLExtensions::initWithGLStrings(
+        GLubyte const* vendor,
+        GLubyte const* renderer,
+        GLubyte const* version,
+        GLubyte const* extensions,
+        char const* egl_vendor,
+        char const* egl_version,
+        char const* egl_extensions)
+{
+    mVendor     = (char const*)vendor;
+    mRenderer   = (char const*)renderer;
+    mVersion    = (char const*)version;
+    mExtensions = (char const*)extensions;
+    mEglVendor     = egl_vendor;
+    mEglVersion    = egl_version;
+    mEglExtensions = egl_extensions;
+
+    char const* curr = (char const*)extensions;
+    char const* head = curr;
+    do {
+        head = strchr(curr, ' ');
+        String8 s(curr, head ? head-curr : strlen(curr));
+        if (s.length()) {
+            mExtensionList.add(s);
+        }
+        curr = head+1;
+    } while (head);
+
+    curr = egl_extensions;
+    head = curr;
+    do {
+        head = strchr(curr, ' ');
+        String8 s(curr, head ? head-curr : strlen(curr));
+        if (s.length()) {
+            mExtensionList.add(s);
+        }
+        curr = head+1;
+    } while (head);
+
+#ifdef EGL_ANDROID_image_native_buffer
+    if (hasExtension("GL_OES_EGL_image") &&
+        (hasExtension("EGL_KHR_image_base") || hasExtension("EGL_KHR_image")) &&
+        hasExtension("EGL_ANDROID_image_native_buffer"))
+    {
+        mHaveDirectTexture = true;
+    }
+#else
+#warning "EGL_ANDROID_image_native_buffer not supported"
+#endif
+
+    if (hasExtension("GL_ARB_texture_non_power_of_two")) {
+        mHaveNpot = true;
+    }
+
+    if (hasExtension("GL_OES_texture_external")) {
+        mHaveTextureExternal = true;
+    } else if (strstr(mRenderer.string(), "Adreno")) {
+        // hack for Adreno 200
+        mHaveTextureExternal = true;
+    }
+}
+
+bool GLExtensions::hasExtension(char const* extension) const
+{
+    const String8 s(extension);
+    return mExtensionList.indexOf(s) >= 0;
+}
+
+char const* GLExtensions::getVendor() const {
+    return mVendor.string();
+}
+
+char const* GLExtensions::getRenderer() const {
+    return mRenderer.string();
+}
+
+char const* GLExtensions::getVersion() const {
+    return mVersion.string();
+}
+
+char const* GLExtensions::getExtension() const {
+    return mExtensions.string();
+}
+
+char const* GLExtensions::getEglVendor() const {
+    return mEglVendor.string();
+}
+
+char const* GLExtensions::getEglVersion() const {
+    return mEglVersion.string();
+}
+
+char const* GLExtensions::getEglExtension() const {
+    return mEglExtensions.string();
+}
+
+
+// ---------------------------------------------------------------------------
+}; // namespace android
diff --git a/libs/surfaceflinger/GLExtensions.h b/libs/surfaceflinger/GLExtensions.h
new file mode 100644
index 0000000..bbb284e
--- /dev/null
+++ b/libs/surfaceflinger/GLExtensions.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2010 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_SF_GLEXTENSION_H
+#define ANDROID_SF_GLEXTENSION_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/String8.h>
+#include <utils/SortedVector.h>
+#include <utils/Singleton.h>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+class GLExtensions : public Singleton<GLExtensions>
+{
+    friend class Singleton<GLExtensions>;
+
+    bool mHaveTextureExternal   : 1;
+    bool mHaveNpot              : 1;
+    bool mHaveDirectTexture     : 1;
+
+    String8 mVendor;
+    String8 mRenderer;
+    String8 mVersion;
+    String8 mExtensions;
+    String8 mEglVendor;
+    String8 mEglVersion;
+    String8 mEglExtensions;
+    SortedVector<String8> mExtensionList;
+
+    GLExtensions(const GLExtensions&);
+    GLExtensions& operator = (const GLExtensions&);
+
+protected:
+    GLExtensions();
+
+public:
+    inline bool haveTextureExternal() const {
+        return mHaveTextureExternal;
+    }
+    inline bool haveNpot() const {
+        return mHaveNpot;
+    }
+    inline bool haveDirectTexture() const {
+        return mHaveDirectTexture;
+    }
+
+    void initWithGLStrings(
+            GLubyte const* vendor,
+            GLubyte const* renderer,
+            GLubyte const* version,
+            GLubyte const* extensions,
+            char const* egl_vendor,
+            char const* egl_version,
+            char const* egl_extensions);
+
+    char const* getVendor() const;
+    char const* getRenderer() const;
+    char const* getVersion() const;
+    char const* getExtension() const;
+
+    char const* getEglVendor() const;
+    char const* getEglVersion() const;
+    char const* getEglExtension() const;
+
+    bool hasExtension(char const* extension) const;
+};
+
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_SF_GLEXTENSION_H
diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp
index e606f71..758da4e 100644
--- a/libs/surfaceflinger/Layer.cpp
+++ b/libs/surfaceflinger/Layer.cpp
@@ -31,6 +31,7 @@
 #include <surfaceflinger/Surface.h>
 
 #include "clz.h"
+#include "GLExtensions.h"
 #include "Layer.h"
 #include "SurfaceFlinger.h"
 #include "DisplayHardware/DisplayHardware.h"
@@ -50,10 +51,11 @@
 Layer::Layer(SurfaceFlinger* flinger,
         DisplayID display, const sp<Client>& client)
     :   LayerBaseClient(flinger, display, client),
+        mGLExtensions(GLExtensions::getInstance()),
         mNeedsBlending(true),
         mNeedsDithering(false),
         mSecure(false),
-        mTextureManager(mFlags),
+        mTextureManager(),
         mBufferManager(mTextureManager),
         mWidth(0), mHeight(0), mFixedSize(false)
 {
@@ -185,17 +187,13 @@
         return;
     }
 
-#ifdef EGL_ANDROID_image_native_buffer
-    if (mFlags & DisplayHardware::DIRECT_TEXTURE) {
+    if (mGLExtensions.haveDirectTexture()) {
         EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
         if (mBufferManager.initEglImage(dpy, buffer) != NO_ERROR) {
             // not sure what we can do here...
-            mFlags &= ~DisplayHardware::DIRECT_TEXTURE;
             goto slowpath;
         }
-    } else
-#endif
-    {
+    } else {
 slowpath:
         GGLSurface t;
         status_t res = buffer->lock(&t, GRALLOC_USAGE_SW_READ_OFTEN);
@@ -786,19 +784,24 @@
     status_t err = NO_INIT;
     ssize_t index = mActiveBuffer;
     if (index >= 0) {
-        Image& texture(mBufferData[index].texture);
-        err = mTextureManager.initEglImage(&texture, dpy, buffer);
-        // if EGLImage fails, we switch to regular texture mode, and we
-        // free all resources associated with using EGLImages.
-        if (err == NO_ERROR) {
-            mFailover = false;
-            destroyTexture(&mFailoverTexture, dpy);
-        } else {
-            mFailover = true;
-            const size_t num = mNumBuffers;
-            for (size_t i=0 ; i<num ; i++) {
-                destroyTexture(&mBufferData[i].texture, dpy);
+        if (!mFailover) {
+            Image& texture(mBufferData[index].texture);
+            err = mTextureManager.initEglImage(&texture, dpy, buffer);
+            // if EGLImage fails, we switch to regular texture mode, and we
+            // free all resources associated with using EGLImages.
+            if (err == NO_ERROR) {
+                mFailover = false;
+                destroyTexture(&mFailoverTexture, dpy);
+            } else {
+                mFailover = true;
+                const size_t num = mNumBuffers;
+                for (size_t i=0 ; i<num ; i++) {
+                    destroyTexture(&mBufferData[i].texture, dpy);
+                }
             }
+        } else {
+            // we failed once, don't try again
+            err = BAD_VALUE;
         }
     }
     return err;
diff --git a/libs/surfaceflinger/Layer.h b/libs/surfaceflinger/Layer.h
index dcb27a0..e1d283b 100644
--- a/libs/surfaceflinger/Layer.h
+++ b/libs/surfaceflinger/Layer.h
@@ -37,9 +37,10 @@
 
 // ---------------------------------------------------------------------------
 
-class Client;
-class UserClient;
 class FreezeLock;
+class Client;
+class GLExtensions;
+class UserClient;
 
 // ---------------------------------------------------------------------------
 
@@ -206,6 +207,7 @@
     // constants
     sp<Surface> mSurface;
     PixelFormat mFormat;
+    const GLExtensions& mGLExtensions;
     bool mNeedsBlending;
     bool mNeedsDithering;
 
diff --git a/libs/surfaceflinger/LayerBlur.cpp b/libs/surfaceflinger/LayerBlur.cpp
index c1c440b..64a43c7 100644
--- a/libs/surfaceflinger/LayerBlur.cpp
+++ b/libs/surfaceflinger/LayerBlur.cpp
@@ -147,7 +147,9 @@
     Region::const_iterator const end = clip.end();
     if (it != end) {
 #if defined(GL_OES_texture_external)
-        glDisable(GL_TEXTURE_EXTERNAL_OES);
+        if (GLExtensions::getInstance().haveTextureExternal()) {
+            glDisable(GL_TEXTURE_EXTERNAL_OES);
+        }
 #endif
         glEnable(GL_TEXTURE_2D);
         glBindTexture(GL_TEXTURE_2D, mTextureName);
@@ -181,7 +183,7 @@
             bl.data = (GGLubyte*)pixels;            
             blurFilter(&bl, 8, 2);
 
-            if (mFlags & (DisplayHardware::NPOT_EXTENSION)) {
+            if (GLExtensions::getInstance().haveNpot()) {
                 glTexImage2D(GL_TEXTURE_2D, 0, mReadFormat, w, h, 0,
                         mReadFormat, mReadType, pixels);
                 mWidthScale  = 1.0f / w;
diff --git a/libs/surfaceflinger/LayerBuffer.cpp b/libs/surfaceflinger/LayerBuffer.cpp
index 732a4ec..5f83636 100644
--- a/libs/surfaceflinger/LayerBuffer.cpp
+++ b/libs/surfaceflinger/LayerBuffer.cpp
@@ -315,8 +315,7 @@
 
 LayerBuffer::BufferSource::BufferSource(LayerBuffer& layer,
         const ISurface::BufferHeap& buffers)
-    : Source(layer), mStatus(NO_ERROR), mBufferSize(0),
-      mTextureManager(layer.mFlags)
+    : Source(layer), mStatus(NO_ERROR), mBufferSize(0)
 {
     if (buffers.heap == NULL) {
         // this is allowed, but in this case, it is illegal to receive
@@ -374,11 +373,11 @@
 
     if (mTexture.name != -1U) {
         // GL textures can only be destroyed from the GL thread
-        mLayer.mFlinger->mEventQueue.postMessage(
-                new MessageDestroyTexture(mLayer.mFlinger.get(), mTexture.name) );
+        getFlinger()->mEventQueue.postMessage(
+                new MessageDestroyTexture(getFlinger(), mTexture.name) );
     }
     if (mTexture.image != EGL_NO_IMAGE_KHR) {
-        EGLDisplay dpy(mLayer.mFlinger->graphicPlane(0).getEGLDisplay());
+        EGLDisplay dpy(getFlinger()->graphicPlane(0).getEGLDisplay());
         eglDestroyImageKHR(dpy, mTexture.image);
     }
 }
@@ -444,7 +443,7 @@
     const Rect transformedBounds(mLayer.getTransformedBounds());
 
 #if defined(EGL_ANDROID_image_native_buffer)
-    if (mLayer.mFlags & DisplayHardware::DIRECT_TEXTURE) {
+    if (GLExtensions::getInstance().haveDirectTexture()) {
         err = INVALID_OPERATION;
         if (ourBuffer->supportsCopybit()) {
             copybit_device_t* copybit = mLayer.mBlitEngine;
@@ -549,7 +548,7 @@
         dst.crop.r = w;
         dst.crop.b = h;
 
-        EGLDisplay dpy(mLayer.mFlinger->graphicPlane(0).getEGLDisplay());
+        EGLDisplay dpy(getFlinger()->graphicPlane(0).getEGLDisplay());
         err = mTextureManager.initEglImage(&mTexture, dpy, buffer);
     }
 
@@ -559,7 +558,7 @@
 void LayerBuffer::BufferSource::clearTempBufferImage() const
 {
     // delete the image
-    EGLDisplay dpy(mLayer.mFlinger->graphicPlane(0).getEGLDisplay());
+    EGLDisplay dpy(getFlinger()->graphicPlane(0).getEGLDisplay());
     eglDestroyImageKHR(dpy, mTexture.image);
 
     // and the associated texture (recreate a name)
@@ -576,7 +575,7 @@
     : Source(layer), mVisibilityChanged(false),
     mOverlay(0), mOverlayHandle(0), mOverlayDevice(0), mOrientation(orientation)
 {
-    overlay_control_device_t* overlay_dev = mLayer.mFlinger->getOverlayEngine();
+    overlay_control_device_t* overlay_dev = getFlinger()->getOverlayEngine();
     if (overlay_dev == NULL) {
         // overlays not supported
         return;
@@ -607,7 +606,7 @@
 
     *overlayRef = new OverlayRef(mOverlayHandle, channel,
             mWidth, mHeight, mFormat, mWidthStride, mHeightStride);
-    mLayer.mFlinger->signalEvent();
+    getFlinger()->signalEvent();
 }
 
 LayerBuffer::OverlaySource::~OverlaySource()
diff --git a/libs/surfaceflinger/LayerBuffer.h b/libs/surfaceflinger/LayerBuffer.h
index 413b8a4..1c0bf83 100644
--- a/libs/surfaceflinger/LayerBuffer.h
+++ b/libs/surfaceflinger/LayerBuffer.h
@@ -47,6 +47,7 @@
         virtual void postBuffer(ssize_t offset);
         virtual void unregisterBuffers();
         virtual void destroy() { }
+        SurfaceFlinger* getFlinger() const { return mLayer.mFlinger.get(); }
     protected:
         LayerBuffer& mLayer;
     };
diff --git a/libs/surfaceflinger/LayerDim.cpp b/libs/surfaceflinger/LayerDim.cpp
index 906a583..a1f339e 100644
--- a/libs/surfaceflinger/LayerDim.cpp
+++ b/libs/surfaceflinger/LayerDim.cpp
@@ -51,54 +51,6 @@
     sWidth = w;
     sHeight = h;
     sUseTexture = false;
-    
-#if defined(DIM_WITH_TEXTURE) && defined(EGL_ANDROID_image_native_buffer)
-
-#warning "using a texture to implement LayerDim"
-    
-    /* On some h/w like msm7K, it is faster to use a texture because the
-     * software renderer will defer to copybit, for this to work we need to
-     * use an EGLImage texture so copybit can actually make use of it.
-     * This burns a full-screen worth of graphic memory.
-     */
-
-    const DisplayHardware& hw(flinger->graphicPlane(0).displayHardware());
-    uint32_t flags = hw.getFlags();
-
-    if (LIKELY(flags & DisplayHardware::DIRECT_TEXTURE)) {
-        sp<GraphicBuffer> buffer = new GraphicBuffer(w, h, PIXEL_FORMAT_RGB_565,
-                 GraphicBuffer::USAGE_SW_WRITE_OFTEN |
-                 GraphicBuffer::USAGE_HW_TEXTURE);
-        
-        android_native_buffer_t* clientBuf = buffer->getNativeBuffer();
-
-        glGenTextures(1, &sTexId);
-        glBindTexture(GL_TEXTURE_2D, sTexId);
-
-        EGLDisplay dpy = eglGetCurrentDisplay();
-        sImage = eglCreateImageKHR(dpy, EGL_NO_CONTEXT, 
-                EGL_NATIVE_BUFFER_ANDROID, (EGLClientBuffer)clientBuf, 0);
-        if (sImage == EGL_NO_IMAGE_KHR) {
-            LOGE("eglCreateImageKHR() failed. err=0x%4x", eglGetError());
-            return;
-        }
-
-        glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)sImage);
-        GLint error = glGetError();
-        if (error != GL_NO_ERROR) {
-            eglDestroyImageKHR(dpy, sImage);
-            LOGE("glEGLImageTargetTexture2DOES() failed. err=0x%4x", error);
-            return;
-        }
-
-        // initialize the texture with zeros
-        GGLSurface t;
-        buffer->lock(&t, GRALLOC_USAGE_SW_WRITE_OFTEN);
-        memset(t.data, 0, t.stride * t.height * 2);
-        buffer->unlock();
-        sUseTexture = true;
-    }
-#endif
 }
 
 LayerDim::~LayerDim()
@@ -112,36 +64,19 @@
     Region::const_iterator const end = clip.end();
     if (s.alpha>0 && (it != end)) {
         const DisplayHardware& hw(graphicPlane(0).displayHardware());
-        const GGLfixed alpha = (s.alpha << 16)/255;
+        const GLfloat alpha = s.alpha/255.0f;
         const uint32_t fbHeight = hw.getHeight();
         glDisable(GL_DITHER);
         glEnable(GL_BLEND);
         glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
-        glColor4x(0, 0, 0, alpha);
-        
+        glColor4f(0, 0, 0, alpha);
+
 #if defined(GL_OES_texture_external)
-        glDisable(GL_TEXTURE_EXTERNAL_OES);
-#endif
-#if defined(DIM_WITH_TEXTURE) && defined(EGL_ANDROID_image_native_buffer)
-        if (sUseTexture) {
-            glBindTexture(GL_TEXTURE_2D, sTexId);
-            glEnable(GL_TEXTURE_2D);
-            glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
-            const GLshort texCoords[4][2] = {
-                    { 0,  0 },
-                    { 0,  1 },
-                    { 1,  1 },
-                    { 1,  0 }
-            };
-            glMatrixMode(GL_TEXTURE);
-            glLoadIdentity();
-            glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-            glTexCoordPointer(2, GL_SHORT, 0, texCoords);
-        } else
-#endif
-        {
-            glDisable(GL_TEXTURE_2D);
+        if (GLExtensions::getInstance().haveTextureExternal()) {
+            glDisable(GL_TEXTURE_EXTERNAL_OES);
         }
+#endif
+        glDisable(GL_TEXTURE_2D);
 
         GLshort w = sWidth;
         GLshort h = sHeight;
diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp
index 96a5411..68e8f19 100644
--- a/libs/surfaceflinger/SurfaceFlinger.cpp
+++ b/libs/surfaceflinger/SurfaceFlinger.cpp
@@ -44,6 +44,7 @@
 #include <GLES/gl.h>
 
 #include "clz.h"
+#include "GLExtensions.h"
 #include "Layer.h"
 #include "LayerBlur.h"
 #include "LayerBuffer.h"
@@ -993,7 +994,9 @@
         glTexCoordPointer(2, GL_SHORT, 0, tcoords);
         glEnableClientState(GL_TEXTURE_COORD_ARRAY);
 #if defined(GL_OES_texture_external)
-        glDisable(GL_TEXTURE_EXTERNAL_OES);
+        if (GLExtensions::getInstance().haveTextureExternal()) {
+            glDisable(GL_TEXTURE_EXTERNAL_OES);
+        }
 #endif
         glEnable(GL_TEXTURE_2D);
         glBindTexture(GL_TEXTURE_2D, mWormholeTexName);
@@ -1260,10 +1263,19 @@
         format = PIXEL_FORMAT_RGBA_8888;
         break;
     case PIXEL_FORMAT_OPAQUE:
+#ifdef NO_RGBX_8888
+        format = PIXEL_FORMAT_RGB_565;
+#else
         format = PIXEL_FORMAT_RGBX_8888;
+#endif
         break;
     }
 
+#ifdef NO_RGBX_8888
+    if (format == PIXEL_FORMAT_RGBX_8888)
+        format = PIXEL_FORMAT_RGBA_8888;
+#endif
+
     sp<Layer> layer = new Layer(this, display, client);
     status_t err = layer->setBuffers(w, h, format, flags);
     if (LIKELY(err != NO_ERROR)) {
diff --git a/libs/surfaceflinger/TextureManager.cpp b/libs/surfaceflinger/TextureManager.cpp
index d9bdc6a..6526032 100644
--- a/libs/surfaceflinger/TextureManager.cpp
+++ b/libs/surfaceflinger/TextureManager.cpp
@@ -30,14 +30,15 @@
 
 #include "clz.h"
 #include "DisplayHardware/DisplayHardware.h"
+#include "GLExtensions.h"
 #include "TextureManager.h"
 
 namespace android {
 
 // ---------------------------------------------------------------------------
 
-TextureManager::TextureManager(uint32_t flags)
-    : mFlags(flags)
+TextureManager::TextureManager()
+    : mGLExtensions(GLExtensions::getInstance())
 {
 }
 
@@ -85,9 +86,11 @@
 
     GLenum target = GL_TEXTURE_2D;
 #if defined(GL_OES_texture_external)
-    if (format && isSupportedYuvFormat(format)) {
-        target = GL_TEXTURE_EXTERNAL_OES;
-        pImage->target = Texture::TEXTURE_EXTERNAL;
+    if (GLExtensions::getInstance().haveTextureExternal()) {
+        if (format && isYuvFormat(format)) {
+            target = GL_TEXTURE_EXTERNAL_OES;
+            pImage->target = Texture::TEXTURE_EXTERNAL;
+        }
     }
 #endif
 
@@ -102,23 +105,32 @@
 
 bool TextureManager::isSupportedYuvFormat(int format)
 {
-    return isYuvFormat(format);
+    switch (format) {
+    case HAL_PIXEL_FORMAT_YV12:
+    case HAL_PIXEL_FORMAT_YV16:
+        return true;
+    }
+    return false;
 }
 
 bool TextureManager::isYuvFormat(int format)
 {
     switch (format) {
-    case HAL_PIXEL_FORMAT_NV16:
-    case HAL_PIXEL_FORMAT_NV21:
-    case HAL_PIXEL_FORMAT_IYUV:
-    case HAL_PIXEL_FORMAT_YUV9:
-    case HAL_PIXEL_FORMAT_YUY2:
-    case HAL_PIXEL_FORMAT_UYVY:
-    case HAL_PIXEL_FORMAT_NV12:
-    case HAL_PIXEL_FORMAT_NV61:
-    case HAL_PIXEL_FORMAT_NV12_ADRENO_TILED:
+    // supported YUV formats
+    case HAL_PIXEL_FORMAT_YV12:
+    case HAL_PIXEL_FORMAT_YV16:
+    // Legacy/deprecated YUV formats
+    case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+    case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+    case HAL_PIXEL_FORMAT_YCbCr_422_I:
+    case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
         return true;
     }
+
+    // Any OEM format needs to be considered
+    if (format>=0x100 && format<=0x1FF)
+        return true;
+
     return false;
 }
 
@@ -208,7 +220,7 @@
     /*
      * round to POT if needed
      */
-    if (!(mFlags & DisplayHardware::NPOT_EXTENSION)) {
+    if (!mGLExtensions.haveNpot()) {
         texture->NPOTAdjust = true;
     }
 
@@ -252,7 +264,7 @@
             glTexImage2D(GL_TEXTURE_2D, 0,
                     GL_RGBA, texture->potWidth, texture->potHeight, 0,
                     GL_RGBA, GL_UNSIGNED_BYTE, data);
-        } else if (isYuvFormat(t.format)) {
+        } else if (isSupportedYuvFormat(t.format)) {
             // just show the Y plane of YUV buffers
             glTexImage2D(GL_TEXTURE_2D, 0,
                     GL_LUMINANCE, texture->potWidth, texture->potHeight, 0,
@@ -280,7 +292,7 @@
                     0, bounds.top, t.width, bounds.height(),
                     GL_RGBA, GL_UNSIGNED_BYTE,
                     t.data + bounds.top*t.stride*4);
-        } else if (isYuvFormat(t.format)) {
+        } else if (isSupportedYuvFormat(t.format)) {
             // just show the Y plane of YUV buffers
             glTexSubImage2D(GL_TEXTURE_2D, 0,
                     0, bounds.top, t.width, bounds.height(),
@@ -294,17 +306,19 @@
 void TextureManager::activateTexture(const Texture& texture, bool filter)
 {
     const GLenum target = getTextureTarget(&texture);
-
-    glBindTexture(target, texture.name);
-    glEnable(target);
-
+    if (target == GL_TEXTURE_2D) {
+        glBindTexture(GL_TEXTURE_2D, texture.name);
+        glEnable(GL_TEXTURE_2D);
 #if defined(GL_OES_texture_external)
-    if (texture.target == Texture::TEXTURE_2D) {
-        glDisable(GL_TEXTURE_EXTERNAL_OES);
+        if (GLExtensions::getInstance().haveTextureExternal()) {
+            glDisable(GL_TEXTURE_EXTERNAL_OES);
+        }
     } else {
+        glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture.name);
+        glEnable(GL_TEXTURE_EXTERNAL_OES);
         glDisable(GL_TEXTURE_2D);
-    }
 #endif
+    }
 
     if (filter) {
         glTexParameterx(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
@@ -319,7 +333,9 @@
 {
     glDisable(GL_TEXTURE_2D);
 #if defined(GL_OES_texture_external)
-    glDisable(GL_TEXTURE_EXTERNAL_OES);
+    if (GLExtensions::getInstance().haveTextureExternal()) {
+        glDisable(GL_TEXTURE_EXTERNAL_OES);
+    }
 #endif
 }
 
diff --git a/libs/surfaceflinger/TextureManager.h b/libs/surfaceflinger/TextureManager.h
index 1f7fe3f..c7c14e7 100644
--- a/libs/surfaceflinger/TextureManager.h
+++ b/libs/surfaceflinger/TextureManager.h
@@ -32,6 +32,7 @@
 
 // ---------------------------------------------------------------------------
 
+class GLExtensions;
 class GraphicBuffer;
 
 // ---------------------------------------------------------------------------
@@ -61,7 +62,7 @@
 // ---------------------------------------------------------------------------
 
 class TextureManager {
-    uint32_t mFlags;
+    const GLExtensions& mGLExtensions;
     static status_t initTexture(Image* texture, int32_t format);
     static status_t initTexture(Texture* texture);
     static bool isSupportedYuvFormat(int format);
@@ -69,7 +70,7 @@
     static GLenum getTextureTarget(const Image* pImage);
 public:
 
-    TextureManager(uint32_t flags);
+    TextureManager();
 
     // load bitmap data into the active buffer
     status_t loadTexture(Texture* texture,
diff --git a/libs/surfaceflinger_client/Surface.cpp b/libs/surfaceflinger_client/Surface.cpp
index 8617d94..dc6332c 100644
--- a/libs/surfaceflinger_client/Surface.cpp
+++ b/libs/surfaceflinger_client/Surface.cpp
@@ -387,21 +387,21 @@
 
 void Surface::init()
 {
-    android_native_window_t::setSwapInterval  = setSwapInterval;
-    android_native_window_t::dequeueBuffer    = dequeueBuffer;
-    android_native_window_t::lockBuffer       = lockBuffer;
-    android_native_window_t::queueBuffer      = queueBuffer;
-    android_native_window_t::query            = query;
-    android_native_window_t::perform          = perform;
+    ANativeWindow::setSwapInterval  = setSwapInterval;
+    ANativeWindow::dequeueBuffer    = dequeueBuffer;
+    ANativeWindow::lockBuffer       = lockBuffer;
+    ANativeWindow::queueBuffer      = queueBuffer;
+    ANativeWindow::query            = query;
+    ANativeWindow::perform          = perform;
 
     DisplayInfo dinfo;
     SurfaceComposerClient::getDisplayInfo(0, &dinfo);
-    const_cast<float&>(android_native_window_t::xdpi) = dinfo.xdpi;
-    const_cast<float&>(android_native_window_t::ydpi) = dinfo.ydpi;
+    const_cast<float&>(ANativeWindow::xdpi) = dinfo.xdpi;
+    const_cast<float&>(ANativeWindow::ydpi) = dinfo.ydpi;
     // FIXME: set real values here
-    const_cast<int&>(android_native_window_t::minSwapInterval) = 1;
-    const_cast<int&>(android_native_window_t::maxSwapInterval) = 1;
-    const_cast<uint32_t&>(android_native_window_t::flags) = 0;
+    const_cast<int&>(ANativeWindow::minSwapInterval) = 1;
+    const_cast<int&>(ANativeWindow::maxSwapInterval) = 1;
+    const_cast<uint32_t&>(ANativeWindow::flags) = 0;
 
     mConnected = 0;
     mSwapRectangle.makeInvalid();
@@ -485,35 +485,35 @@
 
 // ----------------------------------------------------------------------------
 
-int Surface::setSwapInterval(android_native_window_t* window, int interval) {
+int Surface::setSwapInterval(ANativeWindow* window, int interval) {
     return 0;
 }
 
-int Surface::dequeueBuffer(android_native_window_t* window, 
+int Surface::dequeueBuffer(ANativeWindow* window, 
         android_native_buffer_t** buffer) {
     Surface* self = getSelf(window);
     return self->dequeueBuffer(buffer);
 }
 
-int Surface::lockBuffer(android_native_window_t* window, 
+int Surface::lockBuffer(ANativeWindow* window, 
         android_native_buffer_t* buffer) {
     Surface* self = getSelf(window);
     return self->lockBuffer(buffer);
 }
 
-int Surface::queueBuffer(android_native_window_t* window, 
+int Surface::queueBuffer(ANativeWindow* window, 
         android_native_buffer_t* buffer) {
     Surface* self = getSelf(window);
     return self->queueBuffer(buffer);
 }
 
-int Surface::query(android_native_window_t* window, 
+int Surface::query(ANativeWindow* window, 
         int what, int* value) {
     Surface* self = getSelf(window);
     return self->query(what, value);
 }
 
-int Surface::perform(android_native_window_t* window, 
+int Surface::perform(ANativeWindow* window, 
         int operation, ...) {
     va_list args;
     va_start(args, operation);
@@ -803,7 +803,7 @@
 {
     if (getConnectedApi()) {
         LOGE("Surface::lock(%p) failed. Already connected to another API",
-                (android_native_window_t*)this);
+                (ANativeWindow*)this);
         CallStack stack;
         stack.update();
         stack.dump("");
diff --git a/libs/ui/FramebufferNativeWindow.cpp b/libs/ui/FramebufferNativeWindow.cpp
index 52380a0..6f8948d 100644
--- a/libs/ui/FramebufferNativeWindow.cpp
+++ b/libs/ui/FramebufferNativeWindow.cpp
@@ -67,7 +67,7 @@
  * This implements the (main) framebuffer management. This class is used
  * mostly by SurfaceFlinger, but also by command line GL application.
  * 
- * In fact this is an implementation of android_native_window_t on top of
+ * In fact this is an implementation of ANativeWindow on top of
  * the framebuffer.
  * 
  * Currently it is pretty simple, it manages only two buffers (the front and 
@@ -117,23 +117,23 @@
         LOGE_IF(err, "fb buffer 1 allocation failed w=%d, h=%d, err=%s",
                 fbDev->width, fbDev->height, strerror(-err));
 
-        const_cast<uint32_t&>(android_native_window_t::flags) = fbDev->flags; 
-        const_cast<float&>(android_native_window_t::xdpi) = fbDev->xdpi;
-        const_cast<float&>(android_native_window_t::ydpi) = fbDev->ydpi;
-        const_cast<int&>(android_native_window_t::minSwapInterval) = 
+        const_cast<uint32_t&>(ANativeWindow::flags) = fbDev->flags; 
+        const_cast<float&>(ANativeWindow::xdpi) = fbDev->xdpi;
+        const_cast<float&>(ANativeWindow::ydpi) = fbDev->ydpi;
+        const_cast<int&>(ANativeWindow::minSwapInterval) = 
             fbDev->minSwapInterval;
-        const_cast<int&>(android_native_window_t::maxSwapInterval) = 
+        const_cast<int&>(ANativeWindow::maxSwapInterval) = 
             fbDev->maxSwapInterval;
     } else {
         LOGE("Couldn't get gralloc module");
     }
 
-    android_native_window_t::setSwapInterval = setSwapInterval;
-    android_native_window_t::dequeueBuffer = dequeueBuffer;
-    android_native_window_t::lockBuffer = lockBuffer;
-    android_native_window_t::queueBuffer = queueBuffer;
-    android_native_window_t::query = query;
-    android_native_window_t::perform = perform;
+    ANativeWindow::setSwapInterval = setSwapInterval;
+    ANativeWindow::dequeueBuffer = dequeueBuffer;
+    ANativeWindow::lockBuffer = lockBuffer;
+    ANativeWindow::queueBuffer = queueBuffer;
+    ANativeWindow::query = query;
+    ANativeWindow::perform = perform;
 }
 
 FramebufferNativeWindow::~FramebufferNativeWindow() 
@@ -168,13 +168,13 @@
 }
 
 int FramebufferNativeWindow::setSwapInterval(
-        android_native_window_t* window, int interval) 
+        ANativeWindow* window, int interval) 
 {
     framebuffer_device_t* fb = getSelf(window)->fbDev;
     return fb->setSwapInterval(fb, interval);
 }
 
-int FramebufferNativeWindow::dequeueBuffer(android_native_window_t* window, 
+int FramebufferNativeWindow::dequeueBuffer(ANativeWindow* window, 
         android_native_buffer_t** buffer)
 {
     FramebufferNativeWindow* self = getSelf(window);
@@ -196,7 +196,7 @@
     return 0;
 }
 
-int FramebufferNativeWindow::lockBuffer(android_native_window_t* window, 
+int FramebufferNativeWindow::lockBuffer(ANativeWindow* window, 
         android_native_buffer_t* buffer)
 {
     FramebufferNativeWindow* self = getSelf(window);
@@ -210,7 +210,7 @@
     return NO_ERROR;
 }
 
-int FramebufferNativeWindow::queueBuffer(android_native_window_t* window, 
+int FramebufferNativeWindow::queueBuffer(ANativeWindow* window, 
         android_native_buffer_t* buffer)
 {
     FramebufferNativeWindow* self = getSelf(window);
@@ -224,7 +224,7 @@
     return res;
 }
 
-int FramebufferNativeWindow::query(android_native_window_t* window,
+int FramebufferNativeWindow::query(ANativeWindow* window,
         int what, int* value) 
 {
     FramebufferNativeWindow* self = getSelf(window);
@@ -245,7 +245,7 @@
     return BAD_VALUE;
 }
 
-int FramebufferNativeWindow::perform(android_native_window_t* window,
+int FramebufferNativeWindow::perform(ANativeWindow* window,
         int operation, ...)
 {
     switch (operation) {
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index 4b5f025..519c277 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -127,18 +127,6 @@
 {
     GraphicBufferAllocator& allocator = GraphicBufferAllocator::get();
     status_t err = allocator.alloc(w, h, format, reqUsage, &handle, &stride);
-
-    if (err<0 && format == PIXEL_FORMAT_RGBX_8888) {
-        /*
-         * There is currently a bug with some gralloc implementations
-         * not supporting RGBX_8888. In this case, we revert to using RGBA_8888
-         * which is not exactly the same, as GL_REPLACE will yield a different
-         * result.
-         */
-        format = PIXEL_FORMAT_RGBA_8888;
-        err = allocator.alloc(w, h, format, reqUsage, &handle, &stride);
-    }
-
     if (err == NO_ERROR) {
         this->width  = w;
         this->height = h;
diff --git a/libs/ui/Input.cpp b/libs/ui/Input.cpp
index 4121b5a..a64251f 100644
--- a/libs/ui/Input.cpp
+++ b/libs/ui/Input.cpp
@@ -20,6 +20,70 @@
 
 // class KeyEvent
 
+bool KeyEvent::hasDefaultAction(int32_t keyCode) {
+    switch (keyCode) {
+        case KEYCODE_HOME:
+        case KEYCODE_BACK:
+        case KEYCODE_CALL:
+        case KEYCODE_ENDCALL:
+        case KEYCODE_VOLUME_UP:
+        case KEYCODE_VOLUME_DOWN:
+        case KEYCODE_POWER:
+        case KEYCODE_CAMERA:
+        case KEYCODE_HEADSETHOOK:
+        case KEYCODE_MENU:
+        case KEYCODE_NOTIFICATION:
+        case KEYCODE_FOCUS:
+        case KEYCODE_SEARCH:
+        case KEYCODE_MEDIA_PLAY_PAUSE:
+        case KEYCODE_MEDIA_STOP:
+        case KEYCODE_MEDIA_NEXT:
+        case KEYCODE_MEDIA_PREVIOUS:
+        case KEYCODE_MEDIA_REWIND:
+        case KEYCODE_MEDIA_FAST_FORWARD:
+        case KEYCODE_MUTE:
+            return true;
+    }
+    
+    return false;
+}
+
+bool KeyEvent::hasDefaultAction() const {
+    return hasDefaultAction(getKeyCode());
+}
+
+bool KeyEvent::isSystemKey(int32_t keyCode) {
+    switch (keyCode) {
+        case KEYCODE_MENU:
+        case KEYCODE_SOFT_RIGHT:
+        case KEYCODE_HOME:
+        case KEYCODE_BACK:
+        case KEYCODE_CALL:
+        case KEYCODE_ENDCALL:
+        case KEYCODE_VOLUME_UP:
+        case KEYCODE_VOLUME_DOWN:
+        case KEYCODE_MUTE:
+        case KEYCODE_POWER:
+        case KEYCODE_HEADSETHOOK:
+        case KEYCODE_MEDIA_PLAY_PAUSE:
+        case KEYCODE_MEDIA_STOP:
+        case KEYCODE_MEDIA_NEXT:
+        case KEYCODE_MEDIA_PREVIOUS:
+        case KEYCODE_MEDIA_REWIND:
+        case KEYCODE_MEDIA_FAST_FORWARD:
+        case KEYCODE_CAMERA:
+        case KEYCODE_FOCUS:
+        case KEYCODE_SEARCH:
+            return true;
+    }
+    
+    return false;
+}
+
+bool KeyEvent::isSystemKey() const {
+    return isSystemKey(getKeyCode());
+}
+
 void KeyEvent::initialize(
         int32_t deviceId,
         int32_t nature,
diff --git a/libs/ui/InputDispatcher.cpp b/libs/ui/InputDispatcher.cpp
index 0fc29b2..8f6d1fe 100644
--- a/libs/ui/InputDispatcher.cpp
+++ b/libs/ui/InputDispatcher.cpp
@@ -232,6 +232,9 @@
     LOGD("processConfigurationChanged - eventTime=%lld", entry->eventTime);
 #endif
 
+    // Reset key repeating in case a keyboard device was added or removed or something.
+    resetKeyRepeatLocked();
+
     mLock.unlock();
 
     mPolicy->notifyConfigurationChanged(entry->eventTime);
diff --git a/libs/ui/InputReader.cpp b/libs/ui/InputReader.cpp
index 8087f84..899027c 100644
--- a/libs/ui/InputReader.cpp
+++ b/libs/ui/InputReader.cpp
@@ -387,6 +387,11 @@
  * points has moved more than a screen height from the last position,
  * then drop it. */
 bool InputDevice::TouchScreenState::applyBadTouchFilter() {
+    // This hack requires valid axis parameters.
+    if (! parameters.yAxis.valid) {
+        return false;
+    }
+
     uint32_t pointerCount = currentTouch.pointerCount;
 
     // Nothing to do if there are no points.
@@ -466,6 +471,11 @@
  * the coordinate value for one axis has jumped to the other pointer's location.
  */
 bool InputDevice::TouchScreenState::applyJumpyTouchFilter() {
+    // This hack requires valid axis parameters.
+    if (! parameters.yAxis.valid) {
+        return false;
+    }
+
     uint32_t pointerCount = currentTouch.pointerCount;
     if (lastTouch.pointerCount != pointerCount) {
 #if DEBUG_HACKS
@@ -724,6 +734,12 @@
 }
 
 bool InputDevice::TouchScreenState::isPointInsideDisplay(int32_t x, int32_t y) const {
+    if (! parameters.xAxis.valid || ! parameters.yAxis.valid) {
+        // Assume all points on a touch screen without valid axis parameters are
+        // inside the display.
+        return true;
+    }
+
     return x >= parameters.xAxis.minValue
         && x <= parameters.xAxis.maxValue
         && y >= parameters.yAxis.minValue
@@ -1435,6 +1451,9 @@
     int32_t pointerIds[MAX_POINTERS];
     PointerCoords pointerCoords[MAX_POINTERS];
 
+    const InputDevice::TouchScreenState::Precalculated& precalculated =
+            device->touchScreen.precalculated;
+
     // Walk through the the active pointers and map touch screen coordinates (TouchData) into
     // display coordinates (PointerCoords) and adjust for display orientation.
     while (! idBits.isEmpty()) {
@@ -1442,18 +1461,14 @@
         idBits.clearBit(id);
         uint32_t index = touch->idToIndex[id];
 
-        float x = (float(touch->pointers[index].x)
-                        - device->touchScreen.parameters.xAxis.minValue)
-                * device->touchScreen.precalculated.xScale;
-        float y = (float(touch->pointers[index].y)
-                        - device->touchScreen.parameters.yAxis.minValue)
-                * device->touchScreen.precalculated.yScale;
-        float pressure = (float(touch->pointers[index].pressure)
-                        - device->touchScreen.parameters.pressureAxis.minValue)
-                * device->touchScreen.precalculated.pressureScale;
-        float size = (float(touch->pointers[index].size)
-                        - device->touchScreen.parameters.sizeAxis.minValue)
-                * device->touchScreen.precalculated.sizeScale;
+        float x = float(touch->pointers[index].x
+                - precalculated.xOrigin) * precalculated.xScale;
+        float y = float(touch->pointers[index].y
+                - precalculated.yOrigin) * precalculated.yScale;
+        float pressure = float(touch->pointers[index].pressure
+                - precalculated.pressureOrigin) * precalculated.pressureScale;
+        float size = float(touch->pointers[index].size
+                - precalculated.sizeOrigin) * precalculated.sizeScale;
 
         switch (mDisplayOrientation) {
         case InputReaderPolicyInterface::ROTATION_90: {
@@ -1624,10 +1639,6 @@
         *policyFlags |= POLICY_FLAG_BRIGHT_HERE;
     }
 
-    if (policyActions & InputReaderPolicyInterface::ACTION_INTERCEPT_DISPATCH) {
-        *policyFlags |= POLICY_FLAG_INTERCEPT_DISPATCH;
-    }
-
     return policyActions & InputReaderPolicyInterface::ACTION_DISPATCH;
 }
 
@@ -1651,7 +1662,11 @@
             }
         }
 
-        mDisplayOrientation = newOrientation;
+        if (newOrientation != mDisplayOrientation) {
+            LOGD("Display orientation changed to %d", mDisplayOrientation);
+
+            mDisplayOrientation = newOrientation;
+        }
         return true;
     } else {
         resetDisplayProperties();
@@ -1740,10 +1755,25 @@
         device->touchScreen.parameters.useJumpyTouchFilter =
                 mPolicy->filterJumpyTouchEvents();
 
-        device->touchScreen.precalculated.pressureScale =
-                1.0f / device->touchScreen.parameters.pressureAxis.range;
-        device->touchScreen.precalculated.sizeScale =
-                1.0f / device->touchScreen.parameters.sizeAxis.range;
+        if (device->touchScreen.parameters.pressureAxis.valid) {
+            device->touchScreen.precalculated.pressureOrigin =
+                    device->touchScreen.parameters.pressureAxis.minValue;
+            device->touchScreen.precalculated.pressureScale =
+                    1.0f / device->touchScreen.parameters.pressureAxis.range;
+        } else {
+            device->touchScreen.precalculated.pressureOrigin = 0;
+            device->touchScreen.precalculated.pressureScale = 1.0f;
+        }
+
+        if (device->touchScreen.parameters.sizeAxis.valid) {
+            device->touchScreen.precalculated.sizeOrigin =
+                    device->touchScreen.parameters.sizeAxis.minValue;
+            device->touchScreen.precalculated.sizeScale =
+                    1.0f / device->touchScreen.parameters.sizeAxis.range;
+        } else {
+            device->touchScreen.precalculated.sizeOrigin = 0;
+            device->touchScreen.precalculated.sizeScale = 1.0f;
+        }
     }
 
     if (device->isTrackball()) {
@@ -1758,22 +1788,42 @@
 
 void InputReader::configureDeviceForCurrentDisplaySize(InputDevice* device) {
     if (device->isTouchScreen()) {
-        if (mDisplayWidth < 0) {
-            LOGD("Skipping part of touch screen configuration since display size is unknown.");
-        } else {
-            LOGI("Device configured: id=0x%x, name=%s (display size was changed)", device->id,
-                    device->name.string());
-            configureVirtualKeys(device);
+        if (device->touchScreen.parameters.xAxis.valid
+                && device->touchScreen.parameters.yAxis.valid) {
+            device->touchScreen.precalculated.xOrigin =
+                    device->touchScreen.parameters.xAxis.minValue;
+            device->touchScreen.precalculated.yOrigin =
+                    device->touchScreen.parameters.yAxis.minValue;
 
-            device->touchScreen.precalculated.xScale =
-                    float(mDisplayWidth) / device->touchScreen.parameters.xAxis.range;
-            device->touchScreen.precalculated.yScale =
-                    float(mDisplayHeight) / device->touchScreen.parameters.yAxis.range;
+            if (mDisplayWidth < 0) {
+                LOGD("Skipping part of touch screen configuration since display size is unknown.");
+
+                device->touchScreen.precalculated.xScale = 1.0f;
+                device->touchScreen.precalculated.yScale = 1.0f;
+            } else {
+                LOGI("Device configured: id=0x%x, name=%s (display size was changed)", device->id,
+                        device->name.string());
+
+                device->touchScreen.precalculated.xScale =
+                        float(mDisplayWidth) / device->touchScreen.parameters.xAxis.range;
+                device->touchScreen.precalculated.yScale =
+                        float(mDisplayHeight) / device->touchScreen.parameters.yAxis.range;
+
+                configureVirtualKeys(device);
+            }
+        } else {
+            device->touchScreen.precalculated.xOrigin = 0;
+            device->touchScreen.precalculated.xScale = 1.0f;
+            device->touchScreen.precalculated.yOrigin = 0;
+            device->touchScreen.precalculated.yScale = 1.0f;
         }
     }
 }
 
 void InputReader::configureVirtualKeys(InputDevice* device) {
+    assert(device->touchScreen.parameters.xAxis.valid
+            && device->touchScreen.parameters.yAxis.valid);
+
     device->touchScreen.virtualKeys.clear();
 
     Vector<InputReaderPolicyInterface::VirtualKeyDefinition> virtualKeyDefinitions;
@@ -1837,16 +1887,18 @@
         if (out->range != 0) {
             LOGI("  %s: min=%d max=%d flat=%d fuzz=%d",
                     name, out->minValue, out->maxValue, out->flat, out->fuzz);
+            out->valid = true;
             return;
         }
     }
 
+    out->valid = false;
     out->minValue = 0;
     out->maxValue = 0;
     out->flat = 0;
     out->fuzz = 0;
     out->range = 0;
-    LOGI("  %s: unknown axis values, setting to zero", name);
+    LOGI("  %s: unknown axis values, marking as invalid", name);
 }
 
 void InputReader::configureExcludedDevices() {
diff --git a/libs/ui/InputTransport.cpp b/libs/ui/InputTransport.cpp
index f56537a..25def3c 100644
--- a/libs/ui/InputTransport.cpp
+++ b/libs/ui/InputTransport.cpp
@@ -691,7 +691,7 @@
 
 } // namespace android
 
-// --- input_queue_t ---
+// --- AInputQueue ---
 
 using android::InputEvent;
 using android::InputChannel;
@@ -699,13 +699,13 @@
 using android::sp;
 using android::status_t;
 
-input_queue_t::input_queue_t(const sp<InputChannel>& channel) :
+AInputQueue::AInputQueue(const sp<InputChannel>& channel) :
         mConsumer(channel) {
 }
 
-input_queue_t::~input_queue_t() {
+AInputQueue::~AInputQueue() {
 }
 
-status_t input_queue_t::consume(InputEvent** event) {
+status_t AInputQueue::consume(InputEvent** event) {
     return mConsumer.consume(&mInputEventFactory, event);
 }
diff --git a/libs/ui/PixelFormat.cpp b/libs/ui/PixelFormat.cpp
index c9a5950..b205418 100644
--- a/libs/ui/PixelFormat.cpp
+++ b/libs/ui/PixelFormat.cpp
@@ -59,16 +59,13 @@
     // YUV format from the HAL are handled here
     switch (format) {
     case HAL_PIXEL_FORMAT_YCbCr_422_SP:
-    case HAL_PIXEL_FORMAT_YCrCb_422_SP:
-    case HAL_PIXEL_FORMAT_YCbCr_422_P:
     case HAL_PIXEL_FORMAT_YCbCr_422_I:
-    case HAL_PIXEL_FORMAT_CbYCrY_422_I:
+    case HAL_PIXEL_FORMAT_YV16:
         info->bitsPerPixel = 16;
         goto done;
-    case HAL_PIXEL_FORMAT_YCbCr_420_SP:
     case HAL_PIXEL_FORMAT_YCrCb_420_SP:
     case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
-    case HAL_PIXEL_FORMAT_YCbCr_420_P:
+    case HAL_PIXEL_FORMAT_YV12:
         info->bitsPerPixel = 12;
      done:
         info->format = format;
diff --git a/libs/utils/PollLoop.cpp b/libs/utils/PollLoop.cpp
index 20a4d13..58fe141 100644
--- a/libs/utils/PollLoop.cpp
+++ b/libs/utils/PollLoop.cpp
@@ -21,6 +21,10 @@
 
 namespace android {
 
+static pthread_mutex_t gTLSMutex = PTHREAD_MUTEX_INITIALIZER;
+static bool gHaveTLS = false;
+static pthread_key_t gTLS = 0;
+
 PollLoop::PollLoop() :
         mPolling(false), mWaiters(0) {
     openWakePipe();
@@ -30,6 +34,41 @@
     closeWakePipe();
 }
 
+void PollLoop::threadDestructor(void *st) {
+    PollLoop* const self = static_cast<PollLoop*>(st);
+    if (self != NULL) {
+        self->decStrong((void*)threadDestructor);
+    }
+}
+
+void PollLoop::setForThread(const sp<PollLoop>& pollLoop) {
+    sp<PollLoop> old = getForThread();
+    
+    if (pollLoop != NULL) {
+        pollLoop->incStrong((void*)threadDestructor);
+    }
+    
+    pthread_setspecific(gTLS, pollLoop.get());
+    
+    if (old != NULL) {
+        old->decStrong((void*)threadDestructor);
+    }
+}
+    
+sp<PollLoop> PollLoop::getForThread() {
+    if (!gHaveTLS) {
+        pthread_mutex_lock(&gTLSMutex);
+        if (pthread_key_create(&gTLS, threadDestructor) != 0) {
+            pthread_mutex_unlock(&gTLSMutex);
+            return NULL;
+        }
+        gHaveTLS = true;
+        pthread_mutex_unlock(&gTLSMutex);
+    }
+    
+    return (PollLoop*)pthread_getspecific(gTLS);
+}
+
 void PollLoop::openWakePipe() {
     int wakeFds[2];
     int result = pipe(wakeFds);
@@ -54,6 +93,7 @@
 
     RequestedCallback requestedCallback;
     requestedCallback.callback = NULL;
+    requestedCallback.looperCallback = NULL;
     requestedCallback.data = NULL;
     mRequestedCallbacks.insertAt(requestedCallback, 0);
 }
@@ -123,12 +163,14 @@
         if (revents) {
             const RequestedCallback& requestedCallback = mRequestedCallbacks.itemAt(i);
             Callback callback = requestedCallback.callback;
+            ALooper_callbackFunc* looperCallback = requestedCallback.looperCallback;
 
-            if (callback) {
+            if (callback || looperCallback) {
                 PendingCallback pendingCallback;
                 pendingCallback.fd = requestedFd.fd;
                 pendingCallback.events = requestedFd.revents;
                 pendingCallback.callback = callback;
+                pendingCallback.looperCallback = looperCallback;
                 pendingCallback.data = requestedCallback.data;
                 mPendingCallbacks.push(pendingCallback);
             } else {
@@ -172,8 +214,14 @@
             LOGD("%p ~ pollOnce - invoking callback for fd %d", this, pendingCallback.fd);
 #endif
 
-            bool keep = pendingCallback.callback(pendingCallback.fd, pendingCallback.events,
-                    pendingCallback.data);
+            bool keep = true;
+            if (pendingCallback.callback != NULL) {
+                keep = pendingCallback.callback(pendingCallback.fd, pendingCallback.events,
+                        pendingCallback.data);
+            } else {
+                keep = pendingCallback.looperCallback(pendingCallback.fd, pendingCallback.events,
+                        pendingCallback.data) != 0;
+            }
             if (! keep) {
                 removeCallback(pendingCallback.fd);
             }
@@ -200,11 +248,22 @@
 }
 
 void PollLoop::setCallback(int fd, int events, Callback callback, void* data) {
+    setCallbackCommon(fd, events, callback, NULL, data);
+}
+
+void PollLoop::setLooperCallback(int fd, int events, ALooper_callbackFunc* callback,
+        void* data) {
+    setCallbackCommon(fd, events, NULL, callback, data);
+}
+
+void PollLoop::setCallbackCommon(int fd, int events, Callback callback,
+        ALooper_callbackFunc* looperCallback, void* data) {
+
 #if DEBUG_CALLBACKS
     LOGD("%p ~ setCallback - fd=%d, events=%d", this, fd, events);
 #endif
 
-    if (! events || ! callback) {
+    if (! events || (! callback && ! looperCallback)) {
         LOGE("Invalid attempt to set a callback with no selected poll events or no callback.");
         removeCallback(fd);
         return;
@@ -218,6 +277,7 @@
 
     RequestedCallback requestedCallback;
     requestedCallback.callback = callback;
+    requestedCallback.looperCallback = looperCallback;
     requestedCallback.data = data;
 
     ssize_t index = getRequestIndexLocked(fd);
diff --git a/opengl/include/EGL/eglplatform.h b/opengl/include/EGL/eglplatform.h
index a2c6a7d..25d7697 100644
--- a/opengl/include/EGL/eglplatform.h
+++ b/opengl/include/EGL/eglplatform.h
@@ -91,10 +91,11 @@
 
 #elif defined(ANDROID)
 
-struct android_native_window_t;
+#include <android/native_window.h>
+
 struct egl_native_pixmap_t;
 
-typedef struct android_native_window_t* EGLNativeWindowType;
+typedef struct ANativeWindow*           EGLNativeWindowType;
 typedef struct egl_native_pixmap_t*     EGLNativePixmapType;
 typedef void*                           EGLNativeDisplayType;
 
diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp
index 7cb01d0..54d7307 100644
--- a/opengl/libagl/egl.cpp
+++ b/opengl/libagl/egl.cpp
@@ -213,7 +213,7 @@
     egl_window_surface_v2_t(
             EGLDisplay dpy, EGLConfig config,
             int32_t depthFormat,
-            android_native_window_t* window);
+            ANativeWindow* window);
 
     ~egl_window_surface_v2_t();
 
@@ -235,7 +235,7 @@
 private:
     status_t lock(android_native_buffer_t* buf, int usage, void** vaddr);
     status_t unlock(android_native_buffer_t* buf);
-    android_native_window_t*   nativeWindow;
+    ANativeWindow*   nativeWindow;
     android_native_buffer_t*   buffer;
     android_native_buffer_t*   previousBuffer;
     gralloc_module_t const*    module;
@@ -355,7 +355,7 @@
 egl_window_surface_v2_t::egl_window_surface_v2_t(EGLDisplay dpy,
         EGLConfig config,
         int32_t depthFormat,
-        android_native_window_t* window)
+        ANativeWindow* window)
     : egl_surface_t(dpy, config, depthFormat), 
     nativeWindow(window), buffer(0), previousBuffer(0), module(0),
     blitengine(0), bits(NULL)
@@ -1300,7 +1300,7 @@
     if (!(surfaceType & EGL_WINDOW_BIT))
         return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
 
-    if (static_cast<android_native_window_t*>(window)->common.magic !=
+    if (static_cast<ANativeWindow*>(window)->common.magic !=
             ANDROID_NATIVE_WINDOW_MAGIC) {
         return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
     }
@@ -1323,7 +1323,7 @@
 
     egl_surface_t* surface;
     surface = new egl_window_surface_v2_t(dpy, config, depthFormat,
-            static_cast<android_native_window_t*>(window));
+            static_cast<ANativeWindow*>(window));
 
     if (!surface->initCheck()) {
         // there was a problem in the ctor, the error
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index ba09d08..714fd3e 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -1045,6 +1045,10 @@
     int i=0, index=0;
     egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index);
     if (cnx) {
+        if (share_list != EGL_NO_CONTEXT) {
+            egl_context_t* const c = get_context(share_list);
+            share_list = c->context;
+        }
         EGLContext context = cnx->egl.eglCreateContext(
                 dp->disp[i].dpy, dp->disp[i].config[index],
                 share_list, attrib_list);