add a way to query whether an ANativeWindow consumer is running ahead of the producer

Change-Id: Ibccfa1feb56db2ab11f0c0934ce2d570a2b65ae2
diff --git a/include/gui/ISurfaceTexture.h b/include/gui/ISurfaceTexture.h
index 929eda2..1e33764 100644
--- a/include/gui/ISurfaceTexture.h
+++ b/include/gui/ISurfaceTexture.h
@@ -107,21 +107,26 @@
     struct QueueBufferOutput {
         inline QueueBufferOutput() { }
         inline void deflate(uint32_t* outWidth,
-                uint32_t* outHeight, uint32_t* outTransformHint) const {
+                uint32_t* outHeight,
+                uint32_t* outTransformHint,
+                uint32_t* outNumPendingBuffers) const {
             *outWidth = width;
             *outHeight = height;
             *outTransformHint = transformHint;
+            *outNumPendingBuffers = numPendingBuffers;
         }
         inline void inflate(uint32_t inWidth, uint32_t inHeight,
-                uint32_t inTransformHint) {
+                uint32_t inTransformHint, uint32_t inNumPendingBuffers) {
             width = inWidth;
             height = inHeight;
             transformHint = inTransformHint;
+            numPendingBuffers = inNumPendingBuffers;
         }
     private:
         uint32_t width;
         uint32_t height;
         uint32_t transformHint;
+        uint32_t numPendingBuffers;
     };
 
     virtual status_t queueBuffer(int slot,
diff --git a/include/gui/SurfaceTextureClient.h b/include/gui/SurfaceTextureClient.h
index 6644751..7fd9be5 100644
--- a/include/gui/SurfaceTextureClient.h
+++ b/include/gui/SurfaceTextureClient.h
@@ -187,6 +187,10 @@
     // window. this is only a hint, actual transform may differ.
     uint32_t mTransformHint;
 
+    // mConsumerRunningBehind whether the consumer is running more than
+    // one buffer behind the producer.
+    mutable bool mConsumerRunningBehind;
+
     // 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/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp
index 5941dc2..39e9724 100644
--- a/libs/gui/BufferQueue.cpp
+++ b/libs/gui/BufferQueue.cpp
@@ -252,6 +252,9 @@
         value = mSynchronousMode ?
                 (mMinUndequeuedBuffers-1) : mMinUndequeuedBuffers;
         break;
+    case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND:
+        value = (mQueue.size() >= 2);
+        break;
     default:
         return BAD_VALUE;
     }
@@ -615,7 +618,8 @@
         mBufferHasBeenQueued = true;
         mDequeueCondition.broadcast();
 
-        output->inflate(mDefaultWidth, mDefaultHeight, mTransformHint);
+        output->inflate(mDefaultWidth, mDefaultHeight, mTransformHint,
+                mQueue.size());
 
         ATRACE_INT(mConsumerName.string(), mQueue.size());
     } // scope for the lock
@@ -678,7 +682,8 @@
                 err = -EINVAL;
             } else {
                 mConnectedApi = api;
-                output->inflate(mDefaultWidth, mDefaultHeight, mDefaultHeight);
+                output->inflate(mDefaultWidth, mDefaultHeight, mTransformHint,
+                        mQueue.size());
             }
             break;
         default:
diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp
index 48d3b6f..788524b 100644
--- a/libs/gui/SurfaceTextureClient.cpp
+++ b/libs/gui/SurfaceTextureClient.cpp
@@ -83,6 +83,7 @@
     mUserWidth = 0;
     mUserHeight = 0;
     mTransformHint = 0;
+    mConsumerRunningBehind = false;
     mConnectedToCpu = false;
 }
 
@@ -243,7 +244,12 @@
     if (err != OK)  {
         ALOGE("queueBuffer: error queuing buffer to SurfaceTexture, %d", err);
     }
-    output.deflate(&mDefaultWidth, &mDefaultHeight, &mTransformHint);
+    uint32_t numPendingBuffers = 0;
+    output.deflate(&mDefaultWidth, &mDefaultHeight, &mTransformHint,
+            &numPendingBuffers);
+
+    mConsumerRunningBehind = (numPendingBuffers >= 2);
+
     return err;
 }
 
@@ -259,17 +265,16 @@
                     return NO_ERROR;
                 }
                 break;
-            case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER:
-                {
-                    sp<ISurfaceComposer> composer(
-                            ComposerService::getComposerService());
-                    if (composer->authenticateSurfaceTexture(mSurfaceTexture)) {
-                        *value = 1;
-                    } else {
-                        *value = 0;
-                    }
+            case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER: {
+                sp<ISurfaceComposer> composer(
+                        ComposerService::getComposerService());
+                if (composer->authenticateSurfaceTexture(mSurfaceTexture)) {
+                    *value = 1;
+                } else {
+                    *value = 0;
                 }
                 return NO_ERROR;
+            }
             case NATIVE_WINDOW_CONCRETE_TYPE:
                 *value = NATIVE_WINDOW_SURFACE_TEXTURE_CLIENT;
                 return NO_ERROR;
@@ -282,6 +287,18 @@
             case NATIVE_WINDOW_TRANSFORM_HINT:
                 *value = mTransformHint;
                 return NO_ERROR;
+            case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND: {
+                status_t err = NO_ERROR;
+                if (!mConsumerRunningBehind) {
+                    *value = 0;
+                } else {
+                    err = mSurfaceTexture->query(what, value);
+                    if (err == NO_ERROR) {
+                        mConsumerRunningBehind = *value;
+                    }
+                }
+                return err;
+            }
         }
     }
     return mSurfaceTexture->query(what, value);
@@ -431,7 +448,12 @@
     Mutex::Autolock lock(mMutex);
     ISurfaceTexture::QueueBufferOutput output;
     int err = mSurfaceTexture->connect(api, &output);
-    output.deflate(&mDefaultWidth, &mDefaultHeight, &mTransformHint);
+    if (err == NO_ERROR) {
+        uint32_t numPendingBuffers = 0;
+        output.deflate(&mDefaultWidth, &mDefaultHeight, &mTransformHint,
+                &numPendingBuffers);
+        mConsumerRunningBehind = (numPendingBuffers >= 2);
+    }
     if (!err && api == NATIVE_WINDOW_API_CPU) {
         mConnectedToCpu = true;
     }