Merge "Caliper benchmarks for Parcel."
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index b578a6c..96cef2c 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -20,7 +20,6 @@
 
 #include <binder/Binder.h>
 #include <binder/BpBinder.h>
-#include <cutils/sched_policy.h>
 #include <utils/Debug.h>
 #include <utils/Log.h>
 #include <utils/TextOutput.h>
diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp
index d761680..25a4c22 100644
--- a/libs/gui/BufferQueue.cpp
+++ b/libs/gui/BufferQueue.cpp
@@ -56,6 +56,11 @@
 #define ST_LOGW(x, ...) ALOGW("[%s] "x, mConsumerName.string(), ##__VA_ARGS__)
 #define ST_LOGE(x, ...) ALOGE("[%s] "x, mConsumerName.string(), ##__VA_ARGS__)
 
+#define ATRACE_BUFFER_INDEX(index)                                            \
+    char ___traceBuf[1024];                                                   \
+    snprintf(___traceBuf, 1024, "%s: %d", mConsumerName.string(), (index));   \
+    android::ScopedTrace ___bufTracer(ATRACE_TAG, ___traceBuf);
+
 namespace android {
 
 // Get an ID that's unique within this process.
@@ -387,6 +392,8 @@
         const int buf = found;
         *outBuf = found;
 
+        ATRACE_BUFFER_INDEX(buf);
+
         const bool useDefaultSize = !w && !h;
         if (useDefaultSize) {
             // use the default size
@@ -497,6 +504,8 @@
 status_t BufferQueue::queueBuffer(int buf, int64_t timestamp,
         uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) {
     ATRACE_CALL();
+    ATRACE_BUFFER_INDEX(buf);
+
     ST_LOGV("queueBuffer: slot=%d time=%lld", buf, timestamp);
 
     sp<FrameAvailableListener> listener;
@@ -810,6 +819,7 @@
 }
 
 status_t BufferQueue::acquire(BufferItem *buffer) {
+    ATRACE_CALL();
     Mutex::Autolock _l(mMutex);
     // check if queue is empty
     // In asynchronous mode the list is guaranteed to be one buffer
@@ -818,6 +828,8 @@
         Fifo::iterator front(mQueue.begin());
         int buf = *front;
 
+        ATRACE_BUFFER_INDEX(buf);
+
         if (mSlots[buf].mAcquireCalled) {
             buffer->mGraphicBuffer = NULL;
         }
@@ -828,6 +840,7 @@
         buffer->mTransform = mSlots[buf].mTransform;
         buffer->mScalingMode = mSlots[buf].mScalingMode;
         buffer->mFrameNumber = mSlots[buf].mFrameNumber;
+        buffer->mTimestamp = mSlots[buf].mTimestamp;
         buffer->mBuf = buf;
         mSlots[buf].mAcquireCalled = true;
 
@@ -845,6 +858,9 @@
 
 status_t BufferQueue::releaseBuffer(int buf, EGLDisplay display,
         EGLSyncKHR fence) {
+    ATRACE_CALL();
+    ATRACE_BUFFER_INDEX(buf);
+
     Mutex::Autolock _l(mMutex);
 
     if (buf == INVALID_BUFFER_SLOT) {
diff --git a/opengl/libs/GLES_trace/dev.make b/opengl/libs/GLES_trace/dev.make
index 1d89999..a46260c 100644
--- a/opengl/libs/GLES_trace/dev.make
+++ b/opengl/libs/GLES_trace/dev.make
@@ -6,10 +6,9 @@
 	aprotoc --cpp_out=src --java_out=java gltrace.proto
 	mv src/gltrace.pb.cc src/gltrace.pb.cpp
 
-# NOTE: $OUT should be defined in the shell by doing a "lunch <config>"
-# push updated files to device
-push:
-	adb push $(OUT)/system/lib/libGLESv2.so /system/lib/
-	adb push $(OUT)/system/lib/libGLESv1_CM.so /system/lib/
-	adb push $(OUT)/system/lib/libGLES_trace.so /system/lib/
-	adb push $(OUT)/system/lib/libEGL.so /system/lib/
+sync:
+	adb root
+	adb remount
+	adb shell stop
+	adb sync
+	adb shell start
diff --git a/opengl/libs/GLES_trace/gltrace.proto b/opengl/libs/GLES_trace/gltrace.proto
index 2893e6e..bbf3554 100644
--- a/opengl/libs/GLES_trace/gltrace.proto
+++ b/opengl/libs/GLES_trace/gltrace.proto
@@ -510,7 +510,7 @@
         eglGetSystemTimeNV = 2045;
 
         invalid = 3000;
-        frameBufferContents = 3001;
+        glVertexAttribPointerData = 3001;
     }
 
     // A GL call's return data and arguments are formatted into this DataType
diff --git a/opengl/libs/GLES_trace/src/gltrace.pb.cpp b/opengl/libs/GLES_trace/src/gltrace.pb.cpp
index d5f8180..d587c49 100644
--- a/opengl/libs/GLES_trace/src/gltrace.pb.cpp
+++ b/opengl/libs/GLES_trace/src/gltrace.pb.cpp
@@ -1018,7 +1018,7 @@
 const GLMessage_Function GLMessage::eglGetSystemTimeFrequencyNV;
 const GLMessage_Function GLMessage::eglGetSystemTimeNV;
 const GLMessage_Function GLMessage::invalid;
-const GLMessage_Function GLMessage::frameBufferContents;
+const GLMessage_Function GLMessage::glVertexAttribPointerData;
 const GLMessage_Function GLMessage::Function_MIN;
 const GLMessage_Function GLMessage::Function_MAX;
 const int GLMessage::Function_ARRAYSIZE;
diff --git a/opengl/libs/GLES_trace/src/gltrace.pb.h b/opengl/libs/GLES_trace/src/gltrace.pb.h
index a4fcbd3..0901be7 100644
--- a/opengl/libs/GLES_trace/src/gltrace.pb.h
+++ b/opengl/libs/GLES_trace/src/gltrace.pb.h
@@ -535,11 +535,11 @@
   GLMessage_Function_eglGetSystemTimeFrequencyNV = 2044,
   GLMessage_Function_eglGetSystemTimeNV = 2045,
   GLMessage_Function_invalid = 3000,
-  GLMessage_Function_frameBufferContents = 3001
+  GLMessage_Function_glVertexAttribPointerData = 3001
 };
 bool GLMessage_Function_IsValid(int value);
 const GLMessage_Function GLMessage_Function_Function_MIN = GLMessage_Function_glActiveTexture;
-const GLMessage_Function GLMessage_Function_Function_MAX = GLMessage_Function_frameBufferContents;
+const GLMessage_Function GLMessage_Function_Function_MAX = GLMessage_Function_glVertexAttribPointerData;
 const int GLMessage_Function_Function_ARRAYSIZE = GLMessage_Function_Function_MAX + 1;
 
 // ===================================================================
@@ -1351,7 +1351,7 @@
   static const Function eglGetSystemTimeFrequencyNV = GLMessage_Function_eglGetSystemTimeFrequencyNV;
   static const Function eglGetSystemTimeNV = GLMessage_Function_eglGetSystemTimeNV;
   static const Function invalid = GLMessage_Function_invalid;
-  static const Function frameBufferContents = GLMessage_Function_frameBufferContents;
+  static const Function glVertexAttribPointerData = GLMessage_Function_glVertexAttribPointerData;
   static inline bool Function_IsValid(int value) {
     return GLMessage_Function_IsValid(value);
   }
diff --git a/opengl/libs/GLES_trace/src/gltrace_context.cpp b/opengl/libs/GLES_trace/src/gltrace_context.cpp
index 65b7662..45dbb43 100644
--- a/opengl/libs/GLES_trace/src/gltrace_context.cpp
+++ b/opengl/libs/GLES_trace/src/gltrace_context.cpp
@@ -129,13 +129,14 @@
     return mPerContextState[c];
 }
 
-GLTraceContext::GLTraceContext(int id, GLTraceState *state, BufferedOutputStream *stream) {
-    mId = id;
-    mState = state;
-
+GLTraceContext::GLTraceContext(int id, GLTraceState *state, BufferedOutputStream *stream) :
+    mId(id),
+    mState(state),
+    mBufferedOutputStream(stream),
+    mElementArrayBuffers(DefaultKeyedVector<GLuint, ElementArrayBuffer*>(NULL))
+{
     fbcontents = fbcompressed = NULL;
     fbcontentsSize = 0;
-    mBufferedOutputStream = stream;
 }
 
 int GLTraceContext::getId() {
@@ -208,5 +209,74 @@
     }
 }
 
+void GLTraceContext::bindBuffer(GLuint bufferId, GLvoid *data, GLsizeiptr size) {
+    // free previously bound buffer if any
+    ElementArrayBuffer *oldBuffer = mElementArrayBuffers.valueFor(bufferId);
+    if (oldBuffer != NULL) {
+        delete oldBuffer;
+    }
+
+    mElementArrayBuffers.add(bufferId, new ElementArrayBuffer(data, size));
+}
+
+void GLTraceContext::getBuffer(GLuint bufferId, GLvoid **data, GLsizeiptr *size) {
+    ElementArrayBuffer *buffer = mElementArrayBuffers.valueFor(bufferId);
+    if (buffer == NULL) {
+        *data = NULL;
+        *size = 0;
+    } else {
+        *data = buffer->getBuffer();
+        *size = buffer->getSize();
+    }
+}
+
+void GLTraceContext::updateBufferSubData(GLuint bufferId, GLintptr offset, GLvoid *data,
+                                                            GLsizeiptr size) {
+    ElementArrayBuffer *buffer = mElementArrayBuffers.valueFor(bufferId);
+    if (buffer != NULL) {
+        buffer->updateSubBuffer(offset, data, size);
+    }
+}
+
+void GLTraceContext::deleteBuffer(GLuint bufferId) {
+    ElementArrayBuffer *buffer = mElementArrayBuffers.valueFor(bufferId);
+    if (buffer != NULL) {
+        delete buffer;
+        mElementArrayBuffers.removeItem(bufferId);
+    }
+}
+
+ElementArrayBuffer::ElementArrayBuffer(GLvoid *buf, GLsizeiptr size) {
+    mBuf = malloc(size);
+    mSize = size;
+
+    if (buf != NULL) {
+        memcpy(mBuf, buf, size);
+    }
+}
+
+ElementArrayBuffer::~ElementArrayBuffer() {
+    if (mBuf != NULL) {
+        free(mBuf);
+        mSize = 0;
+    }
+
+    mBuf = NULL;
+}
+
+void ElementArrayBuffer::updateSubBuffer(GLintptr offset, const GLvoid* data, GLsizeiptr size) {
+    if (offset + size <= mSize) {
+        memcpy((char*)mBuf + offset, data, size);
+    }
+}
+
+GLvoid *ElementArrayBuffer::getBuffer() {
+    return mBuf;
+}
+
+GLsizeiptr ElementArrayBuffer::getSize() {
+    return mSize;
+}
+
 }; // namespace gltrace
 }; // namespace android
diff --git a/opengl/libs/GLES_trace/src/gltrace_context.h b/opengl/libs/GLES_trace/src/gltrace_context.h
index 129116a..323cfdc 100644
--- a/opengl/libs/GLES_trace/src/gltrace_context.h
+++ b/opengl/libs/GLES_trace/src/gltrace_context.h
@@ -19,6 +19,7 @@
 
 #include <map>
 #include <pthread.h>
+#include <utils/KeyedVector.h>
 
 #include "hooks.h"
 #include "gltrace_transport.h"
@@ -32,6 +33,20 @@
 
 class GLTraceState;
 
+class ElementArrayBuffer {
+    GLvoid *mBuf;
+    GLsizeiptr mSize;
+
+public:
+    ElementArrayBuffer():mBuf(NULL), mSize(0) {}
+    ElementArrayBuffer(GLvoid *buf, GLsizeiptr size);
+    ~ElementArrayBuffer();
+
+    void updateSubBuffer(GLintptr offset, const GLvoid* data, GLsizeiptr size);
+    GLvoid *getBuffer();
+    GLsizeiptr getSize();
+};
+
 /** GL Trace Context info associated with each EGLContext */
 class GLTraceContext {
     int mId;                    /* unique context id */
@@ -43,6 +58,9 @@
 
     BufferedOutputStream *mBufferedOutputStream; /* stream where trace info is sent */
 
+    /* list of element array buffers in use. */
+    DefaultKeyedVector<GLuint, ElementArrayBuffer*> mElementArrayBuffers;
+
     void resizeFBMemory(unsigned minSize);
 public:
     gl_hooks_t *hooks;
@@ -53,6 +71,13 @@
     void getCompressedFB(void **fb, unsigned *fbsize,
                             unsigned *fbwidth, unsigned *fbheight,
                             FBBinding fbToRead);
+
+    // Methods to work with element array buffers
+    void bindBuffer(GLuint bufferId, GLvoid *data, GLsizeiptr size);
+    void getBuffer(GLuint bufferId, GLvoid **data, GLsizeiptr *size);
+    void updateBufferSubData(GLuint bufferId, GLintptr offset, GLvoid *data, GLsizeiptr size);
+    void deleteBuffer(GLuint bufferId);
+
     void traceGLMessage(GLMessage *msg);
 };
 
diff --git a/opengl/libs/GLES_trace/src/gltrace_fixup.cpp b/opengl/libs/GLES_trace/src/gltrace_fixup.cpp
index c69ba5e..3597b26 100644
--- a/opengl/libs/GLES_trace/src/gltrace_fixup.cpp
+++ b/opengl/libs/GLES_trace/src/gltrace_fixup.cpp
@@ -193,7 +193,7 @@
                         GLint border,
                         GLenum format,
                         GLenum type,
-                        const GLvoid *data); 
+                        const GLvoid *data);
     */
     int widthIndex = 3;
     int heightIndex = 4;
@@ -218,7 +218,7 @@
 }
 
 void fixup_glShaderSource(GLMessage *glmsg, void *pointersToFixup[]) {
-    /* void glShaderSource(GLuint shader, GLsizei count, const GLchar** string, 
+    /* void glShaderSource(GLuint shader, GLsizei count, const GLchar** string,
                                     const GLint* length) */
     GLMessage_DataType arg_count  = glmsg->args(1);
     GLMessage_DataType arg_lenp   = glmsg->args(3);
@@ -256,33 +256,13 @@
 }
 
 void fixup_glUniformMatrixGeneric(int matrixSize, GLMessage *glmsg, void *pointersToFixup[]) {
-    /* void glUniformMatrix?fv(GLint location, GLsizei count, GLboolean transpose, 
+    /* void glUniformMatrix?fv(GLint location, GLsizei count, GLboolean transpose,
                                                                 const GLfloat* value) */
     GLMessage_DataType arg_count  = glmsg->args(1);
     int n_matrices = arg_count.intvalue(0);
     fixup_glUniformGeneric(3, matrixSize * matrixSize * n_matrices, glmsg, pointersToFixup[0]);
 }
 
-void fixup_glBufferData(int sizeIndex, int dataIndex, GLMessage *glmsg, void *pointersToFixup[]) {
-    /* void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) */
-    /* void glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) */
-    GLsizeiptr size = glmsg->args(sizeIndex).intvalue(0);
-
-    GLMessage_DataType *arg_datap = glmsg->mutable_args(dataIndex);
-    GLvoid *datap = (GLvoid *) pointersToFixup[0];
-
-    if (datap == NULL) {
-        // glBufferData can be called with a NULL data pointer
-        return;
-    }
-
-    arg_datap->set_type(GLMessage::DataType::VOID);
-    arg_datap->set_isarray(true);
-    arg_datap->clear_intvalue();
-
-    arg_datap->add_rawbytes(datap, size);
-}
-
 void fixup_glGenGeneric(GLMessage *glmsg, void *pointersToFixup[]) {
     /* void glGen*(GLsizei n, GLuint * buffers); */
     GLMessage_DataType arg_n  = glmsg->args(0);
@@ -375,7 +355,7 @@
     }
 }
 
-void fixup_glGetActiveAttribOrUniform(GLTraceContext *context, GLMessage *glmsg, 
+void fixup_glGetActiveAttribOrUniform(GLTraceContext *context, GLMessage *glmsg,
                                                                 void *pointersToFixup[]) {
     /* void glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize,
                 GLsizei* length, GLint* size, GLenum* type, GLchar* name); */
@@ -400,6 +380,303 @@
     arg_location->add_intvalue(location);
 }
 
+GLint glGetInteger(GLTraceContext *context, GLenum param) {
+    GLint x;
+    context->hooks->gl.glGetIntegerv(param, &x);
+    return x;
+}
+
+GLint glGetVertexAttrib(GLTraceContext *context, GLuint index, GLenum pname) {
+    GLint x;
+    context->hooks->gl.glGetVertexAttribiv(index, pname, &x);
+    return x;
+}
+
+bool isUsingArrayBuffers(GLTraceContext *context) {
+    return glGetInteger(context, GL_ARRAY_BUFFER_BINDING) != 0;
+}
+
+bool isUsingElementArrayBuffers(GLTraceContext *context) {
+    return glGetInteger(context, GL_ELEMENT_ARRAY_BUFFER_BINDING) != 0;
+}
+
+/** Copy @len bytes of data from @src into the @dataIndex'th argument of the message. */
+void addGlBufferData(GLMessage *glmsg, int dataIndex, GLvoid *src, GLsizeiptr len) {
+    GLMessage_DataType *arg_datap = glmsg->mutable_args(dataIndex);
+    arg_datap->set_type(GLMessage::DataType::VOID);
+    arg_datap->set_isarray(true);
+    arg_datap->clear_intvalue();
+    arg_datap->add_rawbytes(src, len);
+}
+
+void fixup_glBufferData(GLTraceContext *context, GLMessage *glmsg, void *pointersToFixup[]) {
+    /* void glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) */
+    GLsizeiptr size = glmsg->args(1).intvalue(0);
+    GLvoid *datap = (GLvoid *) pointersToFixup[0];
+
+    // Save element array buffers for future use to fixup glVertexAttribPointers
+    // when a glDrawElements() call is performed.
+    GLenum target = glmsg->args(0).intvalue(0);
+    if (target == GL_ELEMENT_ARRAY_BUFFER) {
+        GLint bufferId = glGetInteger(context, GL_ELEMENT_ARRAY_BUFFER_BINDING);
+        context->bindBuffer(bufferId, datap, size);
+    }
+
+    // add buffer data to the protobuf message
+    if (datap != NULL) {
+        addGlBufferData(glmsg, 2, datap, size);
+    }
+}
+
+void fixup_glBufferSubData(GLTraceContext *context, GLMessage *glmsg, void *pointersToFixup[]) {
+    /* void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) */
+    GLenum target = glmsg->args(0).intvalue(0);
+    GLintptr offset = glmsg->args(1).intvalue(0);
+    GLsizeiptr size = glmsg->args(2).intvalue(0);
+    GLvoid *datap = (GLvoid *) pointersToFixup[0];
+    if (target == GL_ELEMENT_ARRAY_BUFFER) {
+        GLint bufferId = glGetInteger(context, GL_ELEMENT_ARRAY_BUFFER_BINDING);
+        context->updateBufferSubData(bufferId, offset, datap, size);
+    }
+
+    // add buffer data to the protobuf message
+    addGlBufferData(glmsg, 3, datap, size);
+}
+
+/** Obtain the size of each vertex attribute. */
+int vertexAttribSize(GLenum type, GLsizei numComponents) {
+    int sizePerComponent;
+
+    switch(type) {
+    case GL_BYTE:
+    case GL_UNSIGNED_BYTE:
+        sizePerComponent = 1;
+        break;
+    case GL_SHORT:
+    case GL_UNSIGNED_SHORT:
+        sizePerComponent = 2;
+        break;
+    case GL_FIXED:
+    case GL_FLOAT:
+    default:
+        sizePerComponent = 4;
+        break;
+    }
+
+    return sizePerComponent * numComponents;
+}
+
+/** Create and send a glVertexAttribPointerData trace message to the host. */
+void trace_glVertexAttribPointerData(GLTraceContext *context,
+                    GLuint indx, GLint size, GLenum type,
+                    GLboolean normalized, GLsizei stride, const GLvoid* ptr,
+                    GLuint minIndex, GLuint maxIndex, nsecs_t startTime) {
+    /* void glVertexAttribPointerData(GLuint indx, GLint size, GLenum type,
+                    GLboolean normalized, GLsizei stride, const GLvoid* ptr,
+                    int minIndex, int maxIndex) */
+    GLMessage glmsg;
+    GLTraceContext *glContext = context;
+
+    glmsg.set_function(GLMessage::glVertexAttribPointerData);
+
+    // copy argument indx
+    GLMessage_DataType *arg_indx = glmsg.add_args();
+    arg_indx->set_isarray(false);
+    arg_indx->set_type(GLMessage::DataType::INT);
+    arg_indx->add_intvalue(indx);
+
+    // copy argument size
+    GLMessage_DataType *arg_size = glmsg.add_args();
+    arg_size->set_isarray(false);
+    arg_size->set_type(GLMessage::DataType::INT);
+    arg_size->add_intvalue(size);
+
+    // copy argument type
+    GLMessage_DataType *arg_type = glmsg.add_args();
+    arg_type->set_isarray(false);
+    arg_type->set_type(GLMessage::DataType::ENUM);
+    arg_type->add_intvalue((int)type);
+
+    // copy argument normalized
+    GLMessage_DataType *arg_normalized = glmsg.add_args();
+    arg_normalized->set_isarray(false);
+    arg_normalized->set_type(GLMessage::DataType::BOOL);
+    arg_normalized->add_boolvalue(normalized);
+
+    // copy argument stride
+    GLMessage_DataType *arg_stride = glmsg.add_args();
+    arg_stride->set_isarray(false);
+    arg_stride->set_type(GLMessage::DataType::INT);
+    arg_stride->add_intvalue(stride);
+
+    // copy argument ptr
+    GLMessage_DataType *arg_ptr = glmsg.add_args();
+    arg_ptr->set_isarray(true);
+    arg_ptr->set_type(GLMessage::DataType::BYTE);
+    int perVertexSize = vertexAttribSize(type, size);
+    GLchar *p = (GLchar*) ptr;
+    std::string data;
+    for (GLuint i = minIndex; i < maxIndex; i++) {
+        data.append(p, perVertexSize);
+        p += stride == 0 ? perVertexSize : stride;
+    }
+    arg_ptr->add_rawbytes(data);
+
+    // copy argument min index
+    GLMessage_DataType *arg_min = glmsg.add_args();
+    arg_min->set_isarray(false);
+    arg_min->set_type(GLMessage::DataType::INT);
+    arg_min->add_intvalue(minIndex);
+
+    // copy argument max index
+    GLMessage_DataType *arg_max = glmsg.add_args();
+    arg_max->set_isarray(false);
+    arg_max->set_type(GLMessage::DataType::INT);
+    arg_max->add_intvalue(maxIndex);
+
+    glmsg.set_context_id(context->getId());
+    glmsg.set_start_time(startTime);
+    glmsg.set_threadtime(0);
+    glmsg.set_duration(0);
+
+    context->traceGLMessage(&glmsg);
+}
+
+void findMinAndMaxIndices(GLvoid *indices, GLsizei count, GLenum type,
+                            GLuint *minIndex, GLuint *maxIndex) {
+    GLuint index;
+    *minIndex = UINT_MAX;
+    *maxIndex = 0;
+
+    if (indices == NULL) {
+        return;
+    }
+
+    for (GLsizei i = 0; i < count; i++) {
+        if (type == GL_UNSIGNED_BYTE) {
+            index = *((GLubyte*) indices + i);
+        } else {
+            index = *((GLushort*) indices + i);
+        }
+
+        if (index < *minIndex) *minIndex = index;
+        if (index > *maxIndex) *maxIndex = index;
+    }
+}
+
+void trace_VertexAttribPointerData(GLTraceContext *context,
+                            GLuint minIndex, GLuint maxIndex, nsecs_t time) {
+    GLuint maxAttribs = glGetInteger(context, GL_MAX_VERTEX_ATTRIBS);
+    for (GLuint index = 0; index < maxAttribs; index++) {
+        if (!glGetVertexAttrib(context, index, GL_VERTEX_ATTRIB_ARRAY_ENABLED)) {
+            // vertex array disabled
+            continue;
+        }
+
+        if (glGetVertexAttrib(context, index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING)) {
+            // vbo
+            continue;
+        }
+
+        GLint size = glGetVertexAttrib(context, index, GL_VERTEX_ATTRIB_ARRAY_SIZE);
+        GLenum type = glGetVertexAttrib(context, index, GL_VERTEX_ATTRIB_ARRAY_TYPE);
+        GLboolean norm = glGetVertexAttrib(context, index, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED);
+        GLsizei stride = glGetVertexAttrib(context, index, GL_VERTEX_ATTRIB_ARRAY_STRIDE);
+        GLvoid* ptr;
+        context->hooks->gl.glGetVertexAttribPointerv(index, GL_VERTEX_ATTRIB_ARRAY_POINTER, &ptr);
+
+        trace_glVertexAttribPointerData(context,
+                    index, size, type, norm, stride, ptr,
+                    minIndex, maxIndex, time);
+    }
+}
+
+void trace_VertexAttribPointerDataForGlDrawArrays(GLTraceContext *context, GLMessage *glmsg) {
+    /* void glDrawArrays(GLenum mode, GLint first, GLsizei count) */
+    GLsizei count = glmsg->args(2).intvalue(0);
+
+    // Vertex attrib pointer data patchup calls should appear as if
+    // they occurred right before the draw call.
+    nsecs_t time = glmsg->start_time() - 1;
+
+    trace_VertexAttribPointerData(context, 0, count, time);
+}
+
+void trace_VertexAttribPointerDataForGlDrawElements(GLTraceContext *context, GLMessage *glmsg,
+                            GLvoid *indices) {
+    /* void glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) */
+    GLsizei count = glmsg->args(1).intvalue(0);
+    GLenum type = glmsg->args(2).intvalue(0);
+    GLuint index;
+
+    GLuint minIndex, maxIndex;
+
+    // The index buffer is either passed in as an argument to the glDrawElements() call,
+    // or it is stored in the current GL_ELEMENT_ARRAY_BUFFER.
+    GLvoid *indexBuffer;
+    if (isUsingElementArrayBuffers(context)) {
+        GLsizeiptr eaBufferSize;
+        GLuint bufferId = glGetInteger(context, GL_ELEMENT_ARRAY_BUFFER_BINDING);
+        context->getBuffer(bufferId, &indexBuffer, &eaBufferSize);
+    } else {
+        indexBuffer = indices;
+    }
+
+    // Rather than sending vertex attribute data that corresponds to the indices
+    // being drawn, we send the vertex attribute data for the entire range of
+    // indices being drawn, including the ones not drawn. The min & max indices
+    // provide the range of indices being drawn.
+    findMinAndMaxIndices(indexBuffer, count, type, &minIndex, &maxIndex);
+
+    // Vertex attrib pointer data patchup calls should appear as if
+    // they occurred right before the draw call.
+    nsecs_t time = glmsg->start_time() - 1;
+
+    trace_VertexAttribPointerData(context, minIndex, maxIndex + 1, time);
+}
+
+void fixup_glDrawArrays(GLTraceContext *context, GLMessage *glmsg) {
+    // Trace all vertex attribute data stored in client space.
+    trace_VertexAttribPointerDataForGlDrawArrays(context, glmsg);
+
+    // Attach the FB if requested
+    if (context->getGlobalTraceState()->shouldCollectFbOnGlDraw()) {
+        fixup_addFBContents(context, glmsg, CURRENTLY_BOUND_FB);
+    }
+}
+
+void fixup_glDrawElements(GLTraceContext *context, GLMessage *glmsg, void *pointersToFixup[]) {
+    /* void glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) */
+    GLvoid *indices = pointersToFixup[0];
+    GLenum type = glmsg->args(2).intvalue(0);
+    GLsizei count = glmsg->args(1).intvalue(0);
+    GLuint index;
+
+    // Trace all vertex attribute data stored in client space.
+    trace_VertexAttribPointerDataForGlDrawElements(context, glmsg, indices);
+
+    // Fixup indices argument
+    if (!isUsingElementArrayBuffers(context)) {
+        GLMessage_DataType *arg_indices = glmsg->mutable_args(3);
+        arg_indices->set_isarray(true);
+        arg_indices->clear_intvalue();
+        arg_indices->set_type(GLMessage::DataType::INT);
+        for (GLsizei i = 0; i < count; i++) {
+            if (type == GL_UNSIGNED_BYTE) {
+                index = *((GLubyte*) indices + i);
+            } else {
+                index = *((GLushort*) indices + i);
+            }
+            arg_indices->add_intvalue(index);
+        }
+    }
+
+    // Attach the FB if requested
+    if (context->getGlobalTraceState()->shouldCollectFbOnGlDraw()) {
+        fixup_addFBContents(context, glmsg, CURRENTLY_BOUND_FB);
+    }
+}
+
 void fixupGLMessage(GLTraceContext *context, nsecs_t wallStart, nsecs_t wallEnd,
                                              nsecs_t threadStart, nsecs_t threadEnd,
                                              GLMessage *glmsg, void *pointersToFixup[]) {
@@ -438,8 +715,8 @@
         /* void glBindAttribLocation(GLuint program, GLuint index, const GLchar* name); */
         fixup_CStringPtr(2, glmsg, pointersToFixup[0]);
         break;
-    case GLMessage::glGetAttribLocation:  
-    case GLMessage::glGetUniformLocation: 
+    case GLMessage::glGetAttribLocation:
+    case GLMessage::glGetUniformLocation:
         /* int glGetAttribLocation(GLuint program, const GLchar* name) */
         /* int glGetUniformLocation(GLuint program, const GLchar* name) */
         fixup_CStringPtr(1, glmsg, pointersToFixup[0]);
@@ -526,23 +803,19 @@
         break;
     case GLMessage::glBufferData:
         /* void glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) */
-        fixup_glBufferData(1, 2, glmsg, pointersToFixup);
+        fixup_glBufferData(context, glmsg, pointersToFixup);
         break;
     case GLMessage::glBufferSubData:
         /* void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) */
-        fixup_glBufferData(2, 3, glmsg, pointersToFixup);
+        fixup_glBufferSubData(context, glmsg, pointersToFixup);
         break;
     case GLMessage::glDrawArrays:
         /* void glDrawArrays(GLenum mode, GLint first, GLsizei count) */
-        if (context->getGlobalTraceState()->shouldCollectFbOnGlDraw()) {
-            fixup_addFBContents(context, glmsg, CURRENTLY_BOUND_FB);
-        }
+        fixup_glDrawArrays(context, glmsg);
         break;
     case GLMessage::glDrawElements:
         /* void glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) */
-        if (context->getGlobalTraceState()->shouldCollectFbOnGlDraw()) {
-            fixup_addFBContents(context, glmsg, CURRENTLY_BOUND_FB);
-        }
+        fixup_glDrawElements(context, glmsg, pointersToFixup);
         break;
     case GLMessage::glPushGroupMarkerEXT:
         /* void PushGroupMarkerEXT(sizei length, const char *marker); */
diff --git a/opengl/tests/angeles/Android.mk b/opengl/tests/angeles/Android.mk
index 84b754b..ae4f76d 100644
--- a/opengl/tests/angeles/Android.mk
+++ b/opengl/tests/angeles/Android.mk
@@ -4,7 +4,7 @@
 include $(CLEAR_VARS)
 LOCAL_SRC_FILES:= app-linux.cpp demo.c.arm
 LOCAL_SHARED_LIBRARIES := libEGL libGLESv1_CM libui
-LOCAL_C_INCLUDES += frameworks/base/opengl/tests/include
+LOCAL_C_INCLUDES += $(call include-path-for, opengl-tests-includes)
 LOCAL_MODULE:= angeles
 LOCAL_MODULE_TAGS := optional
 include $(BUILD_EXECUTABLE)
diff --git a/opengl/tests/fillrate/Android.mk b/opengl/tests/fillrate/Android.mk
index 835f858..4dade21 100644
--- a/opengl/tests/fillrate/Android.mk
+++ b/opengl/tests/fillrate/Android.mk
@@ -11,7 +11,7 @@
     libGLESv1_CM \
     libui
 
-LOCAL_C_INCLUDES += frameworks/base/opengl/tests/include
+LOCAL_C_INCLUDES += $(call include-path-for, opengl-tests-includes)
 
 LOCAL_MODULE:= test-opengl-fillrate
 
diff --git a/opengl/tests/filter/Android.mk b/opengl/tests/filter/Android.mk
index d780362..d3e4d38 100644
--- a/opengl/tests/filter/Android.mk
+++ b/opengl/tests/filter/Android.mk
@@ -10,7 +10,7 @@
     libGLESv1_CM \
     libui
 
-LOCAL_C_INCLUDES += frameworks/base/opengl/tests/include
+LOCAL_C_INCLUDES += $(call include-path-for, opengl-tests-includes)
 
 LOCAL_MODULE:= test-opengl-filter
 
diff --git a/opengl/tests/finish/Android.mk b/opengl/tests/finish/Android.mk
index 8f4f9c3..aa8adca 100644
--- a/opengl/tests/finish/Android.mk
+++ b/opengl/tests/finish/Android.mk
@@ -11,7 +11,7 @@
     libGLESv1_CM \
     libui
 
-LOCAL_C_INCLUDES += frameworks/base/opengl/tests/include
+LOCAL_C_INCLUDES += $(call include-path-for, opengl-tests-includes)
 
 LOCAL_MODULE:= test-opengl-finish
 
diff --git a/opengl/tests/gl2_basic/Android.mk b/opengl/tests/gl2_basic/Android.mk
index 07469a0..d7819a1 100644
--- a/opengl/tests/gl2_basic/Android.mk
+++ b/opengl/tests/gl2_basic/Android.mk
@@ -10,7 +10,7 @@
     libGLESv2 \
     libui
 
-LOCAL_C_INCLUDES += frameworks/base/opengl/tests/include
+LOCAL_C_INCLUDES += $(call include-path-for, opengl-tests-includes)
 
 LOCAL_MODULE:= test-opengl-gl2_basic
 
diff --git a/opengl/tests/gl2_copyTexImage/Android.mk b/opengl/tests/gl2_copyTexImage/Android.mk
index b616428..005c383 100644
--- a/opengl/tests/gl2_copyTexImage/Android.mk
+++ b/opengl/tests/gl2_copyTexImage/Android.mk
@@ -10,7 +10,7 @@
     libGLESv2 \
     libui
 
-LOCAL_C_INCLUDES += frameworks/base/opengl/tests/include
+LOCAL_C_INCLUDES += $(call include-path-for, opengl-tests-includes)
 
 LOCAL_MODULE:= test-opengl-gl2_copyTexImage
 
diff --git a/opengl/tests/gl2_yuvtex/Android.mk b/opengl/tests/gl2_yuvtex/Android.mk
index e36f319..7d43759 100644
--- a/opengl/tests/gl2_yuvtex/Android.mk
+++ b/opengl/tests/gl2_yuvtex/Android.mk
@@ -10,7 +10,7 @@
     libGLESv2 \
     libui
 
-LOCAL_C_INCLUDES += frameworks/base/opengl/tests/include
+LOCAL_C_INCLUDES += $(call include-path-for, opengl-tests-includes)
 
 LOCAL_MODULE:= test-opengl-gl2_yuvtex
 
diff --git a/opengl/tests/gl_basic/Android.mk b/opengl/tests/gl_basic/Android.mk
index 2ba327b..46bcc60 100644
--- a/opengl/tests/gl_basic/Android.mk
+++ b/opengl/tests/gl_basic/Android.mk
@@ -10,7 +10,7 @@
     libGLESv1_CM \
     libui
 
-LOCAL_C_INCLUDES += frameworks/base/opengl/tests/include
+LOCAL_C_INCLUDES += $(call include-path-for, opengl-tests-includes)
 
 LOCAL_MODULE:= test-opengl-gl_basic
 
diff --git a/opengl/tests/gl_perf/Android.mk b/opengl/tests/gl_perf/Android.mk
index f32abd3..cfca089 100644
--- a/opengl/tests/gl_perf/Android.mk
+++ b/opengl/tests/gl_perf/Android.mk
@@ -11,7 +11,7 @@
     libGLESv2 \
     libui
 
-LOCAL_C_INCLUDES += frameworks/base/opengl/tests/include
+LOCAL_C_INCLUDES += $(call include-path-for, opengl-tests-includes)
 
 LOCAL_MODULE:= test-opengl-gl2_perf
 
diff --git a/opengl/tests/gl_yuvtex/Android.mk b/opengl/tests/gl_yuvtex/Android.mk
index 5b87f2e..9e5dba0 100644
--- a/opengl/tests/gl_yuvtex/Android.mk
+++ b/opengl/tests/gl_yuvtex/Android.mk
@@ -10,7 +10,7 @@
     libGLESv1_CM \
     libui
 
-LOCAL_C_INCLUDES += frameworks/base/opengl/tests/include
+LOCAL_C_INCLUDES += $(call include-path-for, opengl-tests-includes)
 
 LOCAL_MODULE:= test-opengl-gl_yuvtex
 
diff --git a/opengl/tests/hwc/Android.mk b/opengl/tests/hwc/Android.mk
index e4d7e28..9eb58b1 100644
--- a/opengl/tests/hwc/Android.mk
+++ b/opengl/tests/hwc/Android.mk
@@ -22,8 +22,7 @@
     bionic \
     bionic/libstdc++/include \
     external/stlport/stlport \
-    frameworks/base/opengl/tests \
-    frameworks/base/opengl/tests/include \
+	$(call include-path-for, opengl-tests-includes)
 
 LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
 
@@ -51,8 +50,7 @@
 LOCAL_C_INCLUDES += \
     system/extras/tests/include \
     hardware/libhardware/include \
-    frameworks/base/opengl/tests \
-    frameworks/base/opengl/tests/include \
+	$(call include-path-for, opengl-tests-includes)
 
 LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
 
@@ -83,8 +81,7 @@
 LOCAL_C_INCLUDES += \
     system/extras/tests/include \
     hardware/libhardware/include \
-    frameworks/base/opengl/tests \
-    frameworks/base/opengl/tests/include \
+	$(call include-path-for, opengl-tests-includes)
 
 LOCAL_MODULE:= hwcRects
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/nativeutil
@@ -113,8 +110,7 @@
 LOCAL_C_INCLUDES += \
     system/extras/tests/include \
     hardware/libhardware/include \
-    frameworks/base/opengl/tests \
-    frameworks/base/opengl/tests/include \
+	$(call include-path-for, opengl-tests-includes)
 
 LOCAL_MODULE:= hwcColorEquiv
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/nativeutil
@@ -143,8 +139,7 @@
 LOCAL_C_INCLUDES += \
     system/extras/tests/include \
     hardware/libhardware/include \
-    frameworks/base/opengl/tests \
-    frameworks/base/opengl/tests/include \
+	$(call include-path-for, opengl-tests-includes)
 
 LOCAL_MODULE:= hwcCommit
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/nativebenchmark
diff --git a/opengl/tests/hwc/hwcCommit.cpp b/opengl/tests/hwc/hwcCommit.cpp
index 685dc5d..efa646c 100644
--- a/opengl/tests/hwc/hwcCommit.cpp
+++ b/opengl/tests/hwc/hwcCommit.cpp
@@ -106,7 +106,7 @@
 #include <hardware/hwcomposer.h>
 
 #include <glTestLib.h>
-#include <hwc/hwcTestLib.h>
+#include "hwcTestLib.h"
 
 using namespace std;
 using namespace android;
diff --git a/opengl/tests/hwc/hwcRects.cpp b/opengl/tests/hwc/hwcRects.cpp
index 80cde23..906c169 100644
--- a/opengl/tests/hwc/hwcRects.cpp
+++ b/opengl/tests/hwc/hwcRects.cpp
@@ -114,7 +114,7 @@
 #include <hardware/hwcomposer.h>
 
 #include <glTestLib.h>
-#include <hwc/hwcTestLib.h>
+#include "hwcTestLib.h"
 
 using namespace std;
 using namespace android;
diff --git a/opengl/tests/hwc/hwcStress.cpp b/opengl/tests/hwc/hwcStress.cpp
index 7d7bc1f..b02a424 100644
--- a/opengl/tests/hwc/hwcStress.cpp
+++ b/opengl/tests/hwc/hwcStress.cpp
@@ -111,7 +111,7 @@
 #include <hardware/hwcomposer.h>
 
 #include <glTestLib.h>
-#include <hwc/hwcTestLib.h>
+#include "hwcTestLib.h"
 
 using namespace std;
 using namespace android;
diff --git a/opengl/tests/hwc/hwcTestLib.cpp b/opengl/tests/hwc/hwcTestLib.cpp
index 63f42ba..28e0c3f 100644
--- a/opengl/tests/hwc/hwcTestLib.cpp
+++ b/opengl/tests/hwc/hwcTestLib.cpp
@@ -25,7 +25,7 @@
 
 #include <arpa/inet.h> // For ntohl() and htonl()
 
-#include <hwc/hwcTestLib.h>
+#include "hwcTestLib.h"
 
 #include "EGLUtils.h"
 
diff --git a/opengl/tests/lib/Android.mk b/opengl/tests/lib/Android.mk
index ac1e183..0352a37 100644
--- a/opengl/tests/lib/Android.mk
+++ b/opengl/tests/lib/Android.mk
@@ -22,7 +22,7 @@
     bionic \
     bionic/libstdc++/include \
     external/stlport/stlport \
-    frameworks/base/opengl/tests/include \
+	$(call include-path-for, opengl-tests-includes)
 
 LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
 
diff --git a/opengl/tests/linetex/Android.mk b/opengl/tests/linetex/Android.mk
index 261940e..5b6384e 100644
--- a/opengl/tests/linetex/Android.mk
+++ b/opengl/tests/linetex/Android.mk
@@ -10,7 +10,7 @@
     libGLESv1_CM \
     libui
 
-LOCAL_C_INCLUDES += frameworks/base/opengl/tests/include
+LOCAL_C_INCLUDES += $(call include-path-for, opengl-tests-includes)
 
 LOCAL_MODULE:= test-opengl-linetex
 
diff --git a/opengl/tests/swapinterval/Android.mk b/opengl/tests/swapinterval/Android.mk
index d014cc9..5517f60 100644
--- a/opengl/tests/swapinterval/Android.mk
+++ b/opengl/tests/swapinterval/Android.mk
@@ -11,7 +11,7 @@
     libGLESv1_CM \
     libui
 
-LOCAL_C_INCLUDES += frameworks/base/opengl/tests/include
+LOCAL_C_INCLUDES += $(call include-path-for, opengl-tests-includes)
 
 LOCAL_MODULE:= test-opengl-swapinterval
 
diff --git a/opengl/tests/textures/Android.mk b/opengl/tests/textures/Android.mk
index fe9f43c..97697d7 100644
--- a/opengl/tests/textures/Android.mk
+++ b/opengl/tests/textures/Android.mk
@@ -10,7 +10,7 @@
     libGLESv1_CM \
     libui
 
-LOCAL_C_INCLUDES += frameworks/base/opengl/tests/include
+LOCAL_C_INCLUDES += $(call include-path-for, opengl-tests-includes)
 
 LOCAL_MODULE:= test-opengl-textures
 
diff --git a/opengl/tests/tritex/Android.mk b/opengl/tests/tritex/Android.mk
index fc544e4..89faa87 100644
--- a/opengl/tests/tritex/Android.mk
+++ b/opengl/tests/tritex/Android.mk
@@ -10,7 +10,7 @@
     libGLESv1_CM \
     libui
 
-LOCAL_C_INCLUDES += frameworks/base/opengl/tests/include
+LOCAL_C_INCLUDES += $(call include-path-for, opengl-tests-includes)
 
 LOCAL_MODULE:= test-opengl-tritex
 
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 42e280f..aa1e426 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -51,11 +51,6 @@
 # this is only needed for DDMS debugging
 LOCAL_SHARED_LIBRARIES += libdvm libandroid_runtime
 
-LOCAL_C_INCLUDES := \
-	$(call include-path-for, corecg graphics)
-
-LOCAL_C_INCLUDES += hardware/libhardware/modules/gralloc
-
 LOCAL_MODULE:= libsurfaceflinger
 
 include $(BUILD_SHARED_LIBRARY)