Merge "fix a corruption in Vector<> when adding new items" into jb-dev
diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c
index 880f81f..2bcda11 100644
--- a/cmds/dumpstate/dumpstate.c
+++ b/cmds/dumpstate/dumpstate.c
@@ -144,6 +144,7 @@
 
     dump_file("NETWORK DEV INFO", "/proc/net/dev");
     dump_file("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all");
+    dump_file("QTAGUID NETWORK INTERFACES INFO (xt)", "/proc/net/xt_qtaguid/iface_stat_fmt");
     dump_file("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl");
     dump_file("QTAGUID STATS INFO", "/proc/net/xt_qtaguid/stats");
 
@@ -176,8 +177,10 @@
     dump_file("ARP CACHE", "/proc/net/arp");
     run_command("IPTABLES", 10, SU_PATH, "root", "iptables", "-L", "-nvx", NULL);
     run_command("IP6TABLES", 10, SU_PATH, "root", "ip6tables", "-L", "-nvx", NULL);
-    run_command("IPTABLE NAT", 10, SU_PATH, "root", "iptables", "-t", "nat", "-L", "-n", NULL);
-    run_command("IPT6ABLE NAT", 10, SU_PATH, "root", "ip6tables", "-t", "nat", "-L", "-n", NULL);
+    run_command("IPTABLE NAT", 10, SU_PATH, "root", "iptables", "-t", "nat", "-L", "-nvx", NULL);
+    /* no ip6 nat */
+    run_command("IPTABLE RAW", 10, SU_PATH, "root", "iptables", "-t", "raw", "-L", "-nvx", NULL);
+    run_command("IP6TABLE RAW", 10, SU_PATH, "root", "ip6tables", "-t", "raw", "-L", "-nvx", NULL);
 
     run_command("WIFI NETWORKS", 20,
             SU_PATH, "root", "wpa_cli", "list_networks", NULL);
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp
index 1e58a21..feaf07a 100644
--- a/libs/gui/SurfaceTexture.cpp
+++ b/libs/gui/SurfaceTexture.cpp
@@ -228,14 +228,16 @@
             mEGLSlots[buf].mGraphicBuffer = item.mGraphicBuffer;
         }
 
-        // Update the GL texture object.
+        // Update the GL texture object. We may have to do this even when
+        // item.mGraphicBuffer == NULL, if we destroyed the EGLImage when
+        // detaching from a context but the buffer has not been re-allocated.
         EGLImageKHR image = mEGLSlots[buf].mEglImage;
         if (image == EGL_NO_IMAGE_KHR) {
-            if (item.mGraphicBuffer == 0) {
+            if (mEGLSlots[buf].mGraphicBuffer == NULL) {
                 ST_LOGE("updateTexImage: buffer at slot %d is null", buf);
                 return BAD_VALUE;
             }
-            image = createImage(dpy, item.mGraphicBuffer);
+            image = createImage(dpy, mEGLSlots[buf].mGraphicBuffer);
             mEGLSlots[buf].mEglImage = image;
             if (image == EGL_NO_IMAGE_KHR) {
                 // NOTE: if dpy was invalid, createImage() is guaranteed to
diff --git a/libs/gui/tests/SurfaceTexture_test.cpp b/libs/gui/tests/SurfaceTexture_test.cpp
index d708f6d..078c17b 100644
--- a/libs/gui/tests/SurfaceTexture_test.cpp
+++ b/libs/gui/tests/SurfaceTexture_test.cpp
@@ -2577,4 +2577,32 @@
     ASSERT_TRUE(checkPixel( 0,  0,  35,  35,  35,  35));
 }
 
+TEST_F(SurfaceTextureMultiContextGLTest,
+        UpdateTexImageSucceedsForBufferConsumedBeforeDetach) {
+    ASSERT_EQ(NO_ERROR, mST->setSynchronousMode(true));
+    ASSERT_EQ(NO_ERROR, mST->setBufferCountServer(2));
+
+    // produce two frames and consume them both on the primary context
+    ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
+    mFW->waitForFrame();
+    ASSERT_EQ(OK, mST->updateTexImage());
+
+    ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
+    mFW->waitForFrame();
+    ASSERT_EQ(OK, mST->updateTexImage());
+
+    // produce one more frame
+    ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
+
+    // Detach from the primary context and attach to the secondary context
+    ASSERT_EQ(OK, mST->detachFromContext());
+    ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
+            mSecondEglContext));
+    ASSERT_EQ(OK, mST->attachToContext(SECOND_TEX_ID));
+
+    // Consume final frame on secondary context
+    mFW->waitForFrame();
+    ASSERT_EQ(OK, mST->updateTexImage());
+}
+
 } // namespace android