sdk: Add example code

Add SDK example code imported from https://github.com/skyostil/perfetto-sdk-example

Change-Id: Ic3a478091575d7129e39114d4b0c4280137b5f40
diff --git a/examples/README.md b/examples/README.md
new file mode 100644
index 0000000..cc39a16
--- /dev/null
+++ b/examples/README.md
@@ -0,0 +1,5 @@
+# Perfetto examples
+
+This directory contains examples for integrating Perfetto into your projects.
+
+- Example applications using the [Perfetto SDK](sdk/README.md).
diff --git a/examples/sdk/CMakeLists.txt b/examples/sdk/CMakeLists.txt
new file mode 100644
index 0000000..fc13851
--- /dev/null
+++ b/examples/sdk/CMakeLists.txt
@@ -0,0 +1,46 @@
+# Copyright (C) 2020 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.
+
+cmake_minimum_required(VERSION 3.13)
+project(perfetto-sdk-example)
+
+set(CMAKE_CXX_STANDARD 11)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+
+find_package(Threads)
+
+# Define a static library for Perfetto. In this example, we expect the SDK
+# (perfetto.cc and perfetto.h) to live in the top level sdk/ directory.
+include_directories(../../sdk)
+add_library(perfetto STATIC ../../sdk/perfetto.cc)
+
+# Link the library to the main executables.
+add_executable(example example.cc trace_categories.cc)
+add_executable(example_system_wide example_system_wide.cc
+               trace_categories.cc)
+add_executable(example_custom_data_source example_custom_data_source.cc)
+
+target_link_libraries(example perfetto
+                      ${CMAKE_THREAD_LIBS_INIT})
+target_link_libraries(example_system_wide perfetto
+                      ${CMAKE_THREAD_LIBS_INIT})
+target_link_libraries(example_custom_data_source perfetto
+                      ${CMAKE_THREAD_LIBS_INIT})
+
+# On Android we also need the logging library.
+if (ANDROID)
+  target_link_libraries(example log)
+  target_link_libraries(example_system_wide log)
+  target_link_libraries(example_custom_data_source log)
+endif (ANDROID)
\ No newline at end of file
diff --git a/examples/sdk/README.md b/examples/sdk/README.md
new file mode 100644
index 0000000..2fba4b6
--- /dev/null
+++ b/examples/sdk/README.md
@@ -0,0 +1,129 @@
+# Perfetto SDK example project
+
+This directory contains an example project using the [Perfetto
+SDK](https://perfetto.dev/docs/instrumentation/tracing-sdk). It demonstrates
+how to instrument your application with track events to give more context in
+developing, debugging and performance analysis.
+
+Dependencies:
+
+- [CMake](https://cmake.org/)
+- C++11
+
+## Building
+
+First, check out the latest Perfetto release:
+
+```bash
+git clone https://android.googlesource.com/platform/external/perfetto -b v4.0
+```
+
+Then, build using CMake:
+
+```bash
+cd perfetto/examples/sdk
+cmake -B build
+cmake --build build
+```
+
+## Track event example
+
+The [basic example](example.cc) shows how to instrument an app with track
+events. Run it with:
+
+```bash
+build/example
+```
+
+The program will create a trace file in `example.pftrace`, which can be
+directly opened in the [Perfetto UI](https://ui.perfetto.dev). The result
+should look like this:
+
+![Example trace loaded in the Perfetto UI](
+  example.png "Example trace loaded in the Perfetto UI")
+
+## System-wide example
+
+While the above example only records events from the program itself, with
+Perfetto it's also possible to combine app trace events with system-wide
+profiling data (e.g., ftrace on Linux). The repository has a [second
+example](example_system_wide.cc) which demonstrates this on Android.
+
+Requirements:
+- [Android NDK](https://developer.android.com/ndk)
+- A device running Android Pie or newer
+
+> Tip: It's also possible to sideload Perfetto on pre-Pie Android devices.
+> See the [build
+> instructions](https://perfetto.dev/docs/contributing/build-instructions).
+
+To build:
+
+```bash
+export NDK=/path/to/ndk
+cmake -DCMAKE_TOOLCHAIN_FILE=$NDK/build/cmake/android.toolchain.cmake \
+      -B build_android
+cmake --build build_android
+```
+
+Next, plug in an Android device into a USB port, download the example and run
+it while simultaneously recording a trace using the `perfetto` command line
+tool:
+
+```bash
+adb push build_android/example_system_wide ../system_wide_trace_cfg.pbtxt \
+         /data/local/tmp/
+adb shell "\
+    cd /data/local/tmp; \
+    rm -f /data/misc/perfetto-traces/example_system_wide.pftrace; \
+    cat system_wide_trace_cfg.pbtxt | \
+        perfetto --config - --txt --background \
+                 -o /data/misc/perfetto-traces/example_system_wide.pftrace; \
+    ./example_system_wide"
+```
+
+Finally, retrieve the resulting trace:
+
+```bash
+adb pull /data/misc/perfetto-traces/example_system_wide.pftrace
+```
+
+When opened in the Perfetto UI, the trace now shows additional contextual
+information such as CPU frequencies and kernel scheduler information.
+
+![Example system wide-trace loaded in the Perfetto UI](
+  example_system_wide.png "Example system-wide trace in the Perfetto UI")
+
+> Tip: You can generate a new trace config with additional data sources using
+> the [Perfetto UI](https://ui.perfetto.dev/#!/record) and replace
+> `system_wide_trace_cfg.pbtxt` with the [generated config](
+> https://ui.perfetto.dev/#!/record?p=instructions).
+
+## Custom data source example
+
+The [final example](example_custom_data_source.cc) shows how to use an
+application defined data source to emit custom, strongly typed data into a
+trace. Run it with:
+
+```bash
+build/example_custom_data_source
+```
+
+The program generates a trace file in `example_custom_data_source.pftrace`,
+which we can examine using Perfetto's `trace_to_text` tool to show the trace
+packet written by the custom data source:
+
+```bash
+trace_to_text text example_custom_data_source.pftrace
+...
+packet {
+  trusted_uid: 0
+  timestamp: 42
+  trusted_packet_sequence_id: 2
+  previous_packet_dropped: true
+  for_testing {
+    str: "Hello world!"
+  }
+}
+...
+```
\ No newline at end of file
diff --git a/examples/sdk/example.cc b/examples/sdk/example.cc
new file mode 100644
index 0000000..a1898d2
--- /dev/null
+++ b/examples/sdk/example.cc
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+// This example demonstrates in-process tracing with Perfetto.
+
+#include "trace_categories.h"
+
+#include <chrono>
+#include <fstream>
+#include <thread>
+
+void InitializePerfetto() {
+  perfetto::TracingInitArgs args;
+  // The backends determine where trace events are recorded. For this example we
+  // are going to use the in-process tracing service, which only includes in-app
+  // events.
+  args.backends = perfetto::kInProcessBackend;
+
+  perfetto::Tracing::Initialize(args);
+  perfetto::TrackEvent::Register();
+}
+
+std::unique_ptr<perfetto::TracingSession> StartTracing() {
+  // The trace config defines which types of data sources are enabled for
+  // recording. In this example we just need the "track_event" data source,
+  // which corresponds to the TRACE_EVENT trace points.
+  perfetto::TraceConfig cfg;
+  cfg.add_buffers()->set_size_kb(1024);
+  auto* ds_cfg = cfg.add_data_sources()->mutable_config();
+  ds_cfg->set_name("track_event");
+
+  auto tracing_session = perfetto::Tracing::NewTrace();
+  tracing_session->Setup(cfg);
+  tracing_session->StartBlocking();
+  return tracing_session;
+}
+
+void StopTracing(std::unique_ptr<perfetto::TracingSession> tracing_session) {
+  // Make sure the last event is closed for this example.
+  perfetto::TrackEvent::Flush();
+
+  // Stop tracing and read the trace data.
+  tracing_session->StopBlocking();
+  std::vector<char> trace_data(tracing_session->ReadTraceBlocking());
+
+  // Write the result into a file.
+  // Note: To save memory with longer traces, you can tell Perfetto to write
+  // directly into a file by passing a file descriptor into Setup() above.
+  std::ofstream output;
+  output.open("example.pftrace", std::ios::out | std::ios::binary);
+  output.write(&trace_data[0], trace_data.size());
+  output.close();
+}
+
+void DrawPlayer(int player_number) {
+  TRACE_EVENT("rendering", "DrawPlayer", "player_number", player_number);
+  // Sleep to simulate a long computation.
+  std::this_thread::sleep_for(std::chrono::milliseconds(500));
+}
+
+void DrawGame() {
+  TRACE_EVENT("rendering", "DrawGame");
+  DrawPlayer(1);
+  DrawPlayer(2);
+}
+
+int main(int, const char**) {
+  InitializePerfetto();
+  auto tracing_session = StartTracing();
+
+  // Simulate some work that emits trace events.
+  DrawGame();
+
+  StopTracing(std::move(tracing_session));
+  return 0;
+}
diff --git a/examples/sdk/example.png b/examples/sdk/example.png
new file mode 100644
index 0000000..4246216
--- /dev/null
+++ b/examples/sdk/example.png
Binary files differ
diff --git a/examples/sdk/example_custom_data_source.cc b/examples/sdk/example_custom_data_source.cc
new file mode 100644
index 0000000..2d475c1
--- /dev/null
+++ b/examples/sdk/example_custom_data_source.cc
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+// This example demonstrates a custom tracing data source.
+
+#include <perfetto.h>
+
+#include <fstream>
+#include <thread>
+
+// The definition of our custom data source. Instances of this class will be
+// automatically created and destroyed by Perfetto.
+class CustomDataSource : public perfetto::DataSource<CustomDataSource> {
+ public:
+  void OnSetup(const SetupArgs&) override {
+    // Use this callback to apply any custom configuration to your data source
+    // based on the TraceConfig in SetupArgs.
+  }
+
+  // Optional callbacks for tracking the lifecycle of the data source.
+  void OnStart(const StartArgs&) override {}
+  void OnStop(const StopArgs&) override {}
+};
+
+PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS(CustomDataSource);
+PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(CustomDataSource);
+
+void InitializePerfetto() {
+  perfetto::TracingInitArgs args;
+  // The backends determine where trace events are recorded. For this example we
+  // are going to use the in-process tracing service, which only includes in-app
+  // events.
+  args.backends = perfetto::kInProcessBackend;
+  perfetto::Tracing::Initialize(args);
+
+  // Register our custom data source. Only the name is required, but other
+  // properties can be advertised too.
+  perfetto::DataSourceDescriptor dsd;
+  dsd.set_name("com.example.custom_data_source");
+  CustomDataSource::Register(dsd);
+}
+
+std::unique_ptr<perfetto::TracingSession> StartTracing() {
+  // The trace config defines which types of data sources are enabled for
+  // recording. In this example we enable the custom data source we registered
+  // above.
+  perfetto::TraceConfig cfg;
+  cfg.add_buffers()->set_size_kb(1024);
+  auto* ds_cfg = cfg.add_data_sources()->mutable_config();
+  ds_cfg->set_name("com.example.custom_data_source");
+
+  auto tracing_session = perfetto::Tracing::NewTrace();
+  tracing_session->Setup(cfg);
+  tracing_session->StartBlocking();
+  return tracing_session;
+}
+
+void StopTracing(std::unique_ptr<perfetto::TracingSession> tracing_session) {
+  // Flush to make sure the last written event ends up in the trace.
+  CustomDataSource::Trace(
+      [](CustomDataSource::TraceContext ctx) { ctx.Flush(); });
+
+  // Stop tracing and read the trace data.
+  tracing_session->StopBlocking();
+  std::vector<char> trace_data(tracing_session->ReadTraceBlocking());
+
+  // Write the result into a file.
+  // Note: To save memory with longer traces, you can tell Perfetto to write
+  // directly into a file by passing a file descriptor into Setup() above.
+  std::ofstream output;
+  output.open("example_custom_data_source.pftrace",
+              std::ios::out | std::ios::binary);
+  output.write(&trace_data[0], trace_data.size());
+  output.close();
+}
+
+int main(int, const char**) {
+  InitializePerfetto();
+  auto tracing_session = StartTracing();
+
+  // Write an event using our custom data source.
+  CustomDataSource::Trace([](CustomDataSource::TraceContext ctx) {
+    auto packet = ctx.NewTracePacket();
+    packet->set_timestamp(42);
+    packet->set_for_testing()->set_str("Hello world!");
+  });
+
+  StopTracing(std::move(tracing_session));
+  return 0;
+}
diff --git a/examples/sdk/example_system_wide.cc b/examples/sdk/example_system_wide.cc
new file mode 100644
index 0000000..f755d37
--- /dev/null
+++ b/examples/sdk/example_system_wide.cc
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+// This example demonstrates system-wide tracing with Perfetto.
+
+#include "trace_categories.h"
+
+#include <chrono>
+#include <fstream>
+#include <thread>
+
+void InitializePerfetto() {
+  perfetto::TracingInitArgs args;
+  // The backends determine where trace events are recorded. For this example we
+  // are going to use the system-wide tracing service, so that we can see our
+  // app's events in context with system profiling information.
+  args.backends = perfetto::kSystemBackend;
+
+  perfetto::Tracing::Initialize(args);
+  perfetto::TrackEvent::Register();
+}
+
+void WaitForTracingStart() {
+  PERFETTO_LOG("Waiting for tracing to start...");
+  while (!TRACE_EVENT_CATEGORY_ENABLED("rendering")) {
+    std::this_thread::sleep_for(std::chrono::milliseconds(100));
+  }
+  PERFETTO_LOG("Tracing started");
+}
+
+void DrawPlayer(int player_number) {
+  TRACE_EVENT("rendering", "DrawPlayer", "player_number", player_number);
+  // Sleep to simulate a long computation.
+  std::this_thread::sleep_for(std::chrono::milliseconds(500));
+}
+
+void DrawGame() {
+  TRACE_EVENT("rendering", "DrawGame");
+  DrawPlayer(1);
+  DrawPlayer(2);
+}
+
+int main(int, const char**) {
+  InitializePerfetto();
+  WaitForTracingStart();
+
+  // Simulate some work that emits trace events.
+  // Note that we don't start and stop tracing here; for system-wide tracing
+  // this needs to be done through the "perfetto" command line tool or the
+  // Perfetto UI (https://ui.perfetto.dev).
+  DrawGame();
+
+  // Make sure the last event is closed for this example.
+  perfetto::TrackEvent::Flush();
+
+  return 0;
+}
diff --git a/examples/sdk/example_system_wide.png b/examples/sdk/example_system_wide.png
new file mode 100644
index 0000000..7aa4dbc
--- /dev/null
+++ b/examples/sdk/example_system_wide.png
Binary files differ
diff --git a/examples/sdk/system_wide_trace_cfg.pbtxt b/examples/sdk/system_wide_trace_cfg.pbtxt
new file mode 100644
index 0000000..c9b5bdd
--- /dev/null
+++ b/examples/sdk/system_wide_trace_cfg.pbtxt
@@ -0,0 +1,47 @@
+buffers: {
+    size_kb: 8960
+    fill_policy: DISCARD
+}
+data_sources: {
+    config {
+        name: "linux.process_stats"
+        target_buffer: 1
+        process_stats_config {
+            scan_all_processes_on_start: true
+        }
+    }
+}
+data_sources: {
+    config {
+        name: "linux.sys_stats"
+        sys_stats_config {
+            stat_period_ms: 1000
+            stat_counters: STAT_CPU_TIMES
+            stat_counters: STAT_FORK_COUNT
+        }
+    }
+}
+data_sources: {
+    config {
+        name: "linux.ftrace"
+        ftrace_config {
+            ftrace_events: "sched/sched_switch"
+            ftrace_events: "power/suspend_resume"
+            ftrace_events: "sched/sched_wakeup"
+            ftrace_events: "sched/sched_wakeup_new"
+            ftrace_events: "sched/sched_waking"
+            ftrace_events: "power/cpu_frequency"
+            ftrace_events: "power/cpu_idle"
+            ftrace_events: "sched/sched_process_exit"
+            ftrace_events: "sched/sched_process_free"
+            ftrace_events: "task/task_newtask"
+            ftrace_events: "task/task_rename"
+        }
+    }
+}
+data_sources: {
+    config {
+        name: "track_event"
+    }
+}
+duration_ms: 5000
diff --git a/examples/sdk/trace_categories.cc b/examples/sdk/trace_categories.cc
new file mode 100644
index 0000000..cce90f8
--- /dev/null
+++ b/examples/sdk/trace_categories.cc
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#include "trace_categories.h"
+
+// Reserves internal static storage for our tracing categories.
+PERFETTO_TRACK_EVENT_STATIC_STORAGE();
\ No newline at end of file
diff --git a/examples/sdk/trace_categories.h b/examples/sdk/trace_categories.h
new file mode 100644
index 0000000..c2dd852
--- /dev/null
+++ b/examples/sdk/trace_categories.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#ifndef TRACE_CATEGORIES_H
+#define TRACE_CATEGORIES_H
+
+#include <perfetto.h>
+
+// The set of track event categories that the example is using.
+PERFETTO_DEFINE_CATEGORIES(
+    perfetto::Category("rendering")
+        .SetDescription("Rendering and graphics events"),
+    perfetto::Category("network.debug")
+        .SetTags("debug")
+        .SetDescription("Verbose network events"),
+    perfetto::Category("audio.latency")
+        .SetTags("verbose")
+        .SetDescription("Detailed audio latency metrics"));
+
+#endif  // TRACE_CATEGORIES_H