Merge "Correct an error code to pass CTS."
diff --git a/include/surfaceflinger/Surface.h b/include/surfaceflinger/Surface.h
index cef439c..2df8ca3 100644
--- a/include/surfaceflinger/Surface.h
+++ b/include/surfaceflinger/Surface.h
@@ -249,7 +249,7 @@
             uint32_t *pWidth, uint32_t *pHeight,
             uint32_t *pFormat, uint32_t *pUsage) const;
 
-    static void cleanCachedSurfaces();
+    static void cleanCachedSurfacesLocked();
 
     class BufferInfo {
         uint32_t mWidth;
diff --git a/include/utils/CallStack.h b/include/utils/CallStack.h
index c2c8ce5..8817120 100644
--- a/include/utils/CallStack.h
+++ b/include/utils/CallStack.h
@@ -50,7 +50,7 @@
     
     void clear();
 
-    void update(int32_t ignoreDepth=0, int32_t maxDepth=MAX_DEPTH);
+    void update(int32_t ignoreDepth=1, int32_t maxDepth=MAX_DEPTH);
 
     // Dump a stack trace to the log
     void dump(const char* prefix = 0) const;
diff --git a/libs/surfaceflinger_client/Surface.cpp b/libs/surfaceflinger_client/Surface.cpp
index 9467a4c..aa0c2e8 100644
--- a/libs/surfaceflinger_client/Surface.cpp
+++ b/libs/surfaceflinger_client/Surface.cpp
@@ -384,7 +384,7 @@
 
 
 Mutex Surface::sCachedSurfacesLock;
-DefaultKeyedVector<wp<IBinder>, wp<Surface> > Surface::sCachedSurfaces(wp<Surface>(0));
+DefaultKeyedVector<wp<IBinder>, wp<Surface> > Surface::sCachedSurfaces;
 
 sp<Surface> Surface::readFromParcel(const Parcel& data) {
     Mutex::Autolock _l(sCachedSurfacesLock);
@@ -397,13 +397,13 @@
     if (surface->mSurface == 0) {
       surface = 0;
     }
-    cleanCachedSurfaces();
+    cleanCachedSurfacesLocked();
     return surface;
 }
 
 // Remove the stale entries from the surface cache.  This should only be called
 // with sCachedSurfacesLock held.
-void Surface::cleanCachedSurfaces() {
+void Surface::cleanCachedSurfacesLocked() {
     for (int i = sCachedSurfaces.size()-1; i >= 0; --i) {
         wp<Surface> s(sCachedSurfaces.valueAt(i));
         if (s == 0 || s.promote() == 0) {
@@ -489,6 +489,9 @@
         LOGE("[Surface] using an invalid surface, "
                 "identity=%u should be %d",
                 mIdentity, identity);
+        CallStack stack;
+        stack.update();
+        stack.dump("Surface");
         return NO_INIT;
     }
 
@@ -497,6 +500,9 @@
     if (err != NO_ERROR) {
         LOGE("surface (identity=%u) is invalid, err=%d (%s)",
                 mIdentity, err, strerror(-err));
+        CallStack stack;
+        stack.update();
+        stack.dump("Surface");
         return err;
     }
 
diff --git a/opengl/tests/hwc/hwc_stress.cpp b/opengl/tests/hwc/hwc_stress.cpp
index d41b074..580eb83 100644
--- a/opengl/tests/hwc/hwc_stress.cpp
+++ b/opengl/tests/hwc/hwc_stress.cpp
@@ -1061,16 +1061,16 @@
         size_t h = (height * maxSizeRatio) * testRandFract();
         w = max(1u, w);
         h = max(1u, h);
-        if (verbose) {
-            testPrintI("  frame %u width: %u height: %u format: %u %s",
-                       row, w, h, format, graphicFormat2str(format));
-        }
         if ((w % formatPtr->wMod) != 0) {
             w += formatPtr->wMod - (w % formatPtr->wMod);
         }
         if ((h % formatPtr->hMod) != 0) {
             h += formatPtr->hMod - (h % formatPtr->hMod);
         }
+        if (verbose) {
+            testPrintI("  frame %u width: %u height: %u format: %u %s",
+                       row, w, h, format, graphicFormat2str(format));
+        }
 
         size_t cols = testRandMod((maxCols + 1) - minCols) + minCols;
         frames[row].resize(cols);
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 74d1ac9..8a00a2e 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -35,7 +35,6 @@
 
 LOCAL_SHARED_LIBRARIES := \
 	libcutils \
-	libpixelflinger \
 	libhardware \
 	libutils \
 	libEGL \
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 80aef5f..fde68f6 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -83,8 +83,28 @@
             sharedClient, token, mBufferManager.getDefaultBufferCount(),
             getIdentity());
 
-    status_t err = mUserClientRef.setToken(userClient, lcblk, token);
 
+    sp<UserClient> ourClient(mUserClientRef.getClient());
+
+    /*
+     *  Here it is guaranteed that userClient != ourClient
+     *  (see UserClient::getTokenForSurface()).
+     *
+     *  We release the token used by this surface in ourClient below.
+     *  This should be safe to do so now, since this layer won't be attached
+     *  to this client, it should be okay to reuse that id.
+     *
+     *  If this causes problems, an other solution would be to keep a list
+     *  of all the {UserClient, token} ever used and release them when the
+     *  Layer is destroyed.
+     *
+     */
+
+    if (ourClient != 0) {
+        ourClient->detachLayer(this);
+    }
+
+    status_t err = mUserClientRef.setToken(userClient, lcblk, token);
     LOGE_IF(err != NO_ERROR,
             "ClientRef::setToken(%p, %p, %u) failed",
             userClient.get(), lcblk.get(), token);
@@ -226,9 +246,10 @@
 void Layer::setPerFrameData(hwc_layer_t* hwcl) {
     sp<GraphicBuffer> buffer(mBufferManager.getActiveBuffer());
     if (buffer == NULL) {
-        // this situation can happen if we ran out of memory for instance.
-        // not much we can do. continue to use whatever texture was bound
-        // to this context.
+        // this can happen if the client never drew into this layer yet,
+        // or if we ran out of memory. In that case, don't let
+        // HWC handle it.
+        hwcl->flags |= HWC_SKIP_LAYER;
         hwcl->handle = NULL;
         return;
     }
@@ -561,12 +582,20 @@
     }
 
     // we retired a buffer, which becomes the new front buffer
+
+    const bool noActiveBuffer = !mBufferManager.hasActiveBuffer();
     if (mBufferManager.setActiveBufferIndex(buf) < NO_ERROR) {
         LOGE("retireAndLock() buffer index (%d) out of range", int(buf));
         mPostedDirtyRegion.clear();
         return;
     }
 
+    if (noActiveBuffer) {
+        // we didn't have an active buffer, we need to recompute
+        // our visible region
+        recomputeVisibleRegions = true;
+    }
+
     sp<GraphicBuffer> newFrontBuffer(getBuffer(buf));
     if (newFrontBuffer != NULL) {
         // get the dirty region
@@ -775,7 +804,7 @@
 
 Layer::BufferManager::BufferManager(TextureManager& tm)
     : mNumBuffers(NUM_BUFFERS), mTextureManager(tm),
-      mActiveBuffer(-1), mFailover(false)
+      mActiveBufferIndex(-1), mFailover(false)
 {
 }
 
@@ -790,10 +819,10 @@
 
     if (size < mNumBuffers) {
         // Move the active texture into slot 0
-        BufferData activeBufferData = mBufferData[mActiveBuffer];
-        mBufferData[mActiveBuffer] = mBufferData[0];
+        BufferData activeBufferData = mBufferData[mActiveBufferIndex];
+        mBufferData[mActiveBufferIndex] = mBufferData[0];
         mBufferData[0] = activeBufferData;
-        mActiveBuffer = 0;
+        mActiveBufferIndex = 0;
 
         // Free the buffers that are no longer needed.
         for (size_t i = size; i < mNumBuffers; i++) {
@@ -839,33 +868,33 @@
 }
 
 status_t Layer::BufferManager::setActiveBufferIndex(size_t index) {
-    mActiveBuffer = index;
+    BufferData const * const buffers = mBufferData;
+    Mutex::Autolock _l(mLock);
+    mActiveBuffer = buffers[index].buffer;
+    mActiveBufferIndex = index;
     return NO_ERROR;
 }
 
 size_t Layer::BufferManager::getActiveBufferIndex() const {
-    return mActiveBuffer;
+    return mActiveBufferIndex;
 }
 
 Texture Layer::BufferManager::getActiveTexture() const {
     Texture res;
-    if (mFailover || mActiveBuffer<0) {
+    if (mFailover || mActiveBufferIndex<0) {
         res = mFailoverTexture;
     } else {
-        static_cast<Image&>(res) = mBufferData[mActiveBuffer].texture;
+        static_cast<Image&>(res) = mBufferData[mActiveBufferIndex].texture;
     }
     return res;
 }
 
 sp<GraphicBuffer> Layer::BufferManager::getActiveBuffer() const {
-    sp<GraphicBuffer> result;
-    const ssize_t activeBuffer = mActiveBuffer;
-    if (activeBuffer >= 0) {
-        BufferData const * const buffers = mBufferData;
-        Mutex::Autolock _l(mLock);
-        result = buffers[activeBuffer].buffer;
-    }
-    return result;
+    return mActiveBuffer;
+}
+
+bool Layer::BufferManager::hasActiveBuffer() const {
+    return mActiveBufferIndex >= 0;
 }
 
 sp<GraphicBuffer> Layer::BufferManager::detachBuffer(size_t index)
@@ -910,7 +939,7 @@
         const sp<GraphicBuffer>& buffer)
 {
     status_t err = NO_INIT;
-    ssize_t index = mActiveBuffer;
+    ssize_t index = mActiveBufferIndex;
     if (index >= 0) {
         if (!mFailover) {
             Image& texture(mBufferData[index].texture);
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 30021d3..5444d2f 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -164,7 +164,8 @@
         size_t              mNumBuffers;
         Texture             mFailoverTexture;
         TextureManager&     mTextureManager;
-        ssize_t             mActiveBuffer;
+        ssize_t             mActiveBufferIndex;
+        sp<GraphicBuffer>   mActiveBuffer;
         bool                mFailover;
         static status_t destroyTexture(Image* tex, EGLDisplay dpy);
 
@@ -188,6 +189,8 @@
         size_t getActiveBufferIndex() const;
         // return the active buffer
         sp<GraphicBuffer> getActiveBuffer() const;
+        // return wether we have an active buffer
+        bool hasActiveBuffer() const;
         // return the active texture (or fail-over)
         Texture getActiveTexture() const;
         // frees resources associated with all buffers
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 61d08aa..a6b1422 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1023,6 +1023,8 @@
             glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
         }
         glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+        glLoadIdentity();
+        glMatrixMode(GL_MODELVIEW);
     }
 }