Merge "Add a boardconfig to force HWC composition of virtual displays" into klp-dev
diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp
index c165a68..2aecb67 100644
--- a/libs/gui/BufferQueue.cpp
+++ b/libs/gui/BufferQueue.cpp
@@ -644,6 +644,7 @@
             producerControlledByApp ? "true" : "false");
     Mutex::Autolock lock(mMutex);
 
+retry:
     if (mAbandoned) {
         ST_LOGE("connect: BufferQueue has been abandoned!");
         return NO_INIT;
@@ -654,29 +655,41 @@
         return NO_INIT;
     }
 
+    if (mConnectedApi != NO_CONNECTED_API) {
+        ST_LOGE("connect: already connected (cur=%d, req=%d)",
+                mConnectedApi, api);
+        return -EINVAL;
+    }
+
+    // If we disconnect and reconnect quickly, we can be in a state where our slots are
+    // empty but we have many buffers in the queue.  This can cause us to run out of
+    // memory if we outrun the consumer.  Wait here if it looks like we have too many
+    // buffers queued up.
+    int maxBufferCount = getMaxBufferCountLocked(false);    // worst-case, i.e. largest value
+    if (mQueue.size() > (size_t) maxBufferCount) {
+        // TODO: make this bound tighter?
+        ST_LOGV("queue size is %d, waiting", mQueue.size());
+        mDequeueCondition.wait(mMutex);
+        goto retry;
+    }
+
     int err = NO_ERROR;
     switch (api) {
         case NATIVE_WINDOW_API_EGL:
         case NATIVE_WINDOW_API_CPU:
         case NATIVE_WINDOW_API_MEDIA:
         case NATIVE_WINDOW_API_CAMERA:
-            if (mConnectedApi != NO_CONNECTED_API) {
-                ST_LOGE("connect: already connected (cur=%d, req=%d)",
-                        mConnectedApi, api);
-                err = -EINVAL;
-            } else {
-                mConnectedApi = api;
-                output->inflate(mDefaultWidth, mDefaultHeight, mTransformHint, mQueue.size());
+            mConnectedApi = api;
+            output->inflate(mDefaultWidth, mDefaultHeight, mTransformHint, mQueue.size());
 
-                // set-up a death notification so that we can disconnect
-                // automatically when/if the remote producer dies.
-                if (token != NULL && token->remoteBinder() != NULL) {
-                    status_t err = token->linkToDeath(static_cast<IBinder::DeathRecipient*>(this));
-                    if (err == NO_ERROR) {
-                        mConnectedProducerToken = token;
-                    } else {
-                        ALOGE("linkToDeath failed: %s (%d)", strerror(-err), err);
-                    }
+            // set-up a death notification so that we can disconnect
+            // automatically when/if the remote producer dies.
+            if (token != NULL && token->remoteBinder() != NULL) {
+                status_t err = token->linkToDeath(static_cast<IBinder::DeathRecipient*>(this));
+                if (err == NO_ERROR) {
+                    mConnectedProducerToken = token;
+                } else {
+                    ALOGE("linkToDeath failed: %s (%d)", strerror(-err), err);
                 }
             }
             break;
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index 9bd7fc6..09b2e7c 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -511,14 +511,17 @@
     status_t result;
     for (size_t i = mBatches.size(); i-- > 0; ) {
         Batch& batch = mBatches.editItemAt(i);
-        if (frameTime < 0 || !mResampleTouch) {
+        if (frameTime < 0) {
             result = consumeSamples(factory, batch, batch.samples.size(),
                     outSeq, outEvent);
             mBatches.removeAt(i);
             return result;
         }
 
-        nsecs_t sampleTime = frameTime - RESAMPLE_LATENCY;
+        nsecs_t sampleTime = frameTime;
+        if (mResampleTouch) {
+            sampleTime -= RESAMPLE_LATENCY;
+        }
         ssize_t split = findSampleNoLaterThan(batch, sampleTime);
         if (split < 0) {
             continue;
@@ -532,7 +535,7 @@
         } else {
             next = &batch.samples.itemAt(0);
         }
-        if (!result) {
+        if (!result && mResampleTouch) {
             resampleTouchState(sampleTime, static_cast<MotionEvent*>(*outEvent), next);
         }
         return result;