Merge "Handle supplicant stop correctly"
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 35e53ab..580eb83 100644
--- a/opengl/tests/hwc/hwc_stress.cpp
+++ b/opengl/tests/hwc/hwc_stress.cpp
@@ -202,18 +202,19 @@
 };
 
 // File scope constants
-static const struct {
+static const struct graphicFormat {
     unsigned int format;
     const char *desc;
+    unsigned int wMod, hMod; // Width/height mod this value must equal zero
 } graphicFormat[] = {
-    {HAL_PIXEL_FORMAT_RGBA_8888, "RGBA8888"},
-    {HAL_PIXEL_FORMAT_RGBX_8888, "RGBX8888"},
-    {HAL_PIXEL_FORMAT_RGB_888, "RGB888"},
-    {HAL_PIXEL_FORMAT_RGB_565, "RGB565"},
-    {HAL_PIXEL_FORMAT_BGRA_8888, "BGRA8888"},
-    {HAL_PIXEL_FORMAT_RGBA_5551, "RGBA5551"},
-    {HAL_PIXEL_FORMAT_RGBA_4444, "RGBA4444"},
-    {HAL_PIXEL_FORMAT_YV12, "YV12"},
+    {HAL_PIXEL_FORMAT_RGBA_8888, "RGBA8888", 1, 1},
+    {HAL_PIXEL_FORMAT_RGBX_8888, "RGBX8888", 1, 1},
+    {HAL_PIXEL_FORMAT_RGB_888, "RGB888", 1, 1},
+    {HAL_PIXEL_FORMAT_RGB_565, "RGB565", 1, 1},
+    {HAL_PIXEL_FORMAT_BGRA_8888, "BGRA8888", 1, 1},
+    {HAL_PIXEL_FORMAT_RGBA_5551, "RGBA5551", 1, 1},
+    {HAL_PIXEL_FORMAT_RGBA_4444, "RGBA4444", 1, 1},
+    {HAL_PIXEL_FORMAT_YV12, "YV12", 2, 2},
 };
 const unsigned int blendingOps[] = {
     HWC_BLENDING_NONE,
@@ -478,7 +479,7 @@
             exit(20);
         }
 
-	// Prandomly select a subset of frames to be used by this pass.
+        // Prandomly select a subset of frames to be used by this pass.
         vector <vector <sp<GraphicBuffer> > > selectedFrames;
         selectedFrames = vectorRandSelect(frames, list->numHwLayers);
 
@@ -749,7 +750,6 @@
 {
     unsigned char* buf = NULL;
     status_t err;
-    unsigned int numPixels = gBuf->getWidth() * gBuf->getHeight();
     uint32_t pixel;
 
     // RGB 2 YUV conversion ratios
@@ -835,9 +835,16 @@
         exit(51);
     }
 
-    for (unsigned int n1 = 0; n1 < numPixels; n1++) {
-        memmove(buf, &pixel, attrib->bytes);
-        buf += attrib->bytes;
+    for (unsigned int row = 0; row < gBuf->getHeight(); row++) {
+        for (unsigned int col = 0; col < gBuf->getWidth(); col++) {
+          memmove(buf, &pixel, attrib->bytes);
+          buf += attrib->bytes;
+        }
+        for (unsigned int pad = 0;
+             pad < (gBuf->getStride() - gBuf->getWidth()) * attrib->bytes;
+             pad++) {
+            *buf++ = testRandMod(256);
+        }
     }
 
     err = gBuf->unlock();
@@ -856,14 +863,13 @@
 
     const struct yuvAttrib {
         int format;
-        size_t padWidth;
         bool   planar;
         unsigned int uSubSampX;
         unsigned int uSubSampY;
         unsigned int vSubSampX;
         unsigned int vSubSampY;
     } yuvAttributes[] = {
-        { HAL_PIXEL_FORMAT_YV12, 16, true, 2, 2, 2, 2},
+        { HAL_PIXEL_FORMAT_YV12, true, 2, 2, 2, 2},
     };
 
     const struct yuvAttrib *attrib;
@@ -879,12 +885,6 @@
 
     assert(attrib->planar == true); // So far, only know how to handle planar
 
-    // If needed round width up to pad size
-    if (width % attrib->padWidth) {
-        width += attrib->padWidth - (width % attrib->padWidth);
-    }
-    assert((width % attrib->padWidth) == 0);
-
     err = gBuf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&buf));
     if (err != 0) {
         testPrintE("fillColor lock failed: %d", err);
@@ -892,23 +892,35 @@
     }
 
     // Fill in Y component
-    for (unsigned int x = 0; x < width; x++) {
-        for (unsigned int y = 0; y < height; y++) {
-            *buf++ = (x < gBuf->getWidth()) ? (255 * color.y()) : 0;
+    for (unsigned int row = 0; row < height; row++) {
+        for (unsigned int col = 0; col < width; col++) {
+            *buf++ = 255 * color.y();
+        }
+        for (unsigned int pad = 0; pad < gBuf->getStride() - gBuf->getWidth();
+             pad++) {
+             *buf++ = testRandMod(256);
         }
     }
 
     // Fill in U component
-    for (unsigned int x = 0; x < width; x += attrib->uSubSampX) {
-        for (unsigned int y = 0; y < height; y += attrib->uSubSampY) {
-            *buf++ = (x < gBuf->getWidth()) ? (255 * color.u()) : 0;
+    for (unsigned int row = 0; row < height; row += attrib->uSubSampY) {
+        for (unsigned int col = 0; col < width; col += attrib->uSubSampX) {
+            *buf++ = 255 * color.u();
+        }
+        for (unsigned int pad = 0; pad < gBuf->getStride() - gBuf->getWidth();
+             pad += attrib->uSubSampX) {
+            *buf++ = testRandMod(256);
         }
     }
 
     // Fill in V component
-    for (unsigned int x = 0; x < width; x += attrib->vSubSampX) {
-        for (unsigned int y = 0; y < height; y += attrib->vSubSampY) {
-            *buf++ = (x < gBuf->getWidth()) ? (255 * color.v()) : 0;
+    for (unsigned int row = 0; row < height; row += attrib->vSubSampY) {
+        for (unsigned int col = 0; col < width; col += attrib->vSubSampX) {
+            *buf++ = 255 * color.v();
+        }
+        for (unsigned int pad = 0; pad < gBuf->getStride() - gBuf->getWidth();
+             pad += attrib->vSubSampX) {
+            *buf++ = testRandMod(256);
         }
     }
 
@@ -989,7 +1001,7 @@
     eglQuerySurface(dpy, surface, EGL_HEIGHT, &height);
     checkEglError("eglQuerySurface");
 
-    fprintf(stderr, "Window dimensions: %d x %d", width, height);
+    testPrintI("Window dimensions: %d x %d", width, height);
 
     printGLString("Version", GL_VERSION);
     printGLString("Vendor", GL_VENDOR);
@@ -1017,7 +1029,7 @@
  *
  * Creates an array of graphic buffers, within the global variable
  * named frames.  The graphic buffers are contained within a vector of
- * verctors.  All the graphic buffers in a particular row are of the same
+ * vectors.  All the graphic buffers in a particular row are of the same
  * format and dimension.  Each graphic buffer is uniformly filled with a
  * prandomly selected color.  It is likely that each buffer, even
  * in the same row, will be filled with a unique color.
@@ -1039,11 +1051,22 @@
     for (unsigned int row = 0; row < rows; row++) {
         // All frames within a row have to have the same format and
         // dimensions.  Width and height need to be >= 1.
-        int format = graphicFormat[testRandMod(NUMA(graphicFormat))].format;
+        unsigned int formatIdx = testRandMod(NUMA(graphicFormat));
+        const struct graphicFormat *formatPtr = &graphicFormat[formatIdx];
+        int format = formatPtr->format;
+
+        // Pick width and height, which must be >= 1 and the size
+        // mod the wMod/hMod value must be equal to 0.
         size_t w = (width * maxSizeRatio) * testRandFract();
         size_t h = (height * maxSizeRatio) * testRandFract();
         w = max(1u, w);
         h = max(1u, h);
+        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));
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..5a0f115 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
@@ -868,6 +897,10 @@
     return result;
 }
 
+bool Layer::BufferManager::hasActiveBuffer() const {
+    return mActiveBuffer >= 0;
+}
+
 sp<GraphicBuffer> Layer::BufferManager::detachBuffer(size_t index)
 {
     BufferData* const buffers = mBufferData;
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 30021d3..c367a8d 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -188,6 +188,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);
     }
 }