merge in jb-release history after reset to jb-dev
diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c
index 880f81f..165f11c 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);
@@ -205,7 +208,7 @@
run_command("FILESYSTEMS & FREE SPACE", 10, SU_PATH, "root", "df", NULL);
- dump_file("PACKAGE SETTINGS", "/data/system/packages.xml");
+ run_command("PACKAGE SETTINGS", 20, SU_PATH, "root", "cat", "/data/system/packages.xml", NULL);
dump_file("PACKAGE UID ERRORS", "/data/system/uiderrors.txt");
run_command("LAST RADIO LOG", 10, "parse_radio_log", "/proc/last_radio_log", NULL);
diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp
index 9b6bc38..a0774cf 100644
--- a/libs/gui/BufferQueue.cpp
+++ b/libs/gui/BufferQueue.cpp
@@ -994,8 +994,6 @@
}
void BufferQueue::freeAllBuffersExceptHeadLocked() {
- ALOGW_IF(!mQueue.isEmpty(),
- "freeAllBuffersExceptCurrentLocked called but mQueue is not empty");
int head = -1;
if (!mQueue.empty()) {
Fifo::iterator front(mQueue.begin());
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp
index 1e58a21..30c0d9b 100644
--- a/libs/gui/SurfaceTexture.cpp
+++ b/libs/gui/SurfaceTexture.cpp
@@ -228,41 +228,46 @@
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);
- mEGLSlots[buf].mEglImage = image;
- if (image == EGL_NO_IMAGE_KHR) {
- // NOTE: if dpy was invalid, createImage() is guaranteed to
- // fail. so we'd end up here.
- return UNKNOWN_ERROR;
+ err = BAD_VALUE;
+ } else {
+ 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
+ // fail. so we'd end up here.
+ err = UNKNOWN_ERROR;
+ }
}
}
- GLint error;
- while ((error = glGetError()) != GL_NO_ERROR) {
- ST_LOGW("updateTexImage: clearing GL error: %#04x", error);
+ if (err == NO_ERROR) {
+ GLint error;
+ while ((error = glGetError()) != GL_NO_ERROR) {
+ ST_LOGW("updateTexImage: clearing GL error: %#04x", error);
+ }
+
+ glBindTexture(mTexTarget, mTexName);
+ glEGLImageTargetTexture2DOES(mTexTarget, (GLeglImageOES)image);
+
+ while ((error = glGetError()) != GL_NO_ERROR) {
+ ST_LOGE("updateTexImage: error binding external texture image %p "
+ "(slot %d): %#04x", image, buf, error);
+ err = UNKNOWN_ERROR;
+ }
+
+ if (err == NO_ERROR) {
+ err = syncForReleaseLocked(dpy);
+ }
}
- glBindTexture(mTexTarget, mTexName);
- glEGLImageTargetTexture2DOES(mTexTarget, (GLeglImageOES)image);
-
- while ((error = glGetError()) != GL_NO_ERROR) {
- ST_LOGE("updateTexImage: error binding external texture image %p "
- "(slot %d): %#04x", image, buf, error);
- err = UNKNOWN_ERROR;
- }
-
- if (err == OK) {
- err = syncForReleaseLocked(dpy);
- }
-
- if (err != OK) {
+ if (err != NO_ERROR) {
// Release the buffer we just acquired. It's not safe to
// release the old buffer, so instead we just drop the new frame.
mBufferQueue->releaseBuffer(buf, dpy, mEGLSlots[buf].mFence);
@@ -277,12 +282,13 @@
// release old buffer
if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
- status_t status = mBufferQueue->releaseBuffer(mCurrentTexture, dpy, mEGLSlots[mCurrentTexture].mFence);
+ status_t status = mBufferQueue->releaseBuffer(mCurrentTexture, dpy,
+ mEGLSlots[mCurrentTexture].mFence);
mEGLSlots[mCurrentTexture].mFence = EGL_NO_SYNC_KHR;
if (status == BufferQueue::STALE_BUFFER_SLOT) {
freeBufferLocked(mCurrentTexture);
- } else if (status != OK) {
+ } else if (status != NO_ERROR) {
ST_LOGE("updateTexImage: released invalid buffer");
err = status;
}
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
diff --git a/libs/utils/VectorImpl.cpp b/libs/utils/VectorImpl.cpp
index 220ae3e..e78faa8 100644
--- a/libs/utils/VectorImpl.cpp
+++ b/libs/utils/VectorImpl.cpp
@@ -382,8 +382,8 @@
}
}
} else {
+ void* array = editArrayImpl();
if (where != mCount) {
- void* array = editArrayImpl();
const void* from = reinterpret_cast<const uint8_t *>(array) + where*mItemSize;
void* to = reinterpret_cast<uint8_t *>(array) + (where+amount)*mItemSize;
_do_move_forward(to, from, mCount - where);
diff --git a/libs/utils/tests/Android.mk b/libs/utils/tests/Android.mk
index 98e4936..0a5b379 100644
--- a/libs/utils/tests/Android.mk
+++ b/libs/utils/tests/Android.mk
@@ -9,6 +9,7 @@
Looper_test.cpp \
String8_test.cpp \
Unicode_test.cpp \
+ Vector_test.cpp \
ZipFileRO_test.cpp
shared_libraries := \
diff --git a/libs/utils/tests/Vector_test.cpp b/libs/utils/tests/Vector_test.cpp
new file mode 100644
index 0000000..d29c054
--- /dev/null
+++ b/libs/utils/tests/Vector_test.cpp
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "Vector_test"
+
+#include <utils/Vector.h>
+#include <cutils/log.h>
+#include <gtest/gtest.h>
+#include <unistd.h>
+
+namespace android {
+
+class VectorTest : public testing::Test {
+protected:
+ virtual void SetUp() {
+ }
+
+ virtual void TearDown() {
+ }
+
+public:
+};
+
+
+TEST_F(VectorTest, CopyOnWrite_CopyAndAddElements) {
+
+ Vector<int> vector;
+ Vector<int> other;
+ vector.setCapacity(8);
+
+ vector.add(1);
+ vector.add(2);
+ vector.add(3);
+
+ EXPECT_EQ(vector.size(), 3);
+
+ // copy the vector
+ other = vector;
+
+ EXPECT_EQ(other.size(), 3);
+
+ // add an element to the first vector
+ vector.add(4);
+
+ // make sure the sizes are correct
+ EXPECT_EQ(vector.size(), 4);
+ EXPECT_EQ(other.size(), 3);
+
+ // add an element to the copy
+ other.add(5);
+
+ // make sure the sizes are correct
+ EXPECT_EQ(vector.size(), 4);
+ EXPECT_EQ(other.size(), 4);
+
+ // make sure the content of both vectors are correct
+ EXPECT_EQ(vector[3], 4);
+ EXPECT_EQ(other[3], 5);
+}
+
+
+} // namespace android
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 35a7fd5..f4779e7 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -62,6 +62,7 @@
#include <private/android_filesystem_config.h>
#include <private/gui/SharedBufferStack.h>
+#include <gui/BitTube.h>
#define EGL_VERSION_HW_ANDROID 0x3143
@@ -1845,6 +1846,35 @@
// ---------------------------------------------------------------------------
+class VSyncWaiter {
+ DisplayEventReceiver::Event buffer[4];
+ sp<Looper> looper;
+ sp<IDisplayEventConnection> events;
+ sp<BitTube> eventTube;
+public:
+ VSyncWaiter(const sp<EventThread>& eventThread) {
+ looper = new Looper(true);
+ events = eventThread->createEventConnection();
+ eventTube = events->getDataChannel();
+ looper->addFd(eventTube->getFd(), 0, ALOOPER_EVENT_INPUT, 0, 0);
+ events->requestNextVsync();
+ }
+
+ void wait() {
+ ssize_t n;
+
+ looper->pollOnce(-1);
+ // we don't handle any errors here, it doesn't matter
+ // and we don't want to take the risk to get stuck.
+
+ // drain the events...
+ while ((n = DisplayEventReceiver::getEvents(
+ eventTube, buffer, 4)) > 0) ;
+
+ events->requestNextVsync();
+ }
+};
+
status_t SurfaceFlinger::electronBeamOffAnimationImplLocked()
{
// get screen geometry
@@ -1937,6 +1967,8 @@
}
};
+ VSyncWaiter vsync(mEventThread);
+
// the full animation is 24 frames
char value[PROPERTY_VALUE_MAX];
property_get("debug.sf.electron_frames", value, "24");
@@ -1963,6 +1995,9 @@
const float vg = itg(i);
const float vb = itb(i);
+ // wait for vsync
+ vsync.wait();
+
// clear screen
glColorMask(1,1,1,1);
glClear(GL_COLOR_BUFFER_BIT);
@@ -1998,6 +2033,10 @@
for (int i=0 ; i<nbFrames ; i++) {
const float v = itg(i);
hverts(vtx, v);
+
+ // wait for vsync
+ vsync.wait();
+
glClear(GL_COLOR_BUFFER_BIT);
glColor4f(1-v, 1-v, 1-v, 1);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
@@ -2095,6 +2134,8 @@
}
};
+ VSyncWaiter vsync(mEventThread);
+
// the full animation is 12 frames
int nbFrames = 8;
s_curve_interpolator itr(nbFrames, 7.5f);
@@ -2108,6 +2149,10 @@
for (int i=nbFrames-1 ; i>=0 ; i--) {
const float v = itg(i);
hverts(vtx, v);
+
+ // wait for vsync
+ vsync.wait();
+
glClear(GL_COLOR_BUFFER_BIT);
glColor4f(1-v, 1-v, 1-v, 1);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
@@ -2124,6 +2169,9 @@
const float vg = itg(i);
const float vb = itb(i);
+ // wait for vsync
+ vsync.wait();
+
// clear screen
glColorMask(1,1,1,1);
glClear(GL_COLOR_BUFFER_BIT);