Merge "Refactor how timeouts are calculated."
diff --git a/include/gui/ISurfaceTexture.h b/include/gui/ISurfaceTexture.h
index 168310c..6ed3c6f 100644
--- a/include/gui/ISurfaceTexture.h
+++ b/include/gui/ISurfaceTexture.h
@@ -62,8 +62,11 @@
     // contents of the buffer associated with slot and transfers ownership of
     // that slot back to the server. It is not valid to call queueBuffer on a
     // slot that is not owned by the client or one for which a buffer associated
-    // via requestBuffer.
-    virtual status_t queueBuffer(int slot) = 0;
+    // via requestBuffer. In addition, a timestamp must be provided by the
+    // client for this buffer. The timestamp is measured in nanoseconds, and
+    // must be monotonically increasing. Its other properties (zero point, etc)
+    // are client-dependent, and should be documented by the client.
+    virtual status_t queueBuffer(int slot, int64_t timestamp) = 0;
 
     // cancelBuffer indicates that the client does not wish to fill in the
     // buffer associated with slot and transfers ownership of the slot back to
diff --git a/include/gui/SurfaceTexture.h b/include/gui/SurfaceTexture.h
index 9bf38f7..afa64d3 100644
--- a/include/gui/SurfaceTexture.h
+++ b/include/gui/SurfaceTexture.h
@@ -66,7 +66,12 @@
     // unmodified.
     virtual status_t dequeueBuffer(int *buf);
 
-    virtual status_t queueBuffer(int buf);
+    // queueBuffer returns a filled buffer to the SurfaceTexture. In addition, a
+    // timestamp must be provided for the buffer. The timestamp is in
+    // nanoseconds, and must be monotonically increasing. Its other semantics
+    // (zero point, etc) are client-dependent and should be documented by the
+    // client.
+    virtual status_t queueBuffer(int buf, int64_t timestamp);
     virtual void cancelBuffer(int buf);
     virtual status_t setCrop(const Rect& reg);
     virtual status_t setTransform(uint32_t transform);
@@ -98,6 +103,14 @@
     // functions.
     void getTransformMatrix(float mtx[16]);
 
+    // getTimestamp retrieves the timestamp associated with the texture image
+    // set by the most recent call to updateTexImage.
+    //
+    // The timestamp is in nanoseconds, and is monotonically increasing. Its
+    // other semantics (zero point, etc) are source-dependent and should be
+    // documented by the source.
+    int64_t getTimestamp();
+
     // setFrameAvailableListener sets the listener object that will be notified
     // when a new frame becomes available.
     void setFrameAvailableListener(const sp<FrameAvailableListener>& l);
@@ -172,6 +185,10 @@
     // gets set to mLastQueuedTransform each time updateTexImage is called.
     uint32_t mCurrentTransform;
 
+    // mCurrentTimestamp is the timestamp for the current texture. It
+    // gets set to mLastQueuedTimestamp each time updateTexImage is called.
+    int64_t mCurrentTimestamp;
+
     // mLastQueued is the buffer slot index of the most recently enqueued buffer.
     // At construction time it is initialized to INVALID_BUFFER_SLOT, and is
     // updated each time queueBuffer is called.
@@ -187,6 +204,10 @@
     // queueBuffer gets called.
     uint32_t mLastQueuedTransform;
 
+    // mLastQueuedTimestamp is the timestamp for the buffer that was most
+    // recently queued. This gets set by queueBuffer.
+    int64_t mLastQueuedTimestamp;
+
     // mNextCrop is the crop rectangle that will be used for the next buffer
     // that gets queued. It is set by calling setCrop.
     Rect mNextCrop;
diff --git a/include/gui/SurfaceTextureClient.h b/include/gui/SurfaceTextureClient.h
index 7992105..df82bf2 100644
--- a/include/gui/SurfaceTextureClient.h
+++ b/include/gui/SurfaceTextureClient.h
@@ -63,6 +63,7 @@
     int dispatchSetBufferCount(va_list args);
     int dispatchSetBuffersGeometry(va_list args);
     int dispatchSetBuffersTransform(va_list args);
+    int dispatchSetBuffersTimestamp(va_list args);
     int dispatchSetCrop(va_list args);
     int dispatchSetUsage(va_list args);
 
@@ -71,6 +72,7 @@
     int setBufferCount(int bufferCount);
     int setBuffersGeometry(int w, int h, int format);
     int setBuffersTransform(int transform);
+    int setBuffersTimestamp(int64_t timestamp);
     int setCrop(Rect const* rect);
     int setUsage(uint32_t reqUsage);
 
@@ -114,6 +116,11 @@
     // at the next deuque operation. It is initialized to 0.
     uint32_t mReqUsage;
 
+    // mTimestamp is the timestamp that will be used for the next buffer queue
+    // operation. It defaults to NATIVE_WINDOW_TIMESTAMP_AUTO, which means that
+    // a timestamp is auto-generated when queueBuffer is called.
+    int64_t mTimestamp;
+
     // mMutex is the mutex used to prevent concurrent access to the member
     // variables of SurfaceTexture objects. It must be locked whenever the
     // member variables are accessed.
diff --git a/include/surfaceflinger/Surface.h b/include/surfaceflinger/Surface.h
index 9e0b5bb..a59d9e5 100644
--- a/include/surfaceflinger/Surface.h
+++ b/include/surfaceflinger/Surface.h
@@ -226,7 +226,8 @@
     int  dispatch_set_buffer_count(va_list args);
     int  dispatch_set_buffers_geometry(va_list args);
     int  dispatch_set_buffers_transform(va_list args);
-    
+    int  dispatch_set_buffers_timestamp(va_list args);
+
     void setUsage(uint32_t reqUsage);
     int  connect(int api);
     int  disconnect(int api);
@@ -234,6 +235,7 @@
     int  setBufferCount(int bufferCount);
     int  setBuffersGeometry(int w, int h, int format);
     int  setBuffersTransform(int transform);
+    int  setBuffersTimestamp(int64_t timestamp);
 
     /*
      *  private stuff...
diff --git a/include/ui/KeycodeLabels.h b/include/ui/KeycodeLabels.h
index b912e9b..8383957 100755
--- a/include/ui/KeycodeLabels.h
+++ b/include/ui/KeycodeLabels.h
@@ -228,6 +228,9 @@
     { "BUTTON_14", 201 },
     { "BUTTON_15", 202 },
     { "BUTTON_16", 203 },
+    { "LANGUAGE_SWITCH", 204 },
+    { "MANNER_MODE", 205 },
+    { "3D_MODE", 206 },
 
     // NOTE: If you add a new keycode here you must also add it to several other files.
     //       Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list.
diff --git a/include/ui/egl/android_natives.h b/include/ui/egl/android_natives.h
index 0fc1ddf..0a6e4fb 100644
--- a/include/ui/egl/android_natives.h
+++ b/include/ui/egl/android_natives.h
@@ -57,7 +57,7 @@
 {
     /* a magic value defined by the actual EGL native type */
     int magic;
-    
+
     /* the sizeof() of the actual EGL native type */
     int version;
 
@@ -129,6 +129,7 @@
     NATIVE_WINDOW_SET_BUFFER_COUNT,
     NATIVE_WINDOW_SET_BUFFERS_GEOMETRY,
     NATIVE_WINDOW_SET_BUFFERS_TRANSFORM,
+    NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP,
 };
 
 /* parameter for NATIVE_WINDOW_[DIS]CONNECT */
@@ -157,7 +158,15 @@
     NATIVE_WINDOW_SURFACE_TEXTURE_CLIENT,       // SurfaceTextureClient
 };
 
-struct ANativeWindow 
+/* parameter for NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP
+ *
+ * Special timestamp value to indicate that timestamps should be auto-generated
+ * by the native window when queueBuffer is called.  This is equal to INT64_MIN,
+ * defined directly to avoid problems with C99/C++ inclusion of stdint.h.
+ */
+const int64_t NATIVE_WINDOW_TIMESTAMP_AUTO = (-9223372036854775807LL-1);
+
+struct ANativeWindow
 {
 #ifdef __cplusplus
     ANativeWindow()
@@ -262,7 +271,8 @@
      *     NATIVE_WINDOW_SET_BUFFER_COUNT
      *     NATIVE_WINDOW_SET_BUFFERS_GEOMETRY
      *     NATIVE_WINDOW_SET_BUFFERS_TRANSFORM
-     *  
+     *     NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP
+     *
      */
     
     int     (*perform)(struct ANativeWindow* window,
@@ -389,6 +399,22 @@
             transform);
 }
 
+/*
+ * native_window_set_buffers_timestamp(..., int64_t timestamp)
+ * All buffers queued after this call will be associated with the timestamp
+ * parameter specified. If the timestamp is set to NATIVE_WINDOW_TIMESTAMP_AUTO
+ * (the default), timestamps will be generated automatically when queueBuffer is
+ * called. The timestamp is measured in nanoseconds, and must be monotonically
+ * increasing.
+ */
+static inline int native_window_set_buffers_timestamp(
+        ANativeWindow* window,
+        int64_t timestamp)
+{
+    return window->perform(window, NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP,
+            timestamp);
+}
+
 // ---------------------------------------------------------------------------
 
 /* FIXME: this is legacy for pixmaps */
diff --git a/include/utils/Functor.h b/include/utils/Functor.h
index 565f4a3..e24ded4 100644
--- a/include/utils/Functor.h
+++ b/include/utils/Functor.h
@@ -25,8 +25,7 @@
 public:
     Functor() {}
     virtual ~Functor() {}
-    virtual status_t operator ()() { return true; }
-    virtual status_t operator ()(float* data, uint32_t len) { return true; }
+    virtual status_t operator ()(int what, void* data) { return NO_ERROR; }
 };
 
 }; // namespace android
diff --git a/include/utils/Vector.h b/include/utils/Vector.h
index ec851bd..6fd307f 100644
--- a/include/utils/Vector.h
+++ b/include/utils/Vector.h
@@ -162,6 +162,9 @@
      inline status_t        sort(compar_t cmp);
      inline status_t        sort(compar_r_t cmp, void* state);
 
+     // for debugging only
+     inline size_t getItemSize() const { return itemSize(); }
+
 protected:
     virtual void    do_construct(void* storage, size_t num) const;
     virtual void    do_destroy(void* storage, size_t num) const;
diff --git a/libs/gui/ISurfaceTexture.cpp b/libs/gui/ISurfaceTexture.cpp
index d661fd5..bc14ad5 100644
--- a/libs/gui/ISurfaceTexture.cpp
+++ b/libs/gui/ISurfaceTexture.cpp
@@ -88,10 +88,11 @@
         return result;
     }
 
-    virtual status_t queueBuffer(int buf) {
+    virtual status_t queueBuffer(int buf, int64_t timestamp) {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
         data.writeInt32(buf);
+        data.writeInt64(timestamp);
         remote()->transact(QUEUE_BUFFER, data, &reply);
         status_t result = reply.readInt32();
         return result;
@@ -174,7 +175,8 @@
         case QUEUE_BUFFER: {
             CHECK_INTERFACE(ISurfaceTexture, data, reply);
             int buf = data.readInt32();
-            status_t result = queueBuffer(buf);
+            int64_t timestamp = data.readInt64();
+            status_t result = queueBuffer(buf, timestamp);
             reply->writeInt32(result);
             return NO_ERROR;
         } break;
@@ -196,7 +198,6 @@
             return NO_ERROR;
         } break;
         case SET_TRANSFORM: {
-            Rect reg;
             CHECK_INTERFACE(ISurfaceTexture, data, reply);
             uint32_t transform = data.readInt32();
             status_t result = setTransform(transform);
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp
index 5c6d71b..cdaca47 100644
--- a/libs/gui/SurfaceTexture.cpp
+++ b/libs/gui/SurfaceTexture.cpp
@@ -76,9 +76,15 @@
 static void mtxMul(float out[16], const float a[16], const float b[16]);
 
 SurfaceTexture::SurfaceTexture(GLuint tex) :
-    mBufferCount(MIN_BUFFER_SLOTS), mCurrentTexture(INVALID_BUFFER_SLOT),
-    mCurrentTransform(0), mLastQueued(INVALID_BUFFER_SLOT),
-    mLastQueuedTransform(0), mNextTransform(0), mTexName(tex) {
+    mBufferCount(MIN_BUFFER_SLOTS),
+    mCurrentTexture(INVALID_BUFFER_SLOT),
+    mCurrentTransform(0),
+    mCurrentTimestamp(0),
+    mLastQueued(INVALID_BUFFER_SLOT),
+    mLastQueuedTransform(0),
+    mLastQueuedTimestamp(0),
+    mNextTransform(0),
+    mTexName(tex) {
     LOGV("SurfaceTexture::SurfaceTexture");
     for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
         mSlots[i].mEglImage = EGL_NO_IMAGE_KHR;
@@ -153,7 +159,7 @@
     return OK;
 }
 
-status_t SurfaceTexture::queueBuffer(int buf) {
+status_t SurfaceTexture::queueBuffer(int buf, int64_t timestamp) {
     LOGV("SurfaceTexture::queueBuffer");
     Mutex::Autolock lock(mMutex);
     if (buf < 0 || mBufferCount <= buf) {
@@ -172,6 +178,7 @@
     mLastQueued = buf;
     mLastQueuedCrop = mNextCrop;
     mLastQueuedTransform = mNextTransform;
+    mLastQueuedTimestamp = timestamp;
     if (mFrameAvailableListener != 0) {
         mFrameAvailableListener->onFrameAvailable();
     }
@@ -246,12 +253,13 @@
         mCurrentTextureBuf = mSlots[mCurrentTexture].mGraphicBuffer;
         mCurrentCrop = mLastQueuedCrop;
         mCurrentTransform = mLastQueuedTransform;
+        mCurrentTimestamp = mLastQueuedTimestamp;
     }
     return OK;
 }
 
 void SurfaceTexture::getTransformMatrix(float mtx[16]) {
-    LOGV("SurfaceTexture::updateTexImage");
+    LOGV("SurfaceTexture::getTransformMatrix");
     Mutex::Autolock lock(mMutex);
 
     float xform[16];
@@ -342,6 +350,12 @@
     mtxMul(mtx, mtxFlipV, mtxBeforeFlipV);
 }
 
+nsecs_t SurfaceTexture::getTimestamp() {
+    LOGV("SurfaceTexture::getTimestamp");
+    Mutex::Autolock lock(mMutex);
+    return mCurrentTimestamp;
+}
+
 void SurfaceTexture::setFrameAvailableListener(
         const sp<FrameAvailableListener>& l) {
     LOGV("SurfaceTexture::setFrameAvailableListener");
diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp
index 7f1d9cb..a4812d0 100644
--- a/libs/gui/SurfaceTextureClient.cpp
+++ b/libs/gui/SurfaceTextureClient.cpp
@@ -26,7 +26,8 @@
 SurfaceTextureClient::SurfaceTextureClient(
         const sp<ISurfaceTexture>& surfaceTexture):
         mSurfaceTexture(surfaceTexture), mAllocator(0), mReqWidth(1),
-        mReqHeight(1), mReqFormat(DEFAULT_FORMAT), mReqUsage(0), mMutex() {
+        mReqHeight(1), mReqFormat(DEFAULT_FORMAT), mReqUsage(0),
+        mTimestamp(NATIVE_WINDOW_TIMESTAMP_AUTO), mMutex() {
     // Initialize the ANativeWindow function pointers.
     ANativeWindow::setSwapInterval  = setSwapInterval;
     ANativeWindow::dequeueBuffer    = dequeueBuffer;
@@ -135,9 +136,17 @@
 int SurfaceTextureClient::queueBuffer(android_native_buffer_t* buffer) {
     LOGV("SurfaceTextureClient::queueBuffer");
     Mutex::Autolock lock(mMutex);
+    int64_t timestamp;
+    if (mTimestamp == NATIVE_WINDOW_TIMESTAMP_AUTO) {
+        timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
+        LOGV("SurfaceTextureClient::queueBuffer making up timestamp: %.2f ms",
+             timestamp / 1000000.f);
+    } else {
+        timestamp = mTimestamp;
+    }
     for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
         if (mSlots[i]->handle == buffer->handle) {
-            return mSurfaceTexture->queueBuffer(i);
+            return mSurfaceTexture->queueBuffer(i, timestamp);
         }
     }
     LOGE("queueBuffer: unknown buffer queued");
@@ -196,6 +205,9 @@
     case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM:
         res = dispatchSetBuffersTransform(args);
         break;
+    case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP:
+        res = dispatchSetBuffersTimestamp(args);
+        break;
     default:
         res = NAME_NOT_FOUND;
         break;
@@ -240,6 +252,11 @@
     return setBuffersTransform(transform);
 }
 
+int SurfaceTextureClient::dispatchSetBuffersTimestamp(va_list args) {
+    int64_t timestamp = va_arg(args, int64_t);
+    return setBuffersTimestamp(timestamp);
+}
+
 int SurfaceTextureClient::connect(int api) {
     LOGV("SurfaceTextureClient::connect");
     // XXX: Implement this!
@@ -323,6 +340,14 @@
     return err;
 }
 
+int SurfaceTextureClient::setBuffersTimestamp(int64_t timestamp)
+{
+    LOGV("SurfaceTextureClient::setBuffersTimestamp");
+    Mutex::Autolock lock(mMutex);
+    mTimestamp = timestamp;
+    return NO_ERROR;
+}
+
 void SurfaceTextureClient::freeAllBuffers() {
     for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
         mSlots[i] = 0;
diff --git a/libs/surfaceflinger_client/Surface.cpp b/libs/surfaceflinger_client/Surface.cpp
index 21d509a..0dfbf01 100644
--- a/libs/surfaceflinger_client/Surface.cpp
+++ b/libs/surfaceflinger_client/Surface.cpp
@@ -753,6 +753,9 @@
     case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM:
         res = dispatch_set_buffers_transform( args );
         break;
+    case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP:
+        res = dispatch_set_buffers_timestamp( args );
+        break;
     default:
         res = NAME_NOT_FOUND;
         break;
@@ -792,6 +795,11 @@
     return setBuffersTransform(transform);
 }
 
+int Surface::dispatch_set_buffers_timestamp(va_list args) {
+    int64_t timestamp = va_arg(args, int64_t);
+    return setBuffersTimestamp(timestamp);
+}
+
 void Surface::setUsage(uint32_t reqUsage)
 {
     Mutex::Autolock _l(mSurfaceLock);
@@ -910,6 +918,13 @@
     return NO_ERROR;
 }
 
+int Surface::setBuffersTimestamp(int64_t timestamp)
+{
+    // Surface doesn't really have anything meaningful to do with timestamps
+    // so they'll just be dropped here.
+    return NO_ERROR;
+}
+
 // ----------------------------------------------------------------------------
 
 int Surface::getConnectedApi() const
diff --git a/libs/ui/Region.cpp b/libs/ui/Region.cpp
index 1994f6a..a060a5f 100644
--- a/libs/ui/Region.cpp
+++ b/libs/ui/Region.cpp
@@ -56,6 +56,9 @@
 Region::Region(const Region& rhs)
     : mBounds(rhs.mBounds), mStorage(rhs.mStorage)
 {
+#if VALIDATE_REGIONS
+    validate(rhs, "rhs copy-ctor");
+#endif
 }
 
 Region::Region(const Rect& rhs)
@@ -76,7 +79,8 @@
 Region& Region::operator = (const Region& rhs)
 {
 #if VALIDATE_REGIONS
-    validate(rhs, "operator=");
+    validate(*this, "this->operator=");
+    validate(rhs, "rhs.operator=");
 #endif
     mBounds = rhs.mBounds;
     mStorage = rhs.mStorage;
@@ -366,6 +370,12 @@
         const Region& lhs,
         const Region& rhs, int dx, int dy)
 {
+#if VALIDATE_REGIONS
+    validate(lhs, "boolean_operation (before): lhs");
+    validate(rhs, "boolean_operation (before): rhs");
+    validate(dst, "boolean_operation (before): dst");
+#endif
+
     size_t lhs_count;
     Rect const * const lhs_rects = lhs.getArray(&lhs_count);
 
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index 7ce86b3..75f7078 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -340,7 +340,10 @@
     }
     
     if (gEGLDebugLevel > 0)
-        StartDebugServer();
+    {
+        property_get("debug.egl.debug_port", value, "5039");
+        StartDebugServer(atoi(value));
+    }
 }
 
 static void setGLHooksThreadSpecific(gl_hooks_t const *value) {
@@ -350,7 +353,6 @@
     } else if (gEGLDebugLevel > 0 && value != &gHooksNoContext) {
         setGlTraceThreadSpecific(value);
         setGlThreadSpecific(&gHooksDebug);
-        LOGD("\n* setGLHooksThreadSpecific gHooksDebug");
     } else {
         setGlThreadSpecific(value);
     }
@@ -2119,14 +2121,15 @@
     if (!validate_display_context(dpy, ctx))
         return EGL_FALSE;
 
+    EGLBoolean result = EGL_FALSE;
     egl_context_t * const c = get_context(ctx);
-
     if (c->cnx->egl.eglDestroySyncKHR) {
-        return c->cnx->egl.eglDestroySyncKHR(
+        result = c->cnx->egl.eglDestroySyncKHR(
                 dp->disp[c->impl].dpy, syncObject->sync);
+        if (result)
+            _s.terminate();
     }
-
-    return EGL_FALSE;
+    return result;
 }
 
 EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout)
diff --git a/opengl/libs/GLES2_dbg/generate_debugger_message_proto.py b/opengl/libs/GLES2_dbg/generate_debugger_message_proto.py
index b14885b..48a29da 100755
--- a/opengl/libs/GLES2_dbg/generate_debugger_message_proto.py
+++ b/opengl/libs/GLES2_dbg/generate_debugger_message_proto.py
@@ -98,9 +98,6 @@
     output.write("        SETPROP = %d;\n" % (i))
     i += 1
     
-    output.write("        CAPTURE = %d;\n" % (i))
-    i += 1
-
     output.write("""    }
     required Function function = 2 [default = NEG]; // type/function of message
     enum Type
diff --git a/opengl/libs/GLES2_dbg/src/dbgcontext.cpp b/opengl/libs/GLES2_dbg/src/dbgcontext.cpp
index 68514df..5c41825 100644
--- a/opengl/libs/GLES2_dbg/src/dbgcontext.cpp
+++ b/opengl/libs/GLES2_dbg/src/dbgcontext.cpp
@@ -65,8 +65,9 @@
 
 void DbgContext::glUseProgram(GLuint program)
 {
-    assert(GL_NO_ERROR == hooks->gl.glGetError());
-
+    while (GLenum error = hooks->gl.glGetError())
+        LOGD("DbgContext::glUseProgram: before glGetError() = 0x%.4X", error);
+        
     this->program = program;
 
     GLint activeAttributes = 0;
@@ -106,6 +107,9 @@
             maxAttrib = slot;
     }
     delete name;
+    
+    while (GLenum error = hooks->gl.glGetError())
+        LOGD("DbgContext::glUseProgram: after glGetError() = 0x%.4X", error);
 }
 
 static bool HasNonVBOAttribs(const DbgContext * const ctx)
diff --git a/opengl/libs/GLES2_dbg/src/debugger_message.pb.cpp b/opengl/libs/GLES2_dbg/src/debugger_message.pb.cpp
index 4083c44..1f404c2 100644
--- a/opengl/libs/GLES2_dbg/src/debugger_message.pb.cpp
+++ b/opengl/libs/GLES2_dbg/src/debugger_message.pb.cpp
@@ -229,7 +229,6 @@
     case 188:
     case 189:
     case 190:
-    case 191:
       return true;
     default:
       return false;
@@ -428,7 +427,6 @@
 const Message_Function Message::CONTINUE;
 const Message_Function Message::SKIP;
 const Message_Function Message::SETPROP;
-const Message_Function Message::CAPTURE;
 const Message_Function Message::Function_MIN;
 const Message_Function Message::Function_MAX;
 const int Message::Function_ARRAYSIZE;
diff --git a/opengl/libs/GLES2_dbg/src/debugger_message.pb.h b/opengl/libs/GLES2_dbg/src/debugger_message.pb.h
index 3f2b842..59e7bab 100644
--- a/opengl/libs/GLES2_dbg/src/debugger_message.pb.h
+++ b/opengl/libs/GLES2_dbg/src/debugger_message.pb.h
@@ -226,12 +226,11 @@
   Message_Function_NEG = 187,
   Message_Function_CONTINUE = 188,
   Message_Function_SKIP = 189,
-  Message_Function_SETPROP = 190,
-  Message_Function_CAPTURE = 191
+  Message_Function_SETPROP = 190
 };
 bool Message_Function_IsValid(int value);
 const Message_Function Message_Function_Function_MIN = Message_Function_glActiveTexture;
-const Message_Function Message_Function_Function_MAX = Message_Function_CAPTURE;
+const Message_Function Message_Function_Function_MAX = Message_Function_SETPROP;
 const int Message_Function_Function_ARRAYSIZE = Message_Function_Function_MAX + 1;
 
 enum Message_Type {
@@ -488,7 +487,6 @@
   static const Function CONTINUE = Message_Function_CONTINUE;
   static const Function SKIP = Message_Function_SKIP;
   static const Function SETPROP = Message_Function_SETPROP;
-  static const Function CAPTURE = Message_Function_CAPTURE;
   static inline bool Function_IsValid(int value) {
     return Message_Function_IsValid(value);
   }
diff --git a/opengl/libs/GLES2_dbg/src/egl.cpp b/opengl/libs/GLES2_dbg/src/egl.cpp
index b3979a3..27c7f7e 100644
--- a/opengl/libs/GLES2_dbg/src/egl.cpp
+++ b/opengl/libs/GLES2_dbg/src/egl.cpp
@@ -19,7 +19,7 @@
 EGLBoolean Debug_eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
 {
     glesv2debugger::Message msg;
-    const bool expectResponse = true;
+    const bool expectResponse = false;
     struct : public FunctionCall {
         EGLDisplay dpy;
         EGLSurface draw;
diff --git a/opengl/libs/GLES2_dbg/src/header.h b/opengl/libs/GLES2_dbg/src/header.h
index cbd448a..b79cc0f 100644
--- a/opengl/libs/GLES2_dbg/src/header.h
+++ b/opengl/libs/GLES2_dbg/src/header.h
@@ -113,7 +113,7 @@
     virtual ~FunctionCall() {}
 };
 
-// move these into DbgContext
+// move these into DbgContext as static
 extern bool capture;
 extern int timeMode; // SYSTEM_TIME_
 
@@ -121,8 +121,10 @@
 
 unsigned GetBytesPerPixel(const GLenum format, const GLenum type);
 
+// every Debug_gl* function calls this to send message to client and possibly receive commands
 int * MessageLoop(FunctionCall & functionCall, glesv2debugger::Message & msg,
                   const bool expectResponse, const glesv2debugger::Message_Function function);
+
 void Receive(glesv2debugger::Message & cmd);
 float Send(const glesv2debugger::Message & msg, glesv2debugger::Message & cmd);
 void SetProp(const glesv2debugger::Message & cmd);
diff --git a/opengl/libs/GLES2_dbg/src/server.cpp b/opengl/libs/GLES2_dbg/src/server.cpp
index 820e9de..03c3dae 100644
--- a/opengl/libs/GLES2_dbg/src/server.cpp
+++ b/opengl/libs/GLES2_dbg/src/server.cpp
@@ -38,7 +38,7 @@
     exit(1);
 }
 
-void StartDebugServer()
+void StartDebugServer(unsigned short port)
 {
     LOGD("GLESv2_dbg: StartDebugServer");
     if (serverSock >= 0)
@@ -53,8 +53,8 @@
     }
     /* Construct the server sockaddr_in structure */
     server.sin_family = AF_INET;                  /* Internet/IP */
-    server.sin_addr.s_addr = htonl(INADDR_ANY);   /* Incoming addr */
-    server.sin_port = htons(5039);       /* server port */
+    server.sin_addr.s_addr = htonl(INADDR_LOOPBACK);   /* Incoming addr */
+    server.sin_port = htons(port);       /* server port */
 
     /* Bind the server socket */
     socklen_t sizeofSockaddr_in = sizeof(sockaddr_in);
@@ -79,13 +79,6 @@
 
     LOGD("Client connected: %s\n", inet_ntoa(client.sin_addr));
 //    fcntl(clientSock, F_SETFL, O_NONBLOCK);
-
-    glesv2debugger::Message msg, cmd;
-    msg.set_context_id(0);
-    msg.set_function(glesv2debugger::Message_Function_ACK);
-    msg.set_type(glesv2debugger::Message_Type_Response);
-    msg.set_expect_response(false);
-    Send(msg, cmd);
 }
 
 void StopDebugServer()
@@ -130,6 +123,27 @@
     cmd.ParseFromArray(buffer, len);
 }
 
+bool TryReceive(glesv2debugger::Message & cmd)
+{
+    fd_set readSet;
+    FD_ZERO(&readSet);
+    FD_SET(clientSock, &readSet);
+    timeval timeout;
+    timeout.tv_sec = timeout.tv_usec = 0;
+
+    int rc = select(clientSock + 1, &readSet, NULL, NULL, &timeout);
+    if (rc < 0)
+        Die("failed to select clientSock");
+
+    bool received = false;
+    if (FD_ISSET(clientSock, &readSet)) {
+        LOGD("TryReceive: avaiable for read");
+        Receive(cmd);
+        return true;
+    }
+    return false;
+}
+
 float Send(const glesv2debugger::Message & msg, glesv2debugger::Message & cmd)
 {
     static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
@@ -155,12 +169,18 @@
         Die("Failed to send message");
     }
 
+    // try to receive commands even though not expecting response,
+    // since client can send SETPROP commands anytime
     if (!msg.expect_response()) {
-        pthread_mutex_unlock(&mutex);
-        return t;
-    }
-
-    Receive(cmd);
+        if (TryReceive(cmd)) {
+            LOGD("Send: TryReceived");
+            if (glesv2debugger::Message_Function_SETPROP == cmd.function())
+                LOGD("Send: received SETPROP");
+            else
+                LOGD("Send: received something else");
+        }
+    } else
+        Receive(cmd);
 
     //LOGD("Message sent tid=%lu len=%d", pthread_self(), str.length());
     pthread_mutex_unlock(&mutex);
@@ -193,24 +213,26 @@
     msg.set_type(glesv2debugger::Message_Type_BeforeCall);
     msg.set_expect_response(expectResponse);
     msg.set_function(function);
-    Send(msg, cmd);
     if (!expectResponse)
         cmd.set_function(glesv2debugger::Message_Function_CONTINUE);
+    Send(msg, cmd);
     while (true) {
         msg.Clear();
         nsecs_t c0 = systemTime(timeMode);
         switch (cmd.function()) {
         case glesv2debugger::Message_Function_CONTINUE:
             ret = functionCall(&dbg->hooks->gl, msg);
+            while (GLenum error = dbg->hooks->gl.glGetError())
+                LOGD("Function=%u glGetError() = 0x%.4X", function, error);
             if (!msg.has_time()) // some has output data copy, so time inside call
                 msg.set_time((systemTime(timeMode) - c0) * 1e-6f);
             msg.set_context_id(reinterpret_cast<int>(dbg));
             msg.set_function(function);
             msg.set_type(glesv2debugger::Message_Type_AfterCall);
             msg.set_expect_response(expectResponse);
-            Send(msg, cmd);
             if (!expectResponse)
                 cmd.set_function(glesv2debugger::Message_Function_SKIP);
+            Send(msg, cmd);
             break;
         case glesv2debugger::Message_Function_SKIP:
             return const_cast<int *>(ret);
diff --git a/opengl/libs/GLES2_dbg/src/vertex.cpp b/opengl/libs/GLES2_dbg/src/vertex.cpp
index 52ce907..a73967f 100644
--- a/opengl/libs/GLES2_dbg/src/vertex.cpp
+++ b/opengl/libs/GLES2_dbg/src/vertex.cpp
@@ -41,10 +41,10 @@
     msg.set_arg6(reinterpret_cast<int>(pixels));
     //void * data = NULL;
     //unsigned encodedSize = 0;
-    Send(msg, cmd);
-    float t = 0;
     if (!expectResponse)
         cmd.set_function(glesv2debugger::Message_Function_CONTINUE);
+    Send(msg, cmd);
+    float t = 0;
     while (true) {
         msg.Clear();
         nsecs_t c0 = systemTime(timeMode);
@@ -61,6 +61,8 @@
             //msg.set_data(data, encodedSize);
             //free(data);
             c0 = systemTime(timeMode);
+            if (!expectResponse)
+                cmd.set_function(glesv2debugger::Message_Function_SKIP);
             t = Send(msg, cmd);
             msg.set_time((systemTime(timeMode) - c0) * 1e-6f);
             msg.set_clock(t);
@@ -69,11 +71,13 @@
             msg.set_expect_response(false);
             msg.set_type(glesv2debugger::Message_Type_AfterCall);
             //Send(msg, cmd);
-            if (!expectResponse)
-                cmd.set_function(glesv2debugger::Message_Function_SKIP);
             break;
         case glesv2debugger::Message_Function_SKIP:
             return;
+        case glesv2debugger::Message_Function_SETPROP:
+            SetProp(cmd);
+            Receive(cmd);
+            break;
         default:
             assert(0); //GenerateCall(msg, cmd);
             break;
@@ -104,9 +108,9 @@
     void * pixels = NULL;
     GLint readFormat = 0, readType = 0;
     int viewport[4] = {};
-    Send(msg, cmd);
     if (!expectResponse)
         cmd.set_function(glesv2debugger::Message_Function_CONTINUE);
+    Send(msg, cmd);
     while (true) {
         msg.Clear();
         nsecs_t c0 = systemTime(timeMode);
@@ -118,25 +122,26 @@
             msg.set_function(glesv2debugger::Message_Function_glDrawArrays);
             msg.set_type(glesv2debugger::Message_Type_AfterCall);
             msg.set_expect_response(expectResponse);
-            Send(msg, cmd);
-            if (capture)
-                cmd.set_function(glesv2debugger::Message_Function_CAPTURE);
-            else if (!expectResponse)
+            if (!expectResponse)
                 cmd.set_function(glesv2debugger::Message_Function_SKIP);
+            Send(msg, cmd);
+            if (capture) {
+                dbg->hooks->gl.glGetIntegerv(GL_VIEWPORT, viewport);
+                dbg->hooks->gl.glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &readFormat);
+                dbg->hooks->gl.glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &readType);
+                LOGD("glDrawArrays CAPTURE: x=%d y=%d width=%d height=%d format=0x%.4X type=0x%.4X",
+                     viewport[0], viewport[1], viewport[2], viewport[3], readFormat, readType);
+                pixels = malloc(viewport[2] * viewport[3] * 4);
+                Debug_glReadPixels(viewport[0], viewport[1], viewport[2], viewport[3],
+                                   readFormat, readType, pixels);
+                free(pixels);
+            }
             break;
         case glesv2debugger::Message_Function_SKIP:
             return;
-        case glesv2debugger::Message_Function_CAPTURE:
-            dbg->hooks->gl.glGetIntegerv(GL_VIEWPORT, viewport);
-            dbg->hooks->gl.glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &readFormat);
-            dbg->hooks->gl.glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &readType);
-            LOGD("glDrawArrays CAPTURE: x=%d y=%d width=%d height=%d format=0x%.4X type=0x%.4X",
-                 viewport[0], viewport[1], viewport[2], viewport[3], readFormat, readType);
-            pixels = malloc(viewport[2] * viewport[3] * 4);
-            Debug_glReadPixels(viewport[0], viewport[1], viewport[2], viewport[3],
-                               readFormat, readType, pixels);
-            free(pixels);
-            cmd.set_function(glesv2debugger::Message_Function_SKIP);
+        case glesv2debugger::Message_Function_SETPROP:
+            SetProp(cmd);
+            Receive(cmd);
             break;
         default:
             assert(0); //GenerateCall(msg, cmd);
@@ -189,9 +194,9 @@
     void * pixels = NULL;
     GLint readFormat = 0, readType = 0;
     int viewport[4] = {};
-    Send(msg, cmd);
     if (!expectResponse)
         cmd.set_function(glesv2debugger::Message_Function_CONTINUE);
+    Send(msg, cmd);
     while (true) {
         msg.Clear();
         nsecs_t c0 = systemTime(timeMode);
@@ -203,25 +208,26 @@
             msg.set_function(glesv2debugger::Message_Function_glDrawElements);
             msg.set_type(glesv2debugger::Message_Type_AfterCall);
             msg.set_expect_response(expectResponse);
-            Send(msg, cmd);
-            if (capture)
-                cmd.set_function(glesv2debugger::Message_Function_CAPTURE);
-            else if (!expectResponse)
+            if (!expectResponse)
                 cmd.set_function(glesv2debugger::Message_Function_SKIP);
+            Send(msg, cmd);
+            if (capture) {
+                dbg->hooks->gl.glGetIntegerv(GL_VIEWPORT, viewport);
+                dbg->hooks->gl.glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &readFormat);
+                dbg->hooks->gl.glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &readType);
+                LOGD("glDrawArrays CAPTURE: x=%d y=%d width=%d height=%d format=0x%.4X type=0x%.4X",
+                     viewport[0], viewport[1], viewport[2], viewport[3], readFormat, readType);
+                pixels = malloc(viewport[2] * viewport[3] * 4);
+                Debug_glReadPixels(viewport[0], viewport[1], viewport[2], viewport[3],
+                                   readFormat, readType, pixels);
+                free(pixels);
+            }
             break;
         case glesv2debugger::Message_Function_SKIP:
             return;
-        case glesv2debugger::Message_Function_CAPTURE:
-            dbg->hooks->gl.glGetIntegerv(GL_VIEWPORT, viewport);
-            dbg->hooks->gl.glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &readFormat);
-            dbg->hooks->gl.glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &readType);
-            LOGD("glDrawArrays CAPTURE: x=%d y=%d width=%d height=%d format=0x%.4X type=0x%.4X",
-                 viewport[0], viewport[1], viewport[2], viewport[3], readFormat, readType);
-            pixels = malloc(viewport[2] * viewport[3] * 4);
-            Debug_glReadPixels(viewport[0], viewport[1], viewport[2], viewport[3],
-                               readFormat, readType, pixels);
-            free(pixels);
-            cmd.set_function(glesv2debugger::Message_Function_SKIP);
+        case glesv2debugger::Message_Function_SETPROP:
+            SetProp(cmd);
+            Receive(cmd);
             break;
         default:
             assert(0); //GenerateCall(msg, cmd);
diff --git a/opengl/libs/glesv2dbg.h b/opengl/libs/glesv2dbg.h
index b988eb7..8029dce 100644
--- a/opengl/libs/glesv2dbg.h
+++ b/opengl/libs/glesv2dbg.h
@@ -24,7 +24,7 @@
     DbgContext * CreateDbgContext(const unsigned version, const gl_hooks_t * const hooks);
     void DestroyDbgContext(DbgContext * const dbg);
     
-    void StartDebugServer(); // create and bind socket if haven't already
+    void StartDebugServer(unsigned short port); // create and bind socket if haven't already
     void StopDebugServer(); // close socket if open
     
 }; // namespace android
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 7a69097..78ee07e 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -860,11 +860,13 @@
     Mutex::Autolock _l(mLock);
 
     if (size < mNumBuffers) {
-        // Move the active texture into slot 0
-        BufferData activeBufferData = mBufferData[mActiveBufferIndex];
-        mBufferData[mActiveBufferIndex] = mBufferData[0];
-        mBufferData[0] = activeBufferData;
-        mActiveBufferIndex = 0;
+        // If there is an active texture, move it into slot 0 if needed
+        if (mActiveBufferIndex > 0) {
+            BufferData activeBufferData = mBufferData[mActiveBufferIndex];
+            mBufferData[mActiveBufferIndex] = mBufferData[0];
+            mBufferData[0] = activeBufferData;
+            mActiveBufferIndex = 0;
+        }
 
         // Free the buffers that are no longer needed.
         for (size_t i = size; i < mNumBuffers; i++) {
diff --git a/services/surfaceflinger/tests/resize/resize.cpp b/services/surfaceflinger/tests/resize/resize.cpp
index 99f4b4f..0ccca77 100644
--- a/services/surfaceflinger/tests/resize/resize.cpp
+++ b/services/surfaceflinger/tests/resize/resize.cpp
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
 #include <cutils/memory.h>
 
 #include <utils/Log.h>
diff --git a/services/surfaceflinger/tests/surface/surface.cpp b/services/surfaceflinger/tests/surface/surface.cpp
index 194fbb6..67ecf7e 100644
--- a/services/surfaceflinger/tests/surface/surface.cpp
+++ b/services/surfaceflinger/tests/surface/surface.cpp
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
 #include <cutils/memory.h>
 
 #include <utils/Log.h>