Merge "BufferQueue: alloc without holding the lock" into jb-mr1-dev
diff --git a/include/gui/ISurfaceComposer.h b/include/gui/ISurfaceComposer.h
index 5d2d8d7..002aafc 100644
--- a/include/gui/ISurfaceComposer.h
+++ b/include/gui/ISurfaceComposer.h
@@ -46,6 +46,7 @@
     // flags for setTransactionState()
     enum {
         eSynchronous = 0x01,
+        eAnimation   = 0x02,
     };
 
     enum {
diff --git a/include/gui/SurfaceComposerClient.h b/include/gui/SurfaceComposerClient.h
index 581ec8d..21d16a9 100644
--- a/include/gui/SurfaceComposerClient.h
+++ b/include/gui/SurfaceComposerClient.h
@@ -101,10 +101,13 @@
 
     //! Open a composer transaction on all active SurfaceComposerClients.
     static void openGlobalTransaction();
-        
+
     //! Close a composer transaction on all active SurfaceComposerClients.
     static void closeGlobalTransaction(bool synchronous = false);
 
+    //! Flag the currently open transaction as an animation transaction.
+    static void setAnimationTransaction();
+
     status_t    hide(SurfaceID id);
     status_t    show(SurfaceID id);
     status_t    setFlags(SurfaceID id, uint32_t flags, uint32_t mask);
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 3efd086..8586ed2 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -115,12 +115,15 @@
     SortedVector<ComposerState> mComposerStates;
     SortedVector<DisplayState > mDisplayStates;
     uint32_t                    mForceSynchronous;
+    bool                        mAnimation;
 
     Composer() : Singleton<Composer>(),
-        mForceSynchronous(0)
+        mForceSynchronous(0),
+        mAnimation(false)
     { }
 
     void closeGlobalTransactionImpl(bool synchronous);
+    void setAnimationTransactionImpl();
 
     layer_state_t* getLayerStateLocked(
             const sp<SurfaceComposerClient>& client, SurfaceID id);
@@ -159,6 +162,10 @@
             const Rect& layerStackRect,
             const Rect& displayRect);
 
+    static void setAnimationTransaction() {
+        Composer::getInstance().setAnimationTransactionImpl();
+    }
+
     static void closeGlobalTransaction(bool synchronous) {
         Composer::getInstance().closeGlobalTransactionImpl(synchronous);
     }
@@ -194,12 +201,22 @@
         if (synchronous || mForceSynchronous) {
             flags |= ISurfaceComposer::eSynchronous;
         }
+        if (mAnimation) {
+            flags |= ISurfaceComposer::eAnimation;
+        }
+
         mForceSynchronous = false;
+        mAnimation = false;
     }
 
    sm->setTransactionState(transaction, displayTransaction, flags);
 }
 
+void Composer::setAnimationTransactionImpl() {
+    Mutex::Autolock _l(mLock);
+    mAnimation = true;
+}
+
 layer_state_t* Composer::getLayerStateLocked(
         const sp<SurfaceComposerClient>& client, SurfaceID id) {
 
@@ -471,6 +488,10 @@
     Composer::closeGlobalTransaction(synchronous);
 }
 
+void SurfaceComposerClient::setAnimationTransaction() {
+    Composer::setAnimationTransaction();
+}
+
 // ----------------------------------------------------------------------------
 
 status_t SurfaceComposerClient::setCrop(SurfaceID id, const Rect& crop) {
diff --git a/libs/utils/ZipFileRO.cpp b/libs/utils/ZipFileRO.cpp
index cc62213..ef49c0f 100644
--- a/libs/utils/ZipFileRO.cpp
+++ b/libs/utils/ZipFileRO.cpp
@@ -140,7 +140,7 @@
     /*
      * Open and map the specified file.
      */
-    fd = ::open(zipFileName, O_RDONLY | O_BINARY);
+    fd = TEMP_FAILURE_RETRY(::open(zipFileName, O_RDONLY | O_BINARY));
     if (fd < 0) {
         ALOGW("Unable to open zip '%s': %s\n", zipFileName, strerror(errno));
         return NAME_NOT_FOUND;
@@ -771,7 +771,7 @@
     ptr = (const unsigned char*) file->getDataPtr();
 
     if (method == kCompressStored) {
-        ssize_t actual = write(fd, ptr, uncompLen);
+        ssize_t actual = TEMP_FAILURE_RETRY(write(fd, ptr, uncompLen));
         if (actual < 0) {
             ALOGE("Write failed: %s\n", strerror(errno));
             goto unmap;
@@ -920,9 +920,12 @@
             (zerr == Z_STREAM_END && zstream.avail_out != sizeof(writeBuf)))
         {
             long writeSize = zstream.next_out - writeBuf;
-            int cc = write(fd, writeBuf, writeSize);
-            if (cc != (int) writeSize) {
-                ALOGW("write failed in inflate (%d vs %ld)\n", cc, writeSize);
+            int cc = TEMP_FAILURE_RETRY(write(fd, writeBuf, writeSize));
+            if (cc < 0) {
+                ALOGW("write failed in inflate: %s", strerror(errno));
+                goto z_bail;
+            } else if (cc != (int) writeSize) {
+                ALOGW("write failed in inflate (%d vs %ld)", cc, writeSize);
                 goto z_bail;
             }
 
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 92023ba..23e89da 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -204,6 +204,59 @@
 
     egl_connection_t* const cnx = &gEGLImpl;
     if (cnx->dso) {
+        if (attrib_list) {
+            char value[PROPERTY_VALUE_MAX];
+            property_get("debug.egl.force_msaa", value, "false");
+
+            if (!strcmp(value, "true")) {
+                size_t attribCount = 0;
+                EGLint attrib = attrib_list[0];
+
+                // Only enable MSAA if the context is OpenGL ES 2.0 and
+                // if no caveat is requested
+                const EGLint *attribRendererable = NULL;
+                const EGLint *attribCaveat = NULL;
+
+                // Count the number of attributes and look for
+                // EGL_RENDERABLE_TYPE and EGL_CONFIG_CAVEAT
+                while (attrib != EGL_NONE) {
+                    attrib = attrib_list[attribCount];
+                    switch (attrib) {
+                        case EGL_RENDERABLE_TYPE:
+                            attribRendererable = &attrib_list[attribCount];
+                            break;
+                        case EGL_CONFIG_CAVEAT:
+                            attribCaveat = &attrib_list[attribCount];
+                            break;
+                    }
+                    attribCount++;
+                }
+
+                if (attribRendererable && attribRendererable[1] == EGL_OPENGL_ES2_BIT &&
+                        (!attribCaveat || attribCaveat[1] != EGL_NONE)) {
+    
+                    // Insert 2 extra attributes to force-enable MSAA 4x
+                    EGLint aaAttribs[attribCount + 4];
+                    aaAttribs[0] = EGL_SAMPLE_BUFFERS;
+                    aaAttribs[1] = 1;
+                    aaAttribs[2] = EGL_SAMPLES;
+                    aaAttribs[3] = 4;
+
+                    memcpy(&aaAttribs[4], attrib_list, attribCount * sizeof(EGLint));
+
+                    EGLint numConfigAA;
+                    EGLBoolean resAA = cnx->egl.eglChooseConfig(
+                            dp->disp.dpy, aaAttribs, configs, config_size, &numConfigAA);
+
+                    if (resAA == EGL_TRUE && numConfigAA > 0) {
+                        ALOGD("Enabling MSAA 4x");
+                        *num_config = numConfigAA;
+                        return resAA;
+                    }
+                }
+            }
+        }
+
         res = cnx->egl.eglChooseConfig(
                 dp->disp.dpy, attrib_list, configs, config_size, num_config);
     }
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 0d559e7..5a57697 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -38,6 +38,10 @@
 	LOCAL_CFLAGS += -DTARGET_DISABLE_TRIPLE_BUFFERING
 endif
 
+ifneq ($(NUM_FRAMEBUFFER_SURFACE_BUFFERS),)
+  LOCAL_CFLAGS += -DNUM_FRAMEBUFFER_SURFACE_BUFFERS=$(NUM_FRAMEBUFFER_SURFACE_BUFFERS)
+endif
+
 LOCAL_SHARED_LIBRARIES := \
 	libcutils \
 	libdl \
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index 9ada197..6c86a53 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -36,6 +36,10 @@
 #include "DisplayHardware/GraphicBufferAlloc.h"
 #include "DisplayHardware/HWComposer.h"
 
+#ifndef NUM_FRAMEBUFFER_SURFACE_BUFFERS
+#define NUM_FRAMEBUFFER_SURFACE_BUFFERS (2)
+#endif
+
 // ----------------------------------------------------------------------------
 namespace android {
 // ----------------------------------------------------------------------------
@@ -61,7 +65,7 @@
     mBufferQueue->setDefaultBufferFormat(mHwc.getFormat(disp));
     mBufferQueue->setDefaultBufferSize(mHwc.getWidth(disp),  mHwc.getHeight(disp));
     mBufferQueue->setSynchronousMode(true);
-    mBufferQueue->setDefaultMaxBufferCount(NUM_FRAME_BUFFERS);
+    mBufferQueue->setDefaultMaxBufferCount(NUM_FRAMEBUFFER_SURFACE_BUFFERS);
 }
 
 status_t FramebufferSurface::nextBuffer(sp<GraphicBuffer>& outBuffer, sp<Fence>& outFence) {
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
index d64fea7..6336345 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
@@ -22,8 +22,6 @@
 
 #include <gui/ConsumerBase.h>
 
-#define NUM_FRAME_BUFFERS  2
-
 // ---------------------------------------------------------------------------
 namespace android {
 // ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/LayerScreenshot.cpp b/services/surfaceflinger/LayerScreenshot.cpp
index 5c18ebd..0fd744f 100644
--- a/services/surfaceflinger/LayerScreenshot.cpp
+++ b/services/surfaceflinger/LayerScreenshot.cpp
@@ -118,21 +118,22 @@
 
         if (s.alpha == 0xFF) {
             glDisable(GL_BLEND);
+            glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
         } else {
             glEnable(GL_BLEND);
-            glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+            glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+            glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
         }
 
         LayerMesh mesh;
         computeGeometry(hw, &mesh);
 
-        glColor4f(0, 0, 0, alpha);
+        glColor4f(alpha, alpha, alpha, alpha);
 
         glDisable(GL_TEXTURE_EXTERNAL_OES);
         glEnable(GL_TEXTURE_2D);
 
         glBindTexture(GL_TEXTURE_2D, mTextureName);
-        glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
         glMatrixMode(GL_TEXTURE);
         glLoadIdentity();
         glMatrixMode(GL_MODELVIEW);
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 492d1cf..13b2c6b 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -86,7 +86,8 @@
 SurfaceFlinger::SurfaceFlinger()
     :   BnSurfaceComposer(), Thread(false),
         mTransactionFlags(0),
-        mTransationPending(false),
+        mTransactionPending(false),
+        mAnimTransactionPending(false),
         mLayersRemoved(false),
         mRepaintEverything(0),
         mBootTime(systemTime()),
@@ -506,7 +507,7 @@
     //  or when a texture is (asynchronously) destroyed, and for that
     //  we need a valid surface, so it's convenient to use the main display
     //  for that.
-    sp<const DisplayDevice> hw = getDefaultDisplayDevice();
+    sp<const DisplayDevice> hw(getDefaultDisplayDevice());
 
     //  initialize OpenGL ES
     DisplayDevice::makeCurrent(mEGLDisplay, hw, mEGLContext);
@@ -1125,7 +1126,7 @@
                         // Call makeCurrent() on the primary display so we can
                         // be sure that nothing associated with this display
                         // is current.
-                        const sp<const DisplayDevice>& hw(getDefaultDisplayDevice());
+                        const sp<const DisplayDevice> hw(getDefaultDisplayDevice());
                         DisplayDevice::makeCurrent(mEGLDisplay, hw, mEGLContext);
                         mDisplays.removeItem(draw.keyAt(i));
                         getHwComposer().disconnectDisplay(draw[i].type);
@@ -1149,7 +1150,7 @@
                         continue;
                     }
 
-                    const sp<DisplayDevice>& disp(getDisplayDevice(display));
+                    const sp<DisplayDevice> disp(getDisplayDevice(display));
                     if (disp != NULL) {
                         if (state.layerStack != draw[i].layerStack) {
                             disp->setLayerStack(state.layerStack);
@@ -1264,7 +1265,8 @@
     }
 
     mDrawingState = mCurrentState;
-    mTransationPending = false;
+    mTransactionPending = false;
+    mAnimTransactionPending = false;
     mTransactionCV.broadcast();
 }
 
@@ -1665,6 +1667,21 @@
     Mutex::Autolock _l(mStateLock);
     uint32_t transactionFlags = 0;
 
+    if (flags & eAnimation) {
+        // For window updates that are part of an animation we must wait for
+        // previous animation "frames" to be handled.
+        while (mAnimTransactionPending) {
+            status_t err = mTransactionCV.waitRelative(mStateLock, 500 * 1000);
+            if (CC_UNLIKELY(err != NO_ERROR)) {
+                // just in case something goes wrong in SF, return to the
+                // caller after a few hundred microseconds.
+                ALOGW_IF(err == TIMED_OUT, "setTransactionState timed out!");
+                mAnimTransactionPending = false;
+                break;
+            }
+        }
+    }
+
     size_t count = displays.size();
     for (size_t i=0 ; i<count ; i++) {
         const DisplayState& s(displays[i]);
@@ -1685,15 +1702,18 @@
         // if this is a synchronous transaction, wait for it to take effect
         // before returning.
         if (flags & eSynchronous) {
-            mTransationPending = true;
+            mTransactionPending = true;
         }
-        while (mTransationPending) {
+        if (flags & eAnimation) {
+            mAnimTransactionPending = true;
+        }
+        while (mTransactionPending) {
             status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
             if (CC_UNLIKELY(err != NO_ERROR)) {
                 // just in case something goes wrong in SF, return to the
                 // called after a few seconds.
-                ALOGW_IF(err == TIMED_OUT, "closeGlobalTransaction timed out!");
-                mTransationPending = false;
+                ALOGW_IF(err == TIMED_OUT, "setTransactionState timed out!");
+                mTransactionPending = false;
                 break;
             }
         }
@@ -2023,48 +2043,48 @@
 
 void SurfaceFlinger::unblank(const sp<IBinder>& display) {
     class MessageScreenAcquired : public MessageBase {
-        SurfaceFlinger* mFlinger;
-        const sp<DisplayDevice>& mHw;
+        SurfaceFlinger& mFlinger;
+        sp<IBinder> mDisplay;
     public:
-        MessageScreenAcquired(SurfaceFlinger* flinger,
-                const sp<DisplayDevice>& hw) : mFlinger(flinger), mHw(hw) { }
+        MessageScreenAcquired(SurfaceFlinger& flinger,
+                const sp<IBinder>& disp) : mFlinger(flinger), mDisplay(disp) { }
         virtual bool handler() {
-            mFlinger->onScreenAcquired(mHw);
+            const sp<DisplayDevice> hw(mFlinger.getDisplayDevice(mDisplay));
+            if (hw == NULL) {
+                ALOGE("Attempt to unblank null display %p", mDisplay.get());
+            } else if (hw->getDisplayType() >= DisplayDevice::NUM_DISPLAY_TYPES) {
+                ALOGW("Attempt to unblank virtual display");
+            } else {
+                mFlinger.onScreenAcquired(hw);
+            }
             return true;
         }
     };
-    const sp<DisplayDevice>& hw = getDisplayDevice(display);
-    if (hw == NULL) {
-        ALOGE("Attempt to unblank null display %p", display.get());
-    } else if (hw->getDisplayType() >= DisplayDevice::NUM_DISPLAY_TYPES) {
-        ALOGW("Attempt to unblank virtual display");
-    } else {
-        sp<MessageBase> msg = new MessageScreenAcquired(this, hw);
-        postMessageSync(msg);
-    }
+    sp<MessageBase> msg = new MessageScreenAcquired(*this, display);
+    postMessageSync(msg);
 }
 
 void SurfaceFlinger::blank(const sp<IBinder>& display) {
     class MessageScreenReleased : public MessageBase {
-        SurfaceFlinger* mFlinger;
-        const sp<DisplayDevice>& mHw;
+        SurfaceFlinger& mFlinger;
+        sp<IBinder> mDisplay;
     public:
-        MessageScreenReleased(SurfaceFlinger* flinger,
-                const sp<DisplayDevice>& hw) : mFlinger(flinger), mHw(hw) { }
+        MessageScreenReleased(SurfaceFlinger& flinger,
+                const sp<IBinder>& disp) : mFlinger(flinger), mDisplay(disp) { }
         virtual bool handler() {
-            mFlinger->onScreenReleased(mHw);
+            const sp<DisplayDevice> hw(mFlinger.getDisplayDevice(mDisplay));
+            if (hw == NULL) {
+                ALOGE("Attempt to blank null display %p", mDisplay.get());
+            } else if (hw->getDisplayType() >= DisplayDevice::NUM_DISPLAY_TYPES) {
+                ALOGW("Attempt to blank virtual display");
+            } else {
+                mFlinger.onScreenReleased(hw);
+            }
             return true;
         }
     };
-    const sp<DisplayDevice>& hw = getDisplayDevice(display);
-    if (hw == NULL) {
-        ALOGE("Attempt to blank null display %p", display.get());
-    } else if (hw->getDisplayType() >= DisplayDevice::NUM_DISPLAY_TYPES) {
-        ALOGW("Attempt to blank virtual display");
-    } else {
-        sp<MessageBase> msg = new MessageScreenReleased(this, hw);
-        postMessageSync(msg);
-    }
+    sp<MessageBase> msg = new MessageScreenReleased(*this, display);
+    postMessageSync(msg);
 }
 
 // ---------------------------------------------------------------------------
@@ -2339,6 +2359,7 @@
 
 const Vector< sp<LayerBase> >&
 SurfaceFlinger::getLayerSortedByZForHwcDisplay(int disp) {
+    // Note: mStateLock is held here
     return getDisplayDevice( getBuiltInDisplay(disp) )->getVisibleLayersSortedByZ();
 }
 
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 6d36719..de97167 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -327,10 +327,13 @@
     // called when starting, or restarting after system_server death
     void initializeDisplays();
 
+    // NOTE: can only be called from the main thread or with mStateLock held
     sp<const DisplayDevice> getDisplayDevice(const wp<IBinder>& dpy) const {
         return mDisplays.valueFor(dpy);
     }
-    const sp<DisplayDevice>& getDisplayDevice(const wp<IBinder>& dpy) {
+
+    // NOTE: can only be called from the main thread or with mStateLock held
+    sp<DisplayDevice> getDisplayDevice(const wp<IBinder>& dpy) {
         return mDisplays.valueFor(dpy);
     }
 
@@ -398,7 +401,8 @@
     volatile int32_t mTransactionFlags;
     Condition mTransactionCV;
     SortedVector<sp<LayerBase> > mLayerPurgatory;
-    bool mTransationPending;
+    bool mTransactionPending;
+    bool mAnimTransactionPending;
     Vector<sp<LayerBase> > mLayersPendingRemoval;
 
     // protected by mStateLock (but we could use another lock)
@@ -424,6 +428,9 @@
     State mDrawingState;
     bool mVisibleRegionsDirty;
     bool mHwWorkListDirty;
+
+    // this may only be written from the main thread with mStateLock held
+    // it may be read from other threads with mStateLock held
     DefaultKeyedVector< wp<IBinder>, sp<DisplayDevice> > mDisplays;
 
     // don't use a lock for these, we don't care