Merge "Revert "SurfaceTexture: call ConsumerBase::freeBufferLocked"" into jb-mr1-dev
diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp
index 718fe84..18a0c10 100644
--- a/libs/gui/SurfaceTextureClient.cpp
+++ b/libs/gui/SurfaceTextureClient.cpp
@@ -815,12 +815,16 @@
         ALOGW_IF(res, "failed locking buffer (handle = %p)",
                 backBuffer->handle);
 
-        mLockedBuffer = backBuffer;
-        outBuffer->width  = backBuffer->width;
-        outBuffer->height = backBuffer->height;
-        outBuffer->stride = backBuffer->stride;
-        outBuffer->format = backBuffer->format;
-        outBuffer->bits   = vaddr;
+        if (res != 0) {
+            err = INVALID_OPERATION;
+        } else {
+            mLockedBuffer = backBuffer;
+            outBuffer->width  = backBuffer->width;
+            outBuffer->height = backBuffer->height;
+            outBuffer->stride = backBuffer->stride;
+            outBuffer->format = backBuffer->format;
+            outBuffer->bits   = vaddr;
+        }
     }
     return err;
 }
diff --git a/opengl/libs/EGL/egl_cache.cpp b/opengl/libs/EGL/egl_cache.cpp
index c79fb5f..ed2bef3 100644
--- a/opengl/libs/EGL/egl_cache.cpp
+++ b/opengl/libs/EGL/egl_cache.cpp
@@ -241,19 +241,11 @@
         }
 
         size_t fileSize = headerSize + cacheSize;
-        if (ftruncate(fd, fileSize) == -1) {
-            ALOGE("error setting cache file size: %s (%d)", strerror(errno),
-                    errno);
-            close(fd);
-            unlink(fname);
-            return;
-        }
 
-        uint8_t* buf = reinterpret_cast<uint8_t*>(mmap(NULL, fileSize,
-                PROT_WRITE, MAP_SHARED, fd, 0));
-        if (buf == MAP_FAILED) {
-            ALOGE("error mmaping cache file: %s (%d)", strerror(errno),
-                    errno);
+        uint8_t* buf = new uint8_t [fileSize];
+        if (!buf) {
+            ALOGE("error allocating buffer for cache contents: %s (%d)",
+                    strerror(errno), errno);
             close(fd);
             unlink(fname);
             return;
@@ -264,7 +256,7 @@
         if (err != OK) {
             ALOGE("error writing cache contents: %s (%d)", strerror(-err),
                     -err);
-            munmap(buf, fileSize);
+            delete [] buf;
             close(fd);
             unlink(fname);
             return;
@@ -275,7 +267,16 @@
         uint32_t* crc = reinterpret_cast<uint32_t*>(buf + 4);
         *crc = crc32c(buf + headerSize, cacheSize);
 
-        munmap(buf, fileSize);
+        if (write(fd, buf, fileSize) == -1) {
+            ALOGE("error writing cache file: %s (%d)", strerror(errno),
+                    errno);
+            delete [] buf;
+            close(fd);
+            unlink(fname);
+            return;
+        }
+
+        delete [] buf;
         fchmod(fd, S_IRUSR);
         close(fd);
     }
diff --git a/services/surfaceflinger/EventThread.cpp b/services/surfaceflinger/EventThread.cpp
index 9b61fa9..3833f48 100644
--- a/services/surfaceflinger/EventThread.cpp
+++ b/services/surfaceflinger/EventThread.cpp
@@ -36,10 +36,9 @@
 
 EventThread::EventThread(const sp<SurfaceFlinger>& flinger)
     : mFlinger(flinger),
-      mLastVSyncTimestamp(0),
       mVSyncTimestamp(0),
       mUseSoftwareVSync(false),
-      mDeliveredEvents(0),
+      mVSyncCount(0),
       mDebugVsyncEnabled(false) {
 }
 
@@ -116,133 +115,122 @@
 void EventThread::onVSyncReceived(int, nsecs_t timestamp) {
     Mutex::Autolock _l(mLock);
     mVSyncTimestamp = timestamp;
+    mVSyncCount++;
     mCondition.broadcast();
 }
 
 bool EventThread::threadLoop() {
 
     nsecs_t timestamp;
+    size_t vsyncCount;
+    size_t activeEvents;
     DisplayEventReceiver::Event vsync;
-    Vector< wp<EventThread::Connection> > displayEventConnections;
+    Vector< sp<EventThread::Connection> > activeConnections;
 
     do {
         Mutex::Autolock _l(mLock);
-        do {
-            // latch VSYNC event if any
-            timestamp = mVSyncTimestamp;
-            mVSyncTimestamp = 0;
+        // latch VSYNC event if any
+        timestamp = mVSyncTimestamp;
+        mVSyncTimestamp = 0;
 
-            // check if we should be waiting for VSYNC events
-            bool waitForNextVsync = false;
-            size_t count = mDisplayEventConnections.size();
-            for (size_t i=0 ; i<count ; i++) {
-                sp<Connection> connection =
-                        mDisplayEventConnections.itemAt(i).promote();
-                if (connection!=0 && connection->count >= 0) {
+        // check if we should be waiting for VSYNC events
+        activeEvents = 0;
+        bool waitForNextVsync = false;
+        size_t count = mDisplayEventConnections.size();
+        for (size_t i=0 ; i<count ; i++) {
+            sp<Connection> connection(mDisplayEventConnections[i].promote());
+            if (connection != NULL) {
+                activeConnections.add(connection);
+                if (connection->count >= 0) {
                     // at least one continuous mode or active one-shot event
                     waitForNextVsync = true;
+                    activeEvents++;
                     break;
                 }
             }
-
-            if (timestamp) {
-                if (!waitForNextVsync) {
-                    // we received a VSYNC but we have no clients
-                    // don't report it, and disable VSYNC events
-                    disableVSyncLocked();
-                } else {
-                    // report VSYNC event
-                    break;
-                }
-            } else {
-                // never disable VSYNC events immediately, instead
-                // we'll wait to receive the event and we'll
-                // reevaluate whether we need to dispatch it and/or
-                // disable VSYNC events then.
-                if (waitForNextVsync) {
-                    // enable
-                    enableVSyncLocked();
-                }
-            }
-
-            // wait for something to happen
-            if (mUseSoftwareVSync && waitForNextVsync) {
-                // h/w vsync cannot be used (screen is off), so we use
-                // a  timeout instead. it doesn't matter how imprecise this
-                // is, we just need to make sure to serve the clients
-                if (mCondition.waitRelative(mLock, ms2ns(16)) == TIMED_OUT) {
-                    mVSyncTimestamp = systemTime(SYSTEM_TIME_MONOTONIC);
-                }
-            } else {
-                mCondition.wait(mLock);
-            }
-        } while(true);
-
-        // process vsync event
-        mDeliveredEvents++;
-        mLastVSyncTimestamp = timestamp;
-
-        // now see if we still need to report this VSYNC event
-        const size_t count = mDisplayEventConnections.size();
-        for (size_t i=0 ; i<count ; i++) {
-            bool reportVsync = false;
-            sp<Connection> connection =
-                    mDisplayEventConnections.itemAt(i).promote();
-            if (connection == 0)
-                continue;
-
-            const int32_t count = connection->count;
-            if (count >= 1) {
-                if (count==1 || (mDeliveredEvents % count) == 0) {
-                    // continuous event, and time to report it
-                    reportVsync = true;
-                }
-            } else if (count >= -1) {
-                if (count == 0) {
-                    // fired this time around
-                    reportVsync = true;
-                }
-                connection->count--;
-            }
-            if (reportVsync) {
-                displayEventConnections.add(connection);
-            }
         }
-    } while (!displayEventConnections.size());
+
+        if (timestamp) {
+            if (!waitForNextVsync) {
+                // we received a VSYNC but we have no clients
+                // don't report it, and disable VSYNC events
+                disableVSyncLocked();
+            } else {
+                // report VSYNC event
+                break;
+            }
+        } else {
+            // never disable VSYNC events immediately, instead
+            // we'll wait to receive the event and we'll
+            // reevaluate whether we need to dispatch it and/or
+            // disable VSYNC events then.
+            if (waitForNextVsync) {
+                // enable
+                enableVSyncLocked();
+            }
+        }
+
+        // wait for something to happen
+        if (mUseSoftwareVSync && waitForNextVsync) {
+            // h/w vsync cannot be used (screen is off), so we use
+            // a  timeout instead. it doesn't matter how imprecise this
+            // is, we just need to make sure to serve the clients
+            if (mCondition.waitRelative(mLock, ms2ns(16)) == TIMED_OUT) {
+                mVSyncTimestamp = systemTime(SYSTEM_TIME_MONOTONIC);
+                mVSyncCount++;
+            }
+        } else {
+            mCondition.wait(mLock);
+        }
+        vsyncCount = mVSyncCount;
+    } while (!activeConnections.size());
+
+    if (!activeEvents) {
+        // no events to return. start over.
+        // (here we make sure to exit the scope of this function
+        //  so that we release our Connection references)
+        return true;
+    }
 
     // dispatch vsync events to listeners...
     vsync.header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
     vsync.header.timestamp = timestamp;
-    vsync.vsync.count = mDeliveredEvents;
+    vsync.vsync.count = vsyncCount;
 
-    const size_t count = displayEventConnections.size();
+    const size_t count = activeConnections.size();
     for (size_t i=0 ; i<count ; i++) {
-        sp<Connection> conn(displayEventConnections[i].promote());
-        // make sure the connection didn't die
-        if (conn != NULL) {
-            status_t err = conn->postEvent(vsync);
-            if (err == -EAGAIN || err == -EWOULDBLOCK) {
-                // The destination doesn't accept events anymore, it's probably
-                // full. For now, we just drop the events on the floor.
-                // Note that some events cannot be dropped and would have to be
-                // re-sent later. Right-now we don't have the ability to do
-                // this, but it doesn't matter for VSYNC.
-            } else if (err < 0) {
-                // handle any other error on the pipe as fatal. the only
-                // reasonable thing to do is to clean-up this connection.
-                // The most common error we'll get here is -EPIPE.
-                removeDisplayEventConnection(displayEventConnections[i]);
+        const sp<Connection>& conn(activeConnections[i]);
+        // now see if we still need to report this VSYNC event
+        const int32_t vcount = conn->count;
+        if (vcount >= 0) {
+            bool reportVsync = false;
+            if (vcount == 0) {
+                // fired this time around
+                conn->count = -1;
+                reportVsync = true;
+            } else if (vcount == 1 || (vsyncCount % vcount) == 0) {
+                // continuous event, and time to report it
+                reportVsync = true;
             }
-        } else {
-            // somehow the connection is dead, but we still have it in our list
-            // just clean the list.
-            removeDisplayEventConnection(displayEventConnections[i]);
+
+            if (reportVsync) {
+                status_t err = conn->postEvent(vsync);
+                if (err == -EAGAIN || err == -EWOULDBLOCK) {
+                    // The destination doesn't accept events anymore, it's probably
+                    // full. For now, we just drop the events on the floor.
+                    // Note that some events cannot be dropped and would have to be
+                    // re-sent later. Right-now we don't have the ability to do
+                    // this, but it doesn't matter for VSYNC.
+                } else if (err < 0) {
+                    // handle any other error on the pipe as fatal. the only
+                    // reasonable thing to do is to clean-up this connection.
+                    // The most common error we'll get here is -EPIPE.
+                    removeDisplayEventConnection(activeConnections[i]);
+                }
+            }
         }
     }
 
-    // clear all our references without holding mLock
-    displayEventConnections.clear();
-
     return true;
 }
 
@@ -273,7 +261,7 @@
     result.appendFormat("  soft-vsync: %s\n",
             mUseSoftwareVSync?"enabled":"disabled");
     result.appendFormat("  numListeners=%u,\n  events-delivered: %u\n",
-            mDisplayEventConnections.size(), mDeliveredEvents);
+            mDisplayEventConnections.size(), mVSyncCount);
     for (size_t i=0 ; i<mDisplayEventConnections.size() ; i++) {
         sp<Connection> connection =
                 mDisplayEventConnections.itemAt(i).promote();
diff --git a/services/surfaceflinger/EventThread.h b/services/surfaceflinger/EventThread.h
index a71d985..d23b9fa 100644
--- a/services/surfaceflinger/EventThread.h
+++ b/services/surfaceflinger/EventThread.h
@@ -100,12 +100,9 @@
 
     // protected by mLock
     SortedVector< wp<Connection> > mDisplayEventConnections;
-    nsecs_t mLastVSyncTimestamp;
     nsecs_t mVSyncTimestamp;
     bool mUseSoftwareVSync;
-
-    // main thread only
-    size_t mDeliveredEvents;
+    size_t mVSyncCount;
 
     // for debugging
     bool mDebugVsyncEnabled;