egl: Differentiate pending vs invalid timestamps.

Test: adb shell /data/nativetest/libgui_test/libgui_test
    --gtest_filter=*GetFrameTimestamps*

Change-Id: Iaa418ff1753a4339bfefaa68a6b03e8c96366a87
diff --git a/include/gui/FrameTimestamps.h b/include/gui/FrameTimestamps.h
index 92251ed..9716be4 100644
--- a/include/gui/FrameTimestamps.h
+++ b/include/gui/FrameTimestamps.h
@@ -54,8 +54,7 @@
     static constexpr auto EVENT_COUNT =
             static_cast<size_t>(FrameEvent::EVENT_COUNT);
     static_assert(EVENT_COUNT <= 32, "Event count sanity check failed.");
-    static constexpr nsecs_t TIMESTAMP_PENDING =
-            std::numeric_limits<nsecs_t>::max();
+    static constexpr nsecs_t TIMESTAMP_PENDING = -2;
 
     static inline bool isValidTimestamp(nsecs_t time) {
         return time != TIMESTAMP_PENDING;
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 41221aa..a6d9e66 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -229,14 +229,26 @@
 
 static void getFrameTimestamp(nsecs_t *dst, const nsecs_t& src) {
     if (dst != nullptr) {
-        *dst = FrameEvents::isValidTimestamp(src) ? src : 0;
+        // We always get valid timestamps for these eventually.
+        *dst = (src == FrameEvents::TIMESTAMP_PENDING) ?
+                NATIVE_WINDOW_TIMESTAMP_PENDING : src;
     }
 }
 
-static void getFrameTimestampFence(nsecs_t *dst, const std::shared_ptr<FenceTime>& src) {
+static void getFrameTimestampFence(nsecs_t *dst,
+        const std::shared_ptr<FenceTime>& src, bool fenceShouldBeKnown) {
     if (dst != nullptr) {
+        if (!fenceShouldBeKnown) {
+            *dst = NATIVE_WINDOW_TIMESTAMP_PENDING;
+            return;
+        }
+
         nsecs_t signalTime = src->getSignalTime();
-        *dst = Fence::isValidTimestamp(signalTime) ? signalTime : 0;
+        *dst = (signalTime == Fence::SIGNAL_TIME_PENDING) ?
+                    NATIVE_WINDOW_TIMESTAMP_PENDING :
+                (signalTime == Fence::SIGNAL_TIME_INVALID) ?
+                    NATIVE_WINDOW_TIMESTAMP_INVALID :
+                signalTime;
     }
 }
 
@@ -290,12 +302,15 @@
     getFrameTimestamp(outLastRefreshStartTime, events->lastRefreshStartTime);
     getFrameTimestamp(outDequeueReadyTime, events->dequeueReadyTime);
 
-    getFrameTimestampFence(outAcquireTime, events->acquireFence);
-    getFrameTimestampFence(
-            outGpuCompositionDoneTime, events->gpuCompositionDoneFence);
-    getFrameTimestampFence(
-            outDisplayPresentTime, events->displayPresentFence);
-    getFrameTimestampFence(outReleaseTime, events->releaseFence);
+    getFrameTimestampFence(outAcquireTime, events->acquireFence,
+            events->hasAcquireInfo());
+    getFrameTimestampFence(outGpuCompositionDoneTime,
+            events->gpuCompositionDoneFence,
+            events->hasGpuCompositionDoneInfo());
+    getFrameTimestampFence(outDisplayPresentTime, events->displayPresentFence,
+            events->hasDisplayPresentInfo());
+    getFrameTimestampFence(outReleaseTime, events->releaseFence,
+            events->hasReleaseInfo());
 
     return NO_ERROR;
 }
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 00a374d..cf3d1b2 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -1184,8 +1184,8 @@
     EXPECT_EQ(mFrames[1].mRefreshes[0].kGpuCompositionDoneTime,
             outGpuCompositionDoneTime);
     EXPECT_EQ(mFrames[1].mRefreshes[0].kPresentTime, outDisplayPresentTime);
-    EXPECT_EQ(0, outDequeueReadyTime);
-    EXPECT_EQ(0, outReleaseTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outDequeueReadyTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outReleaseTime);
 }
 
 // This test verifies the acquire fence recorded by the consumer is not sent
@@ -1208,7 +1208,7 @@
     EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount);
     EXPECT_EQ(NO_ERROR, result);
     EXPECT_EQ(mFrames[0].kRequestedPresentTime, outRequestedPresentTime);
-    EXPECT_EQ(0, outAcquireTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outAcquireTime);
 
     // Signal acquire fences. Verify a sync call still isn't necessary.
     mFrames[0].signalQueueFences();
@@ -1237,7 +1237,7 @@
     EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount);
     EXPECT_EQ(NO_ERROR, result);
     EXPECT_EQ(mFrames[1].kRequestedPresentTime, outRequestedPresentTime);
-    EXPECT_EQ(0, outAcquireTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outAcquireTime);
 
     // Signal acquire fences. Verify a sync call still isn't necessary.
     mFrames[1].signalQueueFences();
@@ -1310,10 +1310,10 @@
     EXPECT_EQ(mFrames[0].kLatchTime, outLatchTime);
     EXPECT_EQ(mFrames[0].mRefreshes[0].kStartTime, outFirstRefreshStartTime);
     EXPECT_EQ(mFrames[0].mRefreshes[2].kStartTime, outLastRefreshStartTime);
-    EXPECT_EQ(0, outGpuCompositionDoneTime);
-    EXPECT_EQ(0, outDisplayPresentTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outGpuCompositionDoneTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outDisplayPresentTime);
     EXPECT_EQ(mFrames[0].kDequeueReadyTime, outDequeueReadyTime);
-    EXPECT_EQ(0, outReleaseTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outReleaseTime);
 
     // Verify available timestamps are correct for frame 1 again, before any
     // fence has been signaled.
@@ -1328,10 +1328,10 @@
     EXPECT_EQ(mFrames[0].kLatchTime, outLatchTime);
     EXPECT_EQ(mFrames[0].mRefreshes[0].kStartTime, outFirstRefreshStartTime);
     EXPECT_EQ(mFrames[0].mRefreshes[2].kStartTime, outLastRefreshStartTime);
-    EXPECT_EQ(0, outGpuCompositionDoneTime);
-    EXPECT_EQ(0, outDisplayPresentTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outGpuCompositionDoneTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outDisplayPresentTime);
     EXPECT_EQ(mFrames[0].kDequeueReadyTime, outDequeueReadyTime);
-    EXPECT_EQ(0, outReleaseTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outReleaseTime);
 
     // Signal the fences for frame 1.
     mFrames[0].signalRefreshFences();
@@ -1387,10 +1387,10 @@
     EXPECT_EQ(mFrames[0].kLatchTime, outLatchTime);
     EXPECT_EQ(mFrames[0].mRefreshes[0].kStartTime, outFirstRefreshStartTime);
     EXPECT_EQ(mFrames[0].mRefreshes[2].kStartTime, outLastRefreshStartTime);
-    EXPECT_EQ(0, outGpuCompositionDoneTime);
-    EXPECT_EQ(0, outDisplayPresentTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_INVALID, outGpuCompositionDoneTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outDisplayPresentTime);
     EXPECT_EQ(mFrames[0].kDequeueReadyTime, outDequeueReadyTime);
-    EXPECT_EQ(0, outReleaseTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outReleaseTime);
 
     // Signal the fences for frame 1.
     mFrames[0].signalRefreshFences();
@@ -1408,7 +1408,7 @@
     EXPECT_EQ(mFrames[0].kLatchTime, outLatchTime);
     EXPECT_EQ(mFrames[0].mRefreshes[0].kStartTime, outFirstRefreshStartTime);
     EXPECT_EQ(mFrames[0].mRefreshes[2].kStartTime, outLastRefreshStartTime);
-    EXPECT_EQ(0, outGpuCompositionDoneTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_INVALID, outGpuCompositionDoneTime);
     EXPECT_EQ(mFrames[0].mRefreshes[0].kPresentTime, outDisplayPresentTime);
     EXPECT_EQ(mFrames[0].kDequeueReadyTime, outDequeueReadyTime);
     EXPECT_EQ(mFrames[0].kReleaseTime, outReleaseTime);
@@ -1446,10 +1446,10 @@
     EXPECT_EQ(mFrames[0].kLatchTime, outLatchTime);
     EXPECT_EQ(mFrames[0].mRefreshes[0].kStartTime, outFirstRefreshStartTime);
     EXPECT_EQ(mFrames[0].mRefreshes[2].kStartTime, outLastRefreshStartTime);
-    EXPECT_EQ(0, outGpuCompositionDoneTime);
-    EXPECT_EQ(0, outDisplayPresentTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_INVALID, outGpuCompositionDoneTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outDisplayPresentTime);
     EXPECT_EQ(mFrames[0].kDequeueReadyTime, outDequeueReadyTime);
-    EXPECT_EQ(0, outReleaseTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outReleaseTime);
 
     mFrames[0].signalRefreshFences();
     mFrames[0].signalReleaseFences();
@@ -1470,10 +1470,10 @@
     EXPECT_EQ(mFrames[1].kLatchTime, outLatchTime);
     EXPECT_EQ(mFrames[1].mRefreshes[0].kStartTime, outFirstRefreshStartTime);
     EXPECT_EQ(mFrames[1].mRefreshes[1].kStartTime, outLastRefreshStartTime);
-    EXPECT_EQ(0, outGpuCompositionDoneTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_INVALID, outGpuCompositionDoneTime);
     EXPECT_EQ(mFrames[1].mRefreshes[0].kPresentTime, outDisplayPresentTime);
-    EXPECT_EQ(0, outDequeueReadyTime);
-    EXPECT_EQ(0, outReleaseTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outDequeueReadyTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outReleaseTime);
 }
 
 // This test verifies there are no sync calls for present times
diff --git a/libs/nativewindow/include/system/window.h b/libs/nativewindow/include/system/window.h
index 0251aed..fb67a51 100644
--- a/libs/nativewindow/include/system/window.h
+++ b/libs/nativewindow/include/system/window.h
@@ -311,6 +311,14 @@
  */
 static const int64_t NATIVE_WINDOW_TIMESTAMP_AUTO = (-9223372036854775807LL-1);
 
+/* parameter for NATIVE_WINDOW_GET_FRAME_TIMESTAMPS
+ *
+ * Special timestamp value to indicate the timestamps aren't yet known or
+ * that they are invalid.
+ */
+static const int64_t NATIVE_WINDOW_TIMESTAMP_PENDING = -2;
+static const int64_t NATIVE_WINDOW_TIMESTAMP_INVALID = -1;
+
 struct ANativeWindow
 {
 #ifdef __cplusplus
diff --git a/opengl/include/EGL/eglext.h b/opengl/include/EGL/eglext.h
index bf831a7..3068029 100644
--- a/opengl/include/EGL/eglext.h
+++ b/opengl/include/EGL/eglext.h
@@ -640,6 +640,8 @@
 #define EGL_DISPLAY_PRESENT_TIME_ANDROID 0x3157
 #define EGL_DEQUEUE_READY_TIME_ANDROID 0x3158
 #define EGL_READS_DONE_TIME_ANDROID 0x3159
+#define EGL_TIMESTAMP_PENDING_ANDROID EGL_CAST(EGLnsecsANDROID, -2)
+#define EGL_TIMESTAMP_INVALID_ANDROID EGL_CAST(EGLnsecsANDROID, -1)
 #ifdef EGL_EGLEXT_PROTOTYPES
 EGLAPI EGLBoolean eglGetNextFrameIdANDROID(EGLDisplay dpy, EGLSurface surface, EGLuint64KHR *frameId);
 EGLAPI EGLBoolean eglGetCompositorTimingANDROID(EGLDisplay dpy, EGLSurface surface, EGLint numTimestamps, const EGLint *names, EGLnsecsANDROID *values);
diff --git a/opengl/specs/EGL_ANDROID_get_frame_timestamps.txt b/opengl/specs/EGL_ANDROID_get_frame_timestamps.txt
index 61b9b66..03b8954 100644
--- a/opengl/specs/EGL_ANDROID_get_frame_timestamps.txt
+++ b/opengl/specs/EGL_ANDROID_get_frame_timestamps.txt
@@ -94,6 +94,8 @@
     EGL_DISPLAY_PRESENT_TIME_ANDROID 0x3157
     EGL_DEQUEUE_READY_TIME_ANDROID 0x3158
     EGL_READS_DONE_TIME_ANDROID 0x3159
+    EGL_TIMESTAMP_PENDING_ANDROID -2
+    EGL_TIMESTAMP_INVALID_ANDROID -1
 
 Add to the list of supported tokens for eglSurfaceAttrib in section 3.5.6
 "Surface Attributes", page 43:
@@ -155,10 +157,12 @@
     limited history of timestamp data. If a query is made for a frame whose
     timestamp history no longer exists then EGL_BAD_ACCESS is generated. If
     timestamp collection has not been enabled for the surface then
-    EGL_BAD_SURFACE is generated.  Timestamps for events that will not occur or
-    have not yet occurred will be zero. Timestamp queries that are not
-    supported will generate an EGL_BAD_PARAMETER error. If any error is
-    generated the function will return EGL_FALSE.
+    EGL_BAD_SURFACE is generated.  Timestamps for events that might still occur
+    will have the value EGL_TIMESTAMP_PENDING_ANDROID. Timestamps for events
+    that did not occur will have the value EGL_TIMESTAMP_INVALID_ANDROID.
+    Otherwise, the timestamp will be valid and indicate the event has occured.
+    Timestamp queries that are not supported will generate an EGL_BAD_PARAMETER
+    error. If any error is generated the function will return EGL_FALSE.
 
     The application can poll for the timestamp of particular events by calling
     eglGetFrameTimestamps over and over without needing to call any other EGL
@@ -222,6 +226,9 @@
 
 Revision History
 
+#7 (Brian Anderson, March 21, 2017)
+    - Differentiate between pending events and events that did not occur.
+
 #6 (Brian Anderson, March 16, 2017)
     - Remove DISPLAY_RETIRE_TIME_ANDROID.
 
diff --git a/vulkan/libvulkan/Android.bp b/vulkan/libvulkan/Android.bp
index 9444da5..a35fb98 100644
--- a/vulkan/libvulkan/Android.bp
+++ b/vulkan/libvulkan/Android.bp
@@ -78,6 +78,7 @@
         "libutils",
         "libcutils",
         "libz",
+        "libnativewindow",
     ],
     static_libs: ["libgrallocusage"],
 }
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 3b785e6..caa2674 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -114,14 +114,34 @@
         : vals_{qp->presentID, qp->desiredPresentTime, 0, 0, 0},
           native_frame_id_(nativeFrameId) {}
     bool ready() const {
-        return (timestamp_desired_present_time_ &&
-                timestamp_actual_present_time_ &&
-                timestamp_render_complete_time_ &&
-                timestamp_composition_latch_time_);
+        return (timestamp_desired_present_time_ !=
+                        NATIVE_WINDOW_TIMESTAMP_PENDING &&
+                timestamp_actual_present_time_ !=
+                        NATIVE_WINDOW_TIMESTAMP_PENDING &&
+                timestamp_render_complete_time_ !=
+                        NATIVE_WINDOW_TIMESTAMP_PENDING &&
+                timestamp_composition_latch_time_ !=
+                        NATIVE_WINDOW_TIMESTAMP_PENDING);
     }
-    void calculate(uint64_t rdur) {
-        vals_.actualPresentTime = timestamp_actual_present_time_;
-        uint64_t margin = (timestamp_composition_latch_time_ -
+    void calculate(int64_t rdur) {
+        bool anyTimestampInvalid =
+                (timestamp_actual_present_time_ ==
+                        NATIVE_WINDOW_TIMESTAMP_INVALID) ||
+                (timestamp_render_complete_time_ ==
+                        NATIVE_WINDOW_TIMESTAMP_INVALID) ||
+                (timestamp_composition_latch_time_ ==
+                        NATIVE_WINDOW_TIMESTAMP_INVALID);
+        if (anyTimestampInvalid) {
+            ALOGE("Unexpectedly received invalid timestamp.");
+            vals_.actualPresentTime = 0;
+            vals_.earliestPresentTime = 0;
+            vals_.presentMargin = 0;
+            return;
+        }
+
+        vals_.actualPresentTime =
+                static_cast<uint64_t>(timestamp_actual_present_time_);
+        int64_t margin = (timestamp_composition_latch_time_ -
                            timestamp_render_complete_time_);
         // Calculate vals_.earliestPresentTime, and potentially adjust
         // vals_.presentMargin.  The initial value of vals_.earliestPresentTime
@@ -132,14 +152,14 @@
         // it did (per the extension specification).  If for some reason, we
         // can do this subtraction repeatedly, we do, since
         // vals_.earliestPresentTime really is supposed to be the "earliest".
-        uint64_t early_time = vals_.actualPresentTime;
+        int64_t early_time = timestamp_actual_present_time_;
         while ((margin > rdur) &&
                ((early_time - rdur) > timestamp_composition_latch_time_)) {
             early_time -= rdur;
             margin -= rdur;
         }
-        vals_.earliestPresentTime = early_time;
-        vals_.presentMargin = margin;
+        vals_.earliestPresentTime = static_cast<uint64_t>(early_time);
+        vals_.presentMargin = static_cast<uint64_t>(margin);
     }
     void get_values(VkPastPresentationTimingGOOGLE* values) const {
         *values = vals_;
@@ -149,10 +169,11 @@
     VkPastPresentationTimingGOOGLE vals_ { 0, 0, 0, 0, 0 };
 
     uint64_t native_frame_id_ { 0 };
-    uint64_t timestamp_desired_present_time_ { 0 };
-    uint64_t timestamp_actual_present_time_ { 0 };
-    uint64_t timestamp_render_complete_time_ { 0 };
-    uint64_t timestamp_composition_latch_time_ { 0 };
+    int64_t timestamp_desired_present_time_{ NATIVE_WINDOW_TIMESTAMP_PENDING };
+    int64_t timestamp_actual_present_time_ { NATIVE_WINDOW_TIMESTAMP_PENDING };
+    int64_t timestamp_render_complete_time_ { NATIVE_WINDOW_TIMESTAMP_PENDING };
+    int64_t timestamp_composition_latch_time_
+            { NATIVE_WINDOW_TIMESTAMP_PENDING };
 };
 
 // ----------------------------------------------------------------------------
@@ -187,18 +208,16 @@
           shared(present_mode == VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR ||
                  present_mode == VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR) {
         ANativeWindow* window = surface.window.get();
-        int64_t rdur;
         native_window_get_refresh_cycle_duration(
             window,
-            &rdur);
-        refresh_duration = static_cast<uint64_t>(rdur);
+            &refresh_duration);
     }
 
     Surface& surface;
     uint32_t num_images;
     bool mailbox_mode;
     bool frame_timestamps_enabled;
-    uint64_t refresh_duration;
+    int64_t refresh_duration;
     bool shared;
 
     struct Image {
@@ -327,14 +346,10 @@
 
         // Record the timestamp(s) we received, and then see if this TimingInfo
         // is ready to be reported to the user:
-        ti.timestamp_desired_present_time_ =
-            static_cast<uint64_t>(desired_present_time);
-        ti.timestamp_actual_present_time_ =
-            static_cast<uint64_t>(actual_present_time);
-        ti.timestamp_render_complete_time_ =
-            static_cast<uint64_t>(render_complete_time);
-        ti.timestamp_composition_latch_time_ =
-               static_cast<uint64_t>(composition_latch_time);
+        ti.timestamp_desired_present_time_ = desired_present_time;
+        ti.timestamp_actual_present_time_ = actual_present_time;
+        ti.timestamp_render_complete_time_ = render_complete_time;
+        ti.timestamp_composition_latch_time_ = composition_latch_time;
 
         if (ti.ready()) {
             // The TimingInfo has received enough timestamps, and should now
@@ -1494,7 +1509,8 @@
     Swapchain& swapchain = *SwapchainFromHandle(swapchain_handle);
     VkResult result = VK_SUCCESS;
 
-    pDisplayTimingProperties->refreshDuration = swapchain.refresh_duration;
+    pDisplayTimingProperties->refreshDuration =
+            static_cast<uint64_t>(swapchain.refresh_duration);
 
     return result;
 }