Surface: Add LAST_[DE]QUEUE_DURATION queries

Adds support for the NATIVE_WINDOW_LAST_DEQUEUE_DURATION and
NATIVE_WINDOW_LAST_QUEUE_DURATION queries.

Bug: 29413700
Change-Id: Iea4efa208e8390fb2de52d5ad9f083ae91bf50b0
diff --git a/include/gui/Surface.h b/include/gui/Surface.h
index af9dd50..b9ffc49 100644
--- a/include/gui/Surface.h
+++ b/include/gui/Surface.h
@@ -198,7 +198,6 @@
     virtual int cancelBuffer(ANativeWindowBuffer* buffer, int fenceFd);
     virtual int queueBuffer(ANativeWindowBuffer* buffer, int fenceFd);
     virtual int perform(int operation, va_list args);
-    virtual int query(int what, int* value) const;
     virtual int setSwapInterval(int interval);
 
     virtual int lockBuffer_DEPRECATED(ANativeWindowBuffer* buffer);
@@ -224,6 +223,7 @@
     virtual int setAutoRefresh(bool autoRefresh);
     virtual int lock(ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds);
     virtual int unlockAndPost();
+    virtual int query(int what, int* value) const;
 
     virtual int connect(int api, const sp<IProducerListener>& listener);
     virtual int detachNextBuffer(sp<GraphicBuffer>* outBuffer,
@@ -370,6 +370,10 @@
     // used to prevent a mismatch between the number of queue/dequeue calls.
     bool mSharedBufferHasBeenQueued;
 
+    // These are used to satisfy the NATIVE_WINDOW_LAST_*_DURATION queries
+    nsecs_t mLastDequeueDuration = 0;
+    nsecs_t mLastQueueDuration = 0;
+
     Condition mQueueBufferCondition;
 };
 
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 9760a0e..af55913 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -292,8 +292,10 @@
 
     int buf = -1;
     sp<Fence> fence;
+    nsecs_t now = systemTime();
     status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence,
             reqWidth, reqHeight, reqFormat, reqUsage);
+    mLastDequeueDuration = systemTime() - now;
 
     if (result < 0) {
         ALOGV("dequeueBuffer: IGraphicBufferProducer::dequeueBuffer"
@@ -496,7 +498,9 @@
         input.setSurfaceDamage(flippedRegion);
     }
 
+    nsecs_t now = systemTime();
     status_t err = mGraphicBufferProducer->queueBuffer(i, input, &output);
+    mLastQueueDuration = systemTime() - now;
     if (err != OK)  {
         ALOGE("queueBuffer: error queuing buffer to SurfaceTexture, %d", err);
     }
@@ -575,6 +579,20 @@
                 }
                 return err;
             }
+            case NATIVE_WINDOW_LAST_DEQUEUE_DURATION: {
+                int64_t durationUs = mLastDequeueDuration / 1000;
+                *value = durationUs > std::numeric_limits<int>::max() ?
+                        std::numeric_limits<int>::max() :
+                        static_cast<int>(durationUs);
+                return NO_ERROR;
+            }
+            case NATIVE_WINDOW_LAST_QUEUE_DURATION: {
+                int64_t durationUs = mLastQueueDuration / 1000;
+                *value = durationUs > std::numeric_limits<int>::max() ?
+                        std::numeric_limits<int>::max() :
+                        static_cast<int>(durationUs);
+                return NO_ERROR;
+            }
         }
     }
     return mGraphicBufferProducer->query(what, value);