Add support for Atrace and hook into SkEventTracer framework.

This change is a different version of:
https://skia-review.googlesource.com/c/3269/

BUG=skia:

GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=3345

Change-Id: I49d4f2987740d3ad1307f6aba3add0d63a46b22d
Reviewed-on: https://skia-review.googlesource.com/3345
Reviewed-by: Brian Salomon <bsalomon@google.com>
Reviewed-by: Mike Klein <mtklein@chromium.org>
Commit-Queue: Greg Daniel <egdaniel@google.com>
diff --git a/gyp/core.gypi b/gyp/core.gypi
index 0f6c1e3..a435164 100644
--- a/gyp/core.gypi
+++ b/gyp/core.gypi
@@ -21,6 +21,8 @@
         '<(skia_src_path)/core/SkAdvancedTypefaceMetrics.h',
         '<(skia_src_path)/core/SkAlphaRuns.cpp',
         '<(skia_src_path)/core/SkAntiRun.h',
+        '<(skia_src_path)/core/SkATrace.cpp',
+        '<(skia_src_path)/core/SkATrace.h',
         '<(skia_src_path)/core/SkAutoKern.h',
         '<(skia_src_path)/core/SkAutoPixmapStorage.h',
         '<(skia_src_path)/core/SkAutoPixmapStorage.cpp',
diff --git a/src/core/SkATrace.cpp b/src/core/SkATrace.cpp
new file mode 100644
index 0000000..b40795e
--- /dev/null
+++ b/src/core/SkATrace.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkATrace.h"
+
+#include "SkTraceEvent.h"
+
+#ifdef SK_BUILD_FOR_ANDROID
+#include <dlfcn.h>
+#endif
+
+SkATrace::SkATrace() : fBeginSection(nullptr), fEndSection(nullptr), fIsEnabled(nullptr) {
+#ifdef SK_BUILD_FOR_ANDROID
+    if (void* lib = dlopen("libandroid.so", RTLD_NOW | RTLD_LOCAL)) {
+        fBeginSection = (decltype(fBeginSection))dlsym(lib, "ATrace_beginSection");
+        fEndSection = (decltype(fEndSection))dlsym(lib, "ATrace_endSection");
+        fIsEnabled = (decltype(fIsEnabled))dlsym(lib, "ATrace_isEnabled");
+    }
+#endif
+    if (!fIsEnabled) {
+        fIsEnabled = []{ return false; };
+    }
+}
+
+SkEventTracer::Handle SkATrace::addTraceEvent(char phase,
+                                              const uint8_t* categoryEnabledFlag,
+                                              const char* name,
+                                              uint64_t id,
+                                              int numArgs,
+                                              const char** argNames,
+                                              const uint8_t* argTypes,
+                                              const uint64_t* argValues,
+                                              uint8_t flags) {
+    if (fIsEnabled()) {
+        if (TRACE_EVENT_PHASE_COMPLETE == phase ||
+            TRACE_EVENT_PHASE_BEGIN == phase ||
+            TRACE_EVENT_PHASE_INSTANT == phase) {
+            fBeginSection(name);
+        }
+
+        if (TRACE_EVENT_PHASE_END == phase ||
+            TRACE_EVENT_PHASE_INSTANT == phase) {
+            fEndSection();
+        }
+    }
+    return 0;
+}
+
+void SkATrace::updateTraceEventDuration(const uint8_t* categoryEnabledFlag,
+                                        const char* name,
+                                        SkEventTracer::Handle handle) {
+    // This is only ever called from a scoped trace event so we will just end the ATrace section.
+    if (fIsEnabled()) {
+        fEndSection();
+    }
+}
+
+const uint8_t* SkATrace::getCategoryGroupEnabled(const char* name) {
+    // Chrome tracing is setup to not repeatly call this function once it has been initialized. So
+    // we can't use this to do a check for ATrace isEnabled(). Thus we will always return yes here
+    // and then check to see if ATrace is enabled when beginning and ending a section.
+    static uint8_t yes = SkEventTracer::kEnabledForRecording_CategoryGroupEnabledFlags;
+    return &yes;
+}
+
diff --git a/src/core/SkATrace.h b/src/core/SkATrace.h
new file mode 100644
index 0000000..f870c5a
--- /dev/null
+++ b/src/core/SkATrace.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkATrace_DEFINED
+#define SkATrace_DEFINED
+
+#include "SkEventTracer.h"
+
+/**
+ * This class is used to support ATrace in android apps. It hooks into the SkEventTracer system. It
+ * currently supports the macros TRACE_EVENT*, TRACE_EVENT_INSTANT*, and TRANCE_EVENT_BEGIN/END*.
+ * For versions of these calls that take additoinal args and value pairs we currently just drop them
+ * and report only the name. Since ATrace is a simple push and pop system (all traces are fully
+ * nested), if using BEGIN and END you should also make sure your calls are properly nested (i.e. if
+ * startA is before startB, then endB is before endA).
+ */
+class SkATrace : public SkEventTracer {
+public:
+    SkATrace();
+
+    SkEventTracer::Handle addTraceEvent(char phase,
+                                        const uint8_t* categoryEnabledFlag,
+                                        const char* name,
+                                        uint64_t id,
+                                        int numArgs,
+                                        const char** argNames,
+                                        const uint8_t* argTypes,
+                                        const uint64_t* argValues,
+                                        uint8_t flags) override;
+
+
+    void updateTraceEventDuration(const uint8_t* categoryEnabledFlag,
+                                  const char* name,
+                                  SkEventTracer::Handle handle) override;
+
+    const uint8_t* getCategoryGroupEnabled(const char* name) override;
+
+    const char* getCategoryGroupName(const uint8_t* categoryEnabledFlag) override {
+        static const char* category = "skiaATrace";
+        return category;
+    }
+
+private:
+    void (*fBeginSection)(const char*);
+    void (*fEndSection)(void);
+    bool (*fIsEnabled)(void);
+};
+
+#endif
+
diff --git a/tools/viewer/Viewer.cpp b/tools/viewer/Viewer.cpp
index 6f33d2c..99570a2 100644
--- a/tools/viewer/Viewer.cpp
+++ b/tools/viewer/Viewer.cpp
@@ -12,9 +12,11 @@
 #include "SampleSlide.h"
 #include "SKPSlide.h"
 
+#include "SkATrace.h"
 #include "SkCanvas.h"
 #include "SkCommonFlags.h"
 #include "SkDashPathEffect.h"
+#include "SkGraphics.h"
 #include "SkMetaData.h"
 #include "SkOSFile.h"
 #include "SkRandom.h"
@@ -75,6 +77,8 @@
 
 DEFINE_string2(backend, b, "sw", "Backend to use. Allowed values are " BACKENDS_STR ".");
 
+DEFINE_bool(atrace, false, "Enable support for using ATrace. ATrace is only supported on Android.");
+
 const char *kBackendTypeStrings[sk_app::Window::kBackendTypeCount] = {
     " [OpenGL]",
 #ifdef SK_VULKAN
@@ -123,6 +127,7 @@
     , fZoomLevel(0.0f)
     , fZoomScale(SK_Scalar1)
 {
+    SkGraphics::Init();
     memset(fMeasurements, 0, sizeof(fMeasurements));
 
     SkDebugf("Command line arguments: ");
@@ -133,6 +138,10 @@
 
     SkCommandLineFlags::Parse(argc, argv);
 
+    if (FLAGS_atrace) {
+        SkEventTracer::SetInstance(new SkATrace());
+    }
+
     fBackendType = get_backend_type(FLAGS_backend[0]);
     fWindow = Window::CreateNativeWindow(platformData);
     fWindow->attach(fBackendType, DisplayParams());
diff --git a/tools/viewer/sk_app/android/main_android.cpp b/tools/viewer/sk_app/android/main_android.cpp
index ee2dab5..9c3316f 100644
--- a/tools/viewer/sk_app/android/main_android.cpp
+++ b/tools/viewer/sk_app/android/main_android.cpp
@@ -28,6 +28,9 @@
         "viewer",
         "--skps",
         "/data/local/tmp/skp",
+        // TODO: figure out how to use am start with extra params to pass in additional arguments at
+        // runtime
+        // "--atrace",
     };
 
     std::unique_ptr<Application> vkApp(Application::Create(SK_ARRAY_COUNT(gCmdLine),
diff --git a/tools/viewer/sk_app/android/surface_glue_android.cpp b/tools/viewer/sk_app/android/surface_glue_android.cpp
index 886fcd0..178f04d 100644
--- a/tools/viewer/sk_app/android/surface_glue_android.cpp
+++ b/tools/viewer/sk_app/android/surface_glue_android.cpp
@@ -181,7 +181,16 @@
     ALooper_addFd(looper, skiaAndroidApp->fPipes[0], LOOPER_ID_MESSAGEPIPE, ALOOPER_EVENT_INPUT,
                   message_callback, skiaAndroidApp);
 
-    skiaAndroidApp->fApp = Application::Create(0, nullptr, skiaAndroidApp);
+    static const char* gCmdLine[] = {
+        "viewer",
+        // TODO: figure out how to use am start with extra params to pass in additional arguments at
+        // runtime. Or better yet make an in app switch to enable
+        // "--atrace",
+    };
+
+    skiaAndroidApp->fApp = Application::Create(SK_ARRAY_COUNT(gCmdLine),
+                                               const_cast<char**>(gCmdLine),
+                                               skiaAndroidApp);
 
     while (true) {
         const int ident = ALooper_pollAll(0, nullptr, nullptr, nullptr);