EGL: Use frameId instead of framesAgo for frame events.

Using a frameId allows an app to poll for timestamps
from a thread other than the swapping thread.

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

Change-Id: I3faac0513929837982a2e63f7e0d3d529bd28f10
diff --git a/opengl/include/EGL/eglext.h b/opengl/include/EGL/eglext.h
index 027c18d..6485ae5 100644
--- a/opengl/include/EGL/eglext.h
+++ b/opengl/include/EGL/eglext.h
@@ -643,10 +643,12 @@
 #define EGL_DEQUEUE_READY_TIME_ANDROID 0x3156
 #define EGL_READS_DONE_TIME_ANDROID 0x3157
 #ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy, EGLSurface surface, EGLint framesAgo, EGLint numTimestamps, const EGLint *timestamps, EGLnsecsANDROID *values);
+EGLAPI EGLBoolean eglGetNextFrameIdANDROID(EGLDisplay dpy, EGLSurface surface, EGLuint64KHR *frameId);
+EGLAPI EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy, EGLSurface surface, EGLuint64KHR frameId, EGLint numTimestamps, const EGLint *timestamps, EGLnsecsANDROID *values);
 EGLAPI EGLBoolean eglQueryTimestampSupportedANDROID(EGLDisplay dpy, EGLSurface surface, EGLint timestamp);
 #else
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETFRAMETIMESTAMPSANDROID) (EGLDisplay dpy, EGLSurface surface, EGLint framesAgo, EGLint numTimestamps, const EGLint *timestamps, EGLnsecsANDROID *values);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETNEXTFRAMEIDANDROID) (EGLDisplay dpy, EGLSurface surface, EGLuint64KHR *frameId);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETFRAMETIMESTAMPSANDROID) (EGLDisplay dpy, EGLSurface surface, EGLuint64KHR frameId, EGLint numTimestamps, const EGLint *timestamps, EGLnsecsANDROID *values);
 typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYTIMESTAMPSUPPORTEDANDROID) (EGLDisplay dpy, EGLSurface surface, EGLint timestamp);
 #endif
 #endif
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 1672397..c2fc6bd 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -216,6 +216,8 @@
             (__eglMustCastToProperFunctionPointerType)&eglCreateStreamFromFileDescriptorKHR },
 
     // EGL_ANDROID_get_frame_timestamps
+    { "eglGetNextFrameIdANDROID",
+            (__eglMustCastToProperFunctionPointerType)&eglGetNextFrameIdANDROID },
     { "eglGetFrameTimestampsANDROID",
             (__eglMustCastToProperFunctionPointerType)&eglGetFrameTimestampsANDROID },
     { "eglQueryTimestampSupportedANDROID",
@@ -2042,8 +2044,42 @@
     return EGL_FALSE;
 }
 
+EGLBoolean eglGetNextFrameIdANDROID(EGLDisplay dpy, EGLSurface surface,
+            EGLuint64KHR *frameId) {
+    clearError();
+
+    const egl_display_ptr dp = validate_display(dpy);
+    if (!dp) {
+        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+    }
+
+    SurfaceRef _s(dp.get(), surface);
+    if (!_s.get()) {
+        return setError(EGL_BAD_SURFACE, EGL_FALSE);
+    }
+
+    egl_surface_t const * const s = get_surface(surface);
+
+    if (!s->win.get()) {
+        return setError(EGL_BAD_SURFACE, EGL_FALSE);
+    }
+
+    uint64_t nextFrameId = 0;
+    status_t ret = native_window_get_next_frame_id(s->win.get(), &nextFrameId);
+
+    if (ret != NO_ERROR) {
+        // This should not happen. Return an error that is not in the spec
+        // so it's obvious something is very wrong.
+        ALOGE("eglGetNextFrameId: Unexpected error.");
+        return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
+    }
+
+    *frameId = nextFrameId;
+    return EGL_TRUE;
+}
+
 EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy, EGLSurface surface,
-        EGLint framesAgo, EGLint numTimestamps, const EGLint *timestamps,
+        EGLuint64KHR frameId, EGLint numTimestamps, const EGLint *timestamps,
         EGLnsecsANDROID *values)
 {
     clearError();
@@ -2112,7 +2148,7 @@
         }
     }
 
-    status_t ret = native_window_get_frame_timestamps(s->win.get(), framesAgo,
+    status_t ret = native_window_get_frame_timestamps(s->win.get(), frameId,
             requestedPresentTime, acquireTime, latchTime, firstRefreshStartTime,
             lastRefreshStartTime, GLCompositionDoneTime, displayPresentTime,
             displayRetireTime, dequeueReadyTime, releaseTime);
@@ -2129,6 +2165,7 @@
       default:
         // This should not happen. Return an error that is not in the spec
         // so it's obvious something is very wrong.
+        ALOGE("eglGetFrameTimestamps: Unexpected error.");
         return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
     }
 }
diff --git a/opengl/specs/EGL_ANDROID_get_frame_timestamps.txt b/opengl/specs/EGL_ANDROID_get_frame_timestamps.txt
index 7aa0d30..f24d634 100644
--- a/opengl/specs/EGL_ANDROID_get_frame_timestamps.txt
+++ b/opengl/specs/EGL_ANDROID_get_frame_timestamps.txt
@@ -57,9 +57,12 @@
 
 New Procedures and Functions
 
+    EGLBoolean eglGetNextFrameIdANDROID(EGLDisplay dpy, EGLSurface surface,
+            EGLuint64KHR *frameId);
+
     EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy, EGLSurface surface,
-            EGLint framesAgo, EGLint numTimestamps, const EGLint *timestamps,
-            EGLnsecsANDROID *values);
+            EGLuint64KHR frameId, EGLint numTimestamps,
+            const EGLint *timestamps, EGLnsecsANDROID *values);
 
     EGLBoolean eglQueryTimestampSupportedANDROID(EGLDisplay dpy, EGLSurface
             surface, EGLint timestamp);
@@ -95,23 +98,31 @@
 
     The function
 
-        EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy, EGLSurface
-            surface, EGLint framesAgo, EGLint numTimestamps,
+        EGLBoolean eglGetNextFrameIdANDROID(EGLDisplay dpy, EGLSurface surface,
+            EGLuint64KHR *frameId);
+
+    Returns an identifier for the next frame to be swapped. The identifier can
+    be used to correlate a particular eglSwapBuffers with its timestamps in
+    eglGetFrameTimestampsANDROID. If any error is generated, the function will
+    return EGL_FALSE.
+
+    The function
+
+        EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy,
+            EGLSurface surface, EGLuint64KHR frameId, EGLint numTimestamps,
             const EGLint *timestamps, EGLnsecsANDROID *values);
 
-    allows querying various timestamps related to the composition and display of
-    a window surface.
+    allows querying various timestamps related to the composition and display
+    of specific frames of a window surface.
 
-    The framesAgo parameter indicates how many frames before the last queued
-    frame to query. So a value of zero would indicate that the query is for the
-    last queued frame. Note that the implementation maintains a 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.
+    The frameId indicates which frame to query. The implementation maintains a
+    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.
 
     The eglGetFrameTimestampsANDROID function takes an array of timestamps to
     query and returns timestamps in the corresponding indices of the values
@@ -175,3 +186,6 @@
     - Add EGL_COMPOSITION_LATCH_TIME_ANDROID,
       EGL_LAST_COMPOSITION_START_TIME_ANDROID, and
       EGL_DEQUEUE_READY_TIME_ANDROID.
+
+#4 (Brian Anderson, January 10, 2017)
+    - Use an absolute frameId rather than a relative framesAgo.
diff --git a/opengl/specs/README b/opengl/specs/README
index 8a3a7aa..1853214 100644
--- a/opengl/specs/README
+++ b/opengl/specs/README
@@ -1,5 +1,5 @@
 This directory contains OpenGL ES and EGL extension specifications that have
-been or are being defined for Android.  
+been or are being defined for Android.
 
 The table below tracks usage of EGL enumerant values that have been reserved
 for use by Android extensions.