Merge "Don't overwrite pending port setting change if there are more than one port setting change event."
diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp
index 710ef94..0bee0f1 100644
--- a/libs/gui/SurfaceTextureClient.cpp
+++ b/libs/gui/SurfaceTextureClient.cpp
@@ -219,9 +219,12 @@
     if (i < 0) {
         return i;
     }
-    mSurfaceTexture->queueBuffer(i, timestamp,
+    status_t err = mSurfaceTexture->queueBuffer(i, timestamp,
             &mDefaultWidth, &mDefaultHeight, &mTransformHint);
-    return OK;
+    if (err != OK)  {
+        LOGE("queueBuffer: error queuing buffer to SurfaceTexture, %d", err);
+    }
+    return err;
 }
 
 int SurfaceTextureClient::query(int what, int* value) const {
diff --git a/libs/gui/tests/SurfaceTexture_test.cpp b/libs/gui/tests/SurfaceTexture_test.cpp
index 44babcf..b8bc454 100644
--- a/libs/gui/tests/SurfaceTexture_test.cpp
+++ b/libs/gui/tests/SurfaceTexture_test.cpp
@@ -974,8 +974,6 @@
 
     eglSwapBuffers(mEglDisplay, stcEglSurface);
 
-    eglDestroySurface(mEglDisplay, stcEglSurface);
-
     // Do the consumer side of things
     EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
             mEglContext));
@@ -985,6 +983,10 @@
 
     mST->updateTexImage();
 
+    // We must wait until updateTexImage has been called to destroy the
+    // EGLSurface because we're in synchronous mode.
+    eglDestroySurface(mEglDisplay, stcEglSurface);
+
     glClearColor(0.2, 0.2, 0.2, 0.2);
     glClear(GL_COLOR_BUFFER_BIT);
 
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index e94e50e..325193c 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -23,6 +23,7 @@
 #include <limits.h>
 
 #include <cutils/log.h>
+#include <cutils/properties.h>
 
 #include <EGL/egl.h>
 
@@ -45,6 +46,39 @@
 
 ANDROID_SINGLETON_STATIC_INSTANCE( Loader )
 
+/* This function is called to check whether we run inside the emulator,
+ * and if this is the case whether GLES GPU emulation is supported.
+ *
+ * Returned values are:
+ *  -1   -> not running inside the emulator
+ *   0   -> running inside the emulator, but GPU emulation not supported
+ *   1   -> running inside the emulator, GPU emulation is supported
+ *          through the "emulation" config.
+ */
+static int
+checkGlesEmulationStatus(void)
+{
+    /* We're going to check for the following kernel parameters:
+     *
+     *    qemu=1                      -> tells us that we run inside the emulator
+     *    android.qemu.gles=<number>  -> tells us the GLES GPU emulation status
+     *
+     * Note that we will return <number> if we find it. This let us support
+     * more additionnal emulation modes in the future.
+     */
+    char  prop[PROPERTY_VALUE_MAX];
+    int   result = -1;
+
+    /* First, check for qemu=1 */
+    property_get("ro.kernel.qemu",prop,"0");
+    if (atoi(prop) != 1)
+        return -1;
+
+    /* We are in the emulator, get GPU status value */
+    property_get("ro.kernel.qemu.gles",prop,"0");
+    return atoi(prop);
+}
+
 // ----------------------------------------------------------------------------
 
 Loader::driver_t::driver_t(void* gles) 
@@ -94,6 +128,15 @@
 {
     char line[256];
     char tag[256];
+
+    /* Special case for GLES emulation */
+    if (checkGlesEmulationStatus() == 0) {
+        LOGD("Emulator without GPU support detected. Fallback to software renderer.");
+        gConfig.add( entry_t(0, 0, "android") );
+        return;
+    }
+
+    /* Otherwise, use egl.cfg */
     FILE* cfg = fopen("/system/lib/egl/egl.cfg", "r");
     if (cfg == NULL) {
         // default config
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 7d1bdf0..0ff1cce 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -108,8 +108,21 @@
 }
 
 status_t HWComposer::release() const {
-    int err = mHwc->set(mHwc, NULL, NULL, NULL);
-    return (status_t)err;
+    if (mHwc) {
+        int err = mHwc->set(mHwc, NULL, NULL, NULL);
+        return (status_t)err;
+    }
+    return NO_ERROR;
+}
+
+status_t HWComposer::disable() {
+    if (mHwc) {
+        free(mList);
+        mList = NULL;
+        int err = mHwc->prepare(mHwc, NULL);
+        return (status_t)err;
+    }
+    return NO_ERROR;
 }
 
 size_t HWComposer::getNumLayers() const {
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 983898a..77c1a4b 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -50,6 +50,9 @@
     // Asks the HAL what it can do
     status_t prepare() const;
 
+    // disable hwc until next createWorkList
+    status_t disable();
+
     // commits the list
     status_t commit() const;
 
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index b4c5dec..4a3a8ea 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2113,6 +2113,12 @@
         // we're already off
         return NO_ERROR;
     }
+
+    // turn off hwc while we're doing the animation
+    hw.getHwComposer().disable();
+    // and make sure to turn it back on (if needed) next time we compose
+    invalidateHwcGeometry();
+
     if (mode & ISurfaceComposer::eElectronBeamAnimationOff) {
         electronBeamOffAnimationImplLocked();
     }