Adding ANGLE systrace support

Plumb ANGLE systrace support into Android by setting ANGLE
PlatformMethods struct to required function pointers used by built-in
ANGLE tracing macros.

This includes "#define ATRACE_TAG ATRACE_TAG_GRAPHICS" so that these
markers will fall under the "gfx" class of systrace.

This requires mirroring new header, Platform.h, from ANGLE.

Added AnglePlatformImpl class with static functions that are assigned
into PlatformMethods struct that's passed to ANGLE. This lives in new
egl_angle_platform.h/cpp files. Since we're moving to ANGLE as default
long-term I think it makes sense to have this file live in EGL dir
where I put it.

Currently only defining the functions that we needs to support systrace
through existing ANGLE PlatformMethods. Could potentially expand this
to define more.

Test: build and flash device, run app w/ ANGLE enabled, systrace
Change-Id: I3f0812e8a7554768bbecc3e94feac6559ce17bb2
(cherry picked from commit b032494f6ce813323e79a55a0caa216997fe6a5d)
diff --git a/opengl/libs/Android.bp b/opengl/libs/Android.bp
index d43c164..2a6dee4 100644
--- a/opengl/libs/Android.bp
+++ b/opengl/libs/Android.bp
@@ -143,6 +143,7 @@
         "EGL/egl.cpp",
         "EGL/eglApi.cpp",
         "EGL/Loader.cpp",
+        "EGL/egl_angle_platform.cpp",
     ],
     shared_libs: [
         "libvndksupport",
diff --git a/opengl/libs/EGL/egl_angle_platform.cpp b/opengl/libs/EGL/egl_angle_platform.cpp
new file mode 100644
index 0000000..7e0175a
--- /dev/null
+++ b/opengl/libs/EGL/egl_angle_platform.cpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if defined(__ANDROID__)
+
+#include "egl_angle_platform.h"
+#include <time.h>
+
+#include <log/log.h>
+
+namespace angle {
+
+GetDisplayPlatformFunc AnglePlatformImpl::angleGetDisplayPlatform = nullptr;
+ResetDisplayPlatformFunc AnglePlatformImpl::angleResetDisplayPlatform = nullptr;
+// Initialize start time
+time_t AnglePlatformImpl::startTime = time(nullptr);
+
+void AnglePlatformImpl::assignAnglePlatformMethods(PlatformMethods* platformMethods) {
+    platformMethods->addTraceEvent = addTraceEvent;
+    platformMethods->getTraceCategoryEnabledFlag = getTraceCategoryEnabledFlag;
+    platformMethods->monotonicallyIncreasingTime = monotonicallyIncreasingTime;
+    platformMethods->logError = logError;
+    platformMethods->logWarning = logWarning;
+    platformMethods->logInfo = logInfo;
+}
+
+const unsigned char* AnglePlatformImpl::getTraceCategoryEnabledFlag(PlatformMethods* /*platform*/,
+                                                                    const char* /*categoryName*/) {
+    // Returning ptr to 'g' (non-zero) to ALWAYS enable tracing initially.
+    // This ptr is what will be passed into "category_group_enabled" of addTraceEvent
+    static const unsigned char traceEnabled = 'g';
+    return &traceEnabled;
+}
+
+double AnglePlatformImpl::monotonicallyIncreasingTime(PlatformMethods* /*platform*/) {
+    return difftime(time(nullptr), startTime);
+}
+
+void AnglePlatformImpl::logError(PlatformMethods* /*platform*/, const char* errorMessage) {
+    ALOGE("ANGLE Error:%s", errorMessage);
+}
+
+void AnglePlatformImpl::logWarning(PlatformMethods* /*platform*/, const char* warningMessage) {
+    ALOGW("ANGLE Warn:%s", warningMessage);
+}
+
+void AnglePlatformImpl::logInfo(PlatformMethods* /*platform*/, const char* infoMessage) {
+    ALOGD("ANGLE Info:%s", infoMessage);
+}
+
+TraceEventHandle AnglePlatformImpl::addTraceEvent(
+        PlatformMethods* /**platform*/, char phase, const unsigned char* /*category_group_enabled*/,
+        const char* name, unsigned long long /*id*/, double /*timestamp*/, int /*num_args*/,
+        const char** /*arg_names*/, const unsigned char* /*arg_types*/,
+        const unsigned long long* /*arg_values*/, unsigned char /*flags*/) {
+    switch (phase) {
+        case 'B': {
+            ATRACE_BEGIN(name);
+            break;
+        }
+        case 'E': {
+            ATRACE_END();
+            break;
+        }
+        case 'I': {
+            ATRACE_NAME(name);
+            break;
+        }
+        default:
+            // Could handle other event types here
+            break;
+    }
+    // Return any non-zero handle to avoid assert in ANGLE
+    TraceEventHandle result = 1.0;
+    return result;
+}
+
+}; // namespace angle
+
+#endif // __ANDROID__
diff --git a/opengl/libs/EGL/egl_angle_platform.h b/opengl/libs/EGL/egl_angle_platform.h
new file mode 100644
index 0000000..7c6c8ed
--- /dev/null
+++ b/opengl/libs/EGL/egl_angle_platform.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#if defined(__ANDROID__)
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#include <EGL/Platform.h>
+#pragma GCC diagnostic pop
+
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
+#include "egl_trace.h"
+
+namespace angle {
+
+class AnglePlatformImpl {
+public:
+    static void assignAnglePlatformMethods(PlatformMethods* platformMethods);
+    static GetDisplayPlatformFunc angleGetDisplayPlatform;
+    static ResetDisplayPlatformFunc angleResetDisplayPlatform;
+
+private:
+    static time_t startTime;
+    static const unsigned char* getTraceCategoryEnabledFlag(PlatformMethods* /*platform*/,
+                                                            const char* /*categoryName*/);
+    static double monotonicallyIncreasingTime(PlatformMethods* /*platform*/);
+    static void logError(PlatformMethods* /*platform*/, const char* errorMessage);
+    static void logWarning(PlatformMethods* /*platform*/, const char* warningMessage);
+    static void logInfo(PlatformMethods* /*platform*/, const char* infoMessage);
+    static TraceEventHandle addTraceEvent(PlatformMethods* /**platform*/, char phase,
+                                          const unsigned char* /*category_group_enabled*/,
+                                          const char* name, unsigned long long /*id*/,
+                                          double /*timestamp*/, int /*num_args*/,
+                                          const char** /*arg_names*/,
+                                          const unsigned char* /*arg_types*/,
+                                          const unsigned long long* /*arg_values*/,
+                                          unsigned char /*flags*/);
+};
+
+}; // namespace angle
+
+#endif // __ANDROID__
diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp
index d1635b7..d452a6c 100644
--- a/opengl/libs/EGL/egl_display.cpp
+++ b/opengl/libs/EGL/egl_display.cpp
@@ -24,12 +24,16 @@
 #include <EGL/eglext_angle.h>
 #include <private/EGL/display.h>
 
+#include <cutils/properties.h>
+#include "Loader.h"
+#include "egl_angle_platform.h"
 #include "egl_cache.h"
 #include "egl_object.h"
 #include "egl_tls.h"
-#include "egl_trace.h"
-#include "Loader.h"
-#include <cutils/properties.h>
+
+#include <android/dlext.h>
+#include <dlfcn.h>
+#include <graphicsenv/GraphicsEnv.h>
 
 #include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
 #include <configstore/Utils.h>
@@ -196,6 +200,43 @@
     attrs.push_back(EGL_FALSE);
 }
 
+// Initialize function ptrs for ANGLE PlatformMethods struct, used for systrace
+bool initializeAnglePlatform(EGLDisplay dpy) {
+    // Since we're inside libEGL, use dlsym to lookup fptr for ANGLEGetDisplayPlatform
+    android_namespace_t* ns = android_getAngleNamespace();
+    const android_dlextinfo dlextinfo = {
+            .flags = ANDROID_DLEXT_USE_NAMESPACE,
+            .library_namespace = ns,
+    };
+    void* so = android_dlopen_ext("libEGL_angle.so", RTLD_LOCAL | RTLD_NOW, &dlextinfo);
+    angle::AnglePlatformImpl::angleGetDisplayPlatform =
+            reinterpret_cast<angle::GetDisplayPlatformFunc>(dlsym(so, "ANGLEGetDisplayPlatform"));
+
+    if (!angle::AnglePlatformImpl::angleGetDisplayPlatform) {
+        ALOGE("dlsym lookup of ANGLEGetDisplayPlatform in libEGL_angle failed!");
+        return false;
+    }
+
+    angle::AnglePlatformImpl::angleResetDisplayPlatform =
+            reinterpret_cast<angle::ResetDisplayPlatformFunc>(
+                    eglGetProcAddress("ANGLEResetDisplayPlatform"));
+
+    angle::PlatformMethods* platformMethods = nullptr;
+    if (!((angle::AnglePlatformImpl::angleGetDisplayPlatform)(dpy, angle::g_PlatformMethodNames,
+                                                              angle::g_NumPlatformMethods, nullptr,
+                                                              &platformMethods))) {
+        ALOGE("ANGLEGetDisplayPlatform call failed!");
+        return false;
+    }
+    if (platformMethods) {
+        angle::AnglePlatformImpl::assignAnglePlatformMethods(platformMethods);
+    } else {
+        ALOGE("In initializeAnglePlatform() platformMethods struct ptr is NULL. Not assigning "
+              "tracing function ptrs!");
+    }
+    return true;
+}
+
 static EGLDisplay getDisplayAngle(EGLNativeDisplayType display, egl_connection_t* const cnx) {
     EGLDisplay dpy = EGL_NO_DISPLAY;
 
@@ -216,6 +257,10 @@
                                     reinterpret_cast<void*>(EGL_DEFAULT_DISPLAY), attrs.data());
         if (dpy == EGL_NO_DISPLAY) {
             ALOGE("eglGetPlatformDisplay failed!");
+        } else {
+            if (!initializeAnglePlatform(dpy)) {
+                ALOGE("initializeAnglePlatform failed!");
+            }
         }
     } else {
         ALOGE("eglGetDisplay(%p) failed: Unable to look up eglGetPlatformDisplay from ANGLE",
@@ -417,6 +462,10 @@
 
         egl_connection_t* const cnx = &gEGLImpl;
         if (cnx->dso && disp.state == egl_display_t::INITIALIZED) {
+            // If we're using ANGLE reset any custom DisplayPlatform
+            if (cnx->useAngle && angle::AnglePlatformImpl::angleResetDisplayPlatform) {
+                (angle::AnglePlatformImpl::angleResetDisplayPlatform)(disp.dpy);
+            }
             if (cnx->egl.eglTerminate(disp.dpy) == EGL_FALSE) {
                 ALOGW("eglTerminate(%p) failed (%s)", disp.dpy,
                         egl_tls_t::egl_strerror(cnx->egl.eglGetError()));